diff --git a/Dockerfile b/Dockerfile index b131356..755954d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM wiiuenv/devkitppc:20211229 -COPY --from=wiiuenv/wiiumodulesystem:20220123 /artifacts $DEVKITPRO +COPY --from=wiiuenv/wiiumodulesystem:20220127 /artifacts $DEVKITPRO COPY --from=wiiuenv/wiiupluginsystem:20220123 /artifacts $DEVKITPRO COPY --from=wiiuenv/libfunctionpatcher:20210924 /artifacts $DEVKITPRO COPY --from=wiiuenv/libmappedmemory:20210924 /artifacts $DEVKITPRO diff --git a/source/PluginManagement.cpp b/source/PluginManagement.cpp index dea0951..e4b3d85 100644 --- a/source/PluginManagement.cpp +++ b/source/PluginManagement.cpp @@ -14,7 +14,7 @@ #include "hooks.h" #include "globals.h" -bool PluginManagement::doRelocation(const std::vector> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolinID) { +bool PluginManagement::doRelocation(const std::vector> &relocData, relocation_trampoline_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolineID) { std::map moduleHandleCache; for (auto const &cur: relocData) { uint32_t functionAddress = 0; @@ -53,23 +53,23 @@ bool PluginManagement::doRelocation(const std::vectorgetType(), cur->getOffset(), cur->getAddend(), (uint32_t) cur->getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT, trampolinID)) { + if (!ElfUtils::elfLinkOne(cur->getType(), cur->getOffset(), cur->getAddend(), (uint32_t) cur->getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT, trampolineID)) { DEBUG_FUNCTION_LINE("Relocation failed"); return false; } } - DCFlushRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t)); - ICInvalidateRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t)); + DCFlushRange(tramp_data, tramp_length * sizeof(relocation_trampoline_entry_t)); + ICInvalidateRange(tramp_data, tramp_length * sizeof(relocation_trampoline_entry_t)); return true; } -void PluginManagement::doRelocations(const std::vector> &plugins, relocation_trampolin_entry_t *trampData, uint32_t tramp_size) { +void PluginManagement::doRelocations(const std::vector> &plugins, relocation_trampoline_entry_t *trampData, uint32_t tramp_size) { for (auto &pluginContainer: plugins) { DEBUG_FUNCTION_LINE_VERBOSE("Doing relocations for plugin: %s", pluginContainer->getMetaInformation()->getName().c_str()); - if (!PluginManagement::doRelocation(pluginContainer->getPluginInformation()->getRelocationDataList(), trampData, tramp_size, pluginContainer->getPluginInformation()->getTrampolinId())) { + if (!PluginManagement::doRelocation(pluginContainer->getPluginInformation()->getRelocationDataList(), trampData, tramp_size, pluginContainer->getPluginInformation()->getTrampolineId())) { DEBUG_FUNCTION_LINE("Relocation failed"); } } @@ -145,7 +145,7 @@ void PluginManagement::unloadPlugins(plugin_information_t *pluginInformation, ME for (uint32_t i = 0; i < gTrampolineDataSize; i++) { auto trampoline = &(gTrampolineData[i]); - if (trampoline->id == plugin->info.trampolinId) { + if (trampoline->id == plugin->info.trampolineId) { trampoline->id = 0; trampoline->status = RELOC_TRAMP_FREE; } @@ -189,7 +189,7 @@ void PluginManagement::PatchFunctionsAndCallHooks(plugin_information_t *pluginIn } std::vector> -PluginManagement::loadPlugins(const std::vector> &pluginList, MEMHeapHandle heapHandle, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length) { +PluginManagement::loadPlugins(const std::vector> &pluginList, MEMHeapHandle heapHandle, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length) { std::vector> plugins; for (auto &pluginData: pluginList) { @@ -206,7 +206,7 @@ PluginManagement::loadPlugins(const std::vector> &pl } uint32_t trampolineID = 0; for (auto &pluginContainer: plugins) { - auto info = PluginInformationFactory::load(pluginContainer->getPluginData(), heapHandle, trampolin_data, trampolin_data_length, trampolineID++); + auto info = PluginInformationFactory::load(pluginContainer->getPluginData(), heapHandle, trampoline_data, trampoline_data_length, trampolineID++); if (!info) { DEBUG_FUNCTION_LINE("Failed to load Plugin %s", pluginContainer->getMetaInformation()->getName().c_str()); continue; diff --git a/source/PluginManagement.h b/source/PluginManagement.h index 82ddc95..009fc48 100644 --- a/source/PluginManagement.h +++ b/source/PluginManagement.h @@ -6,7 +6,7 @@ class PluginManagement { public: - static void doRelocations(const std::vector> &plugins, relocation_trampolin_entry_t *trampData, uint32_t tramp_size); + static void doRelocations(const std::vector> &plugins, relocation_trampoline_entry_t *trampData, uint32_t tramp_size); static void memsetBSS(const std::vector> &plugins); @@ -14,11 +14,12 @@ public: static void PatchFunctionsAndCallHooks(plugin_information_t *gPluginInformation); - static bool doRelocation(const std::vector> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolinID); + static bool doRelocation(const std::vector> &relocData, relocation_trampoline_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolineID); static void unloadPlugins(plugin_information_t *pluginInformation, MEMHeapHandle pluginHeap, BOOL freePluginData); - static std::vector> loadPlugins(const std::vector> &pluginList, MEMHeapHandle pHeader, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length); + static std::vector> + loadPlugins(const std::vector> &pluginList, MEMHeapHandle pHeader, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length); static void RestorePatches(plugin_information_t *pluginInformation, BOOL pluginOnly); }; \ No newline at end of file diff --git a/source/common/plugin_defines.h b/source/common/plugin_defines.h index 2114fdf..7f3a06e 100644 --- a/source/common/plugin_defines.h +++ b/source/common/plugin_defines.h @@ -78,7 +78,7 @@ struct plugin_info_t { function_replacement_data_t functions[MAXIMUM_FUNCTION_PER_PLUGIN]{}; // Replacement information for each function. uint32_t number_used_hooks{}; // Number of used hooks. Maximum is MAXIMUM_HOOKS_PER_PLUGIN replacement_data_hook_t hooks[MAXIMUM_HOOKS_PER_PLUGIN]; // Replacement information for each function. - uint8_t trampolinId{}; + uint8_t trampolineId{}; plugin_function_symbol_data_t * function_symbol_data = nullptr; uint32_t number_function_symbol_data = 0; void * allocatedTextMemoryAddress = nullptr; diff --git a/source/globals.cpp b/source/globals.cpp index 2d9a160..cd35bd0 100644 --- a/source/globals.cpp +++ b/source/globals.cpp @@ -5,7 +5,7 @@ MEMHeapHandle gPluginInformationHeap __attribute__((section(".data"))) = nullptr plugin_information_t *gPluginInformation __attribute__((section(".data"))) = nullptr; plugin_information_on_reload_t gLinkOnReload __attribute__((section(".data"))); module_information_t *gModuleData __attribute__((section(".data"))) = nullptr; -relocation_trampolin_entry_t *gTrampolineData __attribute__((section(".data"))) = nullptr; +relocation_trampoline_entry_t *gTrampolineData __attribute__((section(".data"))) = nullptr; uint32_t gPluginDataHeapSize = 0; uint32_t gPluginInformationHeapSize = 0; diff --git a/source/globals.h b/source/globals.h index d50542c..7a0db3a 100644 --- a/source/globals.h +++ b/source/globals.h @@ -13,7 +13,7 @@ extern uint32_t gPluginDataHeapSize; extern uint32_t gPluginInformationHeapSize; extern plugin_information_on_reload_t gLinkOnReload; extern module_information_t *gModuleData; -extern relocation_trampolin_entry_t *gTrampolineData; +extern relocation_trampoline_entry_t *gTrampolineData; extern uint32_t gTrampolineDataSize; extern StoredBuffer storedTVBuffer; extern StoredBuffer storedDRCBuffer; diff --git a/source/main.cpp b/source/main.cpp index 037b8c6..8e19913 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -106,14 +106,14 @@ WUMS_APPLICATION_STARTS() { memset((void *) gPluginInformation, 0, sizeof(plugin_information_t)); } if (gTrampolineData == nullptr) { - DEBUG_FUNCTION_LINE_VERBOSE("Allocate gTrampolineData on heap %08X (size: %d bytes)", gPluginDataHeap, sizeof(relocation_trampolin_entry_t) * NUMBER_OF_TRAMPS); - gTrampolineData = (relocation_trampolin_entry_t *) MEMAllocFromExpHeapEx(gPluginDataHeap, sizeof(relocation_trampolin_entry_t) * NUMBER_OF_TRAMPS, 4); + DEBUG_FUNCTION_LINE_VERBOSE("Allocate gTrampolineData on heap %08X (size: %d bytes)", gPluginDataHeap, sizeof(relocation_trampoline_entry_t) * NUMBER_OF_TRAMPS); + gTrampolineData = (relocation_trampoline_entry_t *) MEMAllocFromExpHeapEx(gPluginDataHeap, sizeof(relocation_trampoline_entry_t) * NUMBER_OF_TRAMPS, 4); if (gTrampolineData == nullptr) { OSFatal("PluginBackend: Failed to allocate gTrampolineData"); return; } gTrampolineDataSize = NUMBER_OF_TRAMPS; - memset((void *) gTrampolineData, 0, sizeof(relocation_trampolin_entry_t) * NUMBER_OF_TRAMPS); + memset((void *) gTrampolineData, 0, sizeof(relocation_trampoline_entry_t) * NUMBER_OF_TRAMPS); } DEBUG_FUNCTION_LINE("Available memory for storing plugins: %d kb", MEMGetAllocatableSizeForExpHeapEx(gPluginDataHeap, 4) / 1024); std::vector> pluginList = PluginDataFactory::loadDir("fs:/vol/external01/wiiu/plugins/", gPluginDataHeap); @@ -190,7 +190,7 @@ WUMS_APPLICATION_STARTS() { if (gPluginDataHeap != nullptr) { auto plugins = PluginContainerPersistence::loadPlugins(gPluginInformation); - PluginManagement::doRelocations(plugins, gTrampolineData, DYN_LINK_TRAMPOLIN_LIST_LENGTH); + PluginManagement::doRelocations(plugins, gTrampolineData, DYN_LINK_TRAMPOLINE_LIST_LENGTH); // PluginManagement::memsetBSS(plugins); DCFlushRange((void *) gPluginDataHeap, gPluginDataHeapSize); diff --git a/source/patcher/hooks_patcher_static.cpp b/source/patcher/hooks_patcher_static.cpp index 856d0cb..438bcfc 100644 --- a/source/patcher/hooks_patcher_static.cpp +++ b/source/patcher/hooks_patcher_static.cpp @@ -196,7 +196,7 @@ DECL_FUNCTION(uint32_t, KiGetAppSymbolName, uint32_t addr, char *buffer, int32_t auto symbolData = &plugin->info.function_symbol_data[i]; auto symbolDataNext = &plugin->info.function_symbol_data[i + 1]; if (i == plugin->info.number_function_symbol_data - 2 || (addr >= (uint32_t) symbolData->address && addr < (uint32_t) symbolDataNext->address)) { - if(spaceLeftInBuffer > 2){ + if (spaceLeftInBuffer > 2) { buffer[pluginNameLen] = '|'; buffer[pluginNameLen + 1] = '\0'; strncpy(buffer + pluginNameLen + 1, symbolData->name, spaceLeftInBuffer - 1); @@ -210,6 +210,7 @@ DECL_FUNCTION(uint32_t, KiGetAppSymbolName, uint32_t addr, char *buffer, int32_t return real_KiGetAppSymbolName(addr, buffer, bufSize); } + #pragma GCC pop_options function_replacement_data_t method_hooks_hooks_static[] __attribute__((section(".data"))) = { diff --git a/source/plugin/DynamicLinkingHelper.cpp b/source/plugin/DynamicLinkingHelper.cpp index 9b3a822..d97557b 100644 --- a/source/plugin/DynamicLinkingHelper.cpp +++ b/source/plugin/DynamicLinkingHelper.cpp @@ -10,7 +10,7 @@ dyn_linking_function_t *DynamicLinkingHelper::getOrAddFunctionEntryByName(dyn_li return nullptr; } dyn_linking_function_t *result = nullptr; - for (auto & curEntry : data->functions) { + for (auto &curEntry: data->functions) { if (strlen(curEntry.functionName) == 0) { if (strlen(functionName) > DYN_LINK_FUNCTION_NAME_LENGTH) { DEBUG_FUNCTION_LINE("Failed to add function name, it's too long."); @@ -41,7 +41,7 @@ dyn_linking_import_t *DynamicLinkingHelper::getOrAddImport(dyn_linking_relocatio return nullptr; } dyn_linking_import_t *result = nullptr; - for (auto & curEntry : data->imports) { + for (auto &curEntry: data->imports) { if (strlen(curEntry.importName) == 0) { if (strlen(importName) > DYN_LINK_IMPORT_NAME_LENGTH) { DEBUG_FUNCTION_LINE("Failed to add Import, it's too long."); diff --git a/source/plugin/DynamicLinkingHelper.h b/source/plugin/DynamicLinkingHelper.h index 59f205f..f5feec0 100644 --- a/source/plugin/DynamicLinkingHelper.h +++ b/source/plugin/DynamicLinkingHelper.h @@ -47,7 +47,8 @@ public: **/ static dyn_linking_import_t *getOrAddImport(dyn_linking_relocation_data_t *data, const char *importName, bool isData); - static bool addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, const std::shared_ptr &relocationData); + static bool addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, + const std::shared_ptr &relocationData); static bool addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, diff --git a/source/plugin/ImportRPLInformation.h b/source/plugin/ImportRPLInformation.h index 883b3c9..eac26d5 100644 --- a/source/plugin/ImportRPLInformation.h +++ b/source/plugin/ImportRPLInformation.h @@ -18,13 +18,14 @@ #pragma once #include +#include #include "../utils/logger.h" class ImportRPLInformation { public: explicit ImportRPLInformation(std::string name, bool isData = false) { - this->name = name; + this->name = std::move(name); this->_isData = isData; } diff --git a/source/plugin/PluginContainerPersistence.cpp b/source/plugin/PluginContainerPersistence.cpp index 2f7c55c..1b97043 100644 --- a/source/plugin/PluginContainerPersistence.cpp +++ b/source/plugin/PluginContainerPersistence.cpp @@ -157,7 +157,7 @@ bool PluginContainerPersistence::savePlugin(plugin_information_t *pluginInformat return false; } } - plugin_data->info.trampolinId = pluginInfo->getTrampolinId(); + plugin_data->info.trampolineId = pluginInfo->getTrampolineId(); plugin_data->info.allocatedTextMemoryAddress = pluginInfo->allocatedTextMemoryAddress; plugin_data->info.allocatedDataMemoryAddress = pluginInfo->allocatedDataMemoryAddress; @@ -253,7 +253,7 @@ std::vector> PluginContainerPersistence::loadPl auto curPluginInformation = std::make_shared(); - curPluginInformation->setTrampolinId(plugin_data->info.trampolinId); + curPluginInformation->setTrampolineId(plugin_data->info.trampolineId); curPluginInformation->allocatedTextMemoryAddress = plugin_data->info.allocatedTextMemoryAddress; curPluginInformation->allocatedDataMemoryAddress = plugin_data->info.allocatedDataMemoryAddress; diff --git a/source/plugin/PluginData.h b/source/plugin/PluginData.h index a5adadd..0ce371b 100644 --- a/source/plugin/PluginData.h +++ b/source/plugin/PluginData.h @@ -43,7 +43,7 @@ public: void *buffer = nullptr; MEMHeapHandle heapHandle{}; - eMemoryTypes memoryType; + eMemoryTypes memoryType{}; size_t length = 0; private: diff --git a/source/plugin/PluginDataFactory.cpp b/source/plugin/PluginDataFactory.cpp index df204b3..8b50efb 100644 --- a/source/plugin/PluginDataFactory.cpp +++ b/source/plugin/PluginDataFactory.cpp @@ -26,7 +26,7 @@ std::vector> PluginDataFactory::loadDir(const std::string &path, MEMHeapHandle heapHandle) { std::vector> result; struct dirent *dp; - DIR *dfd = nullptr; + DIR *dfd; if (path.empty()) { DEBUG_FUNCTION_LINE("Path was empty"); diff --git a/source/plugin/PluginDataPersistence.cpp b/source/plugin/PluginDataPersistence.cpp index d51e44b..369a2de 100644 --- a/source/plugin/PluginDataPersistence.cpp +++ b/source/plugin/PluginDataPersistence.cpp @@ -13,7 +13,7 @@ bool PluginDataPersistence::save(plugin_data_t *pluginDataStruct, const std::sha return true; } -bool PluginDataPersistence::save(plugin_data_t *pluginDataStruct, PluginData* plugin) { +bool PluginDataPersistence::save(plugin_data_t *pluginDataStruct, PluginData *plugin) { if (pluginDataStruct == nullptr) { return false; } diff --git a/source/plugin/PluginDataPersistence.h b/source/plugin/PluginDataPersistence.h index 1312900..6cc054c 100644 --- a/source/plugin/PluginDataPersistence.h +++ b/source/plugin/PluginDataPersistence.h @@ -6,7 +6,8 @@ class PluginDataPersistence { public: static bool save(plugin_data_t *pluginDataStruct, const std::shared_ptr &plugin); - static bool save(plugin_data_t *pluginDataStruct, PluginData* plugin); + + static bool save(plugin_data_t *pluginDataStruct, PluginData *plugin); static std::shared_ptr load(plugin_data_t *pluginDataStruct); }; diff --git a/source/plugin/PluginInformation.cpp b/source/plugin/PluginInformation.cpp index 3302be7..cbb92ec 100644 --- a/source/plugin/PluginInformation.cpp +++ b/source/plugin/PluginInformation.cpp @@ -14,7 +14,7 @@ PluginInformation::PluginInformation(const PluginInformation &other) { symbol_data_list.insert(i); } section_info_list = other.section_info_list; - trampolinId = other.trampolinId; + trampolineId = other.trampolineId; allocatedTextMemoryAddress = other.allocatedTextMemoryAddress; allocatedDataMemoryAddress = other.allocatedDataMemoryAddress; } \ No newline at end of file diff --git a/source/plugin/PluginInformation.h b/source/plugin/PluginInformation.h index 8f34bfb..0827224 100644 --- a/source/plugin/PluginInformation.h +++ b/source/plugin/PluginInformation.h @@ -31,9 +31,8 @@ #include "FunctionSymbolData.h" struct FunctionSymbolDataComparator { - bool operator()(const std::shared_ptr& lhs, - const std::shared_ptr& rhs) const - { + bool operator()(const std::shared_ptr &lhs, + const std::shared_ptr &rhs) const { return (uint32_t) lhs->getAddress() < (uint32_t) rhs->getAddress(); } }; @@ -94,12 +93,12 @@ public: return std::nullopt; } - void setTrampolinId(uint8_t _trampolinId) { - this->trampolinId = _trampolinId; + void setTrampolineId(uint8_t _trampolineId) { + this->trampolineId = _trampolineId; } - [[nodiscard]] uint8_t getTrampolinId() const { - return trampolinId; + [[nodiscard]] uint8_t getTrampolineId() const { + return trampolineId; } private: @@ -109,7 +108,7 @@ private: std::set, FunctionSymbolDataComparator> symbol_data_list; std::map> section_info_list; - uint8_t trampolinId = 0; + uint8_t trampolineId = 0; void *allocatedTextMemoryAddress = nullptr; void *allocatedDataMemoryAddress = nullptr; diff --git a/source/plugin/PluginInformationFactory.cpp b/source/plugin/PluginInformationFactory.cpp index 5e3bf6b..4ba9d08 100644 --- a/source/plugin/PluginInformationFactory.cpp +++ b/source/plugin/PluginInformationFactory.cpp @@ -30,8 +30,8 @@ using namespace ELFIO; std::optional> -PluginInformationFactory::load(const std::shared_ptr &pluginData, MEMHeapHandle heapHandle, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length, - uint8_t trampolinId) { +PluginInformationFactory::load(const std::shared_ptr &pluginData, MEMHeapHandle heapHandle, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, + uint8_t trampolineId) { if (pluginData->buffer == nullptr) { DEBUG_FUNCTION_LINE("Buffer was nullptr"); return std::nullopt; @@ -145,7 +145,8 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, ME if ((psec->get_type() == SHT_PROGBITS || psec->get_type() == SHT_NOBITS) && (psec->get_flags() & SHF_ALLOC)) { DEBUG_FUNCTION_LINE_VERBOSE("Linking (%d)... %s at %08X", i, psec->get_name().c_str(), destinations[psec->get_index()]); - if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], (uint32_t) text_data, (uint32_t) data_data, trampolin_data, trampolin_data_length, trampolinId)) { + if (!linkSection(reader, psec->get_index(), (uint32_t) destinations[psec->get_index()], (uint32_t) text_data, (uint32_t) data_data, trampoline_data, trampoline_data_length, + trampolineId)) { DEBUG_FUNCTION_LINE("elfLink failed"); free(destinations); MEMFreeToExpHeap(heapHandle, text_data); @@ -167,7 +168,7 @@ PluginInformationFactory::load(const std::shared_ptr &pluginData, ME free(destinations); - pluginInfo->setTrampolinId(trampolinId); + pluginInfo->setTrampolineId(trampolineId); auto secInfo = pluginInfo->getSectionInfo(".wups.hooks"); if (secInfo && secInfo.value()->getSize() > 0) { @@ -314,9 +315,9 @@ std::vector> PluginInformationFactory::getImport return result; } -bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampolin_entry_t *trampolin_data, - uint32_t trampolin_data_length, - uint8_t trampolinId) { +bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampoline_entry_t *trampoline_data, + uint32_t trampoline_data_length, + uint8_t trampolineId) { uint32_t sec_num = reader.sections.size(); for (uint32_t i = 0; i < sec_num; ++i) { @@ -372,7 +373,7 @@ bool PluginInformationFactory::linkSection(const elfio &reader, uint32_t section } // DEBUG_FUNCTION_LINE_VERBOSE("sym_value %08X adjusted_sym_value %08X offset %08X adjusted_offset %08X", (uint32_t) sym_value, adjusted_sym_value, (uint32_t) offset, adjusted_offset); - if (!ElfUtils::elfLinkOne(type, adjusted_offset, addend, destination, adjusted_sym_value, trampolin_data, trampolin_data_length, RELOC_TYPE_FIXED, trampolinId)) { + if (!ElfUtils::elfLinkOne(type, adjusted_offset, addend, destination, adjusted_sym_value, trampoline_data, trampoline_data_length, RELOC_TYPE_FIXED, trampolineId)) { DEBUG_FUNCTION_LINE("Link failed"); return false; } diff --git a/source/plugin/PluginInformationFactory.h b/source/plugin/PluginInformationFactory.h index fc1aa11..3c658fd 100644 --- a/source/plugin/PluginInformationFactory.h +++ b/source/plugin/PluginInformationFactory.h @@ -30,11 +30,12 @@ class PluginInformationFactory { public: static std::optional> - load(const std::shared_ptr &pluginData, MEMHeapHandle heaphandle, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length, uint8_t trampolinId); + load(const std::shared_ptr &pluginData, MEMHeapHandle heaphandle, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, uint8_t trampolineId); static bool - linkSection(const elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length, - uint8_t trampolinId); + linkSection(const elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampoline_entry_t *trampoline_data, + uint32_t trampoline_data_length, + uint8_t trampolineId); static std::vector> getImportRelocationData(const elfio &reader, uint8_t **destinations); }; diff --git a/source/utils/ConfigUtils.cpp b/source/utils/ConfigUtils.cpp index e37b809..1e26ba5 100644 --- a/source/utils/ConfigUtils.cpp +++ b/source/utils/ConfigUtils.cpp @@ -146,7 +146,7 @@ void ConfigUtils::displayMenu() { } } - if(configs.empty()){ + if (configs.empty()) { return; } diff --git a/source/utils/ElfUtils.cpp b/source/utils/ElfUtils.cpp index 84e6dcd..dfcf3b3 100644 --- a/source/utils/ElfUtils.cpp +++ b/source/utils/ElfUtils.cpp @@ -5,8 +5,8 @@ #include "ElfUtils.h" // See https://github.com/decaf-emu/decaf-emu/blob/43366a34e7b55ab9d19b2444aeb0ccd46ac77dea/src/libdecaf/src/cafe/loader/cafe_loader_reloc.cpp#L144 -bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length, - RelocationType reloc_type, uint8_t trampolinId) { +bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, + RelocationType reloc_type, uint8_t trampolineId) { if (type == R_PPC_NONE) { return true; } @@ -75,44 +75,44 @@ bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t des // } auto distance = static_cast(value) - static_cast(target); if (distance > 0x1FFFFFC || distance < -0x1FFFFFC) { - if (trampolin_data == nullptr) { - DEBUG_FUNCTION_LINE("***24-bit relative branch cannot hit target. Trampolin isn't provided"); + if (trampoline_data == nullptr) { + DEBUG_FUNCTION_LINE("***24-bit relative branch cannot hit target. Trampoline isn't provided"); DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X", value, target, distance); return false; } else { - relocation_trampolin_entry_t *freeSlot = nullptr; - for (uint32_t i = 0; i < trampolin_data_length; i++) { + relocation_trampoline_entry_t *freeSlot = nullptr; + for (uint32_t i = 0; i < trampoline_data_length; i++) { // We want to override "old" relocations of imports // Pending relocations have the status RELOC_TRAMP_IMPORT_IN_PROGRESS. // When all relocations are done successfully, they will be turned into RELOC_TRAMP_IMPORT_DONE // so they can be overridden/updated/reused on the next application launch. // // Relocations that won't change will have the status RELOC_TRAMP_FIXED and are set to free when the module is unloaded. - if (trampolin_data[i].status == RELOC_TRAMP_FREE || - trampolin_data[i].status == RELOC_TRAMP_IMPORT_DONE) { - freeSlot = &(trampolin_data[i]); + if (trampoline_data[i].status == RELOC_TRAMP_FREE || + trampoline_data[i].status == RELOC_TRAMP_IMPORT_DONE) { + freeSlot = &(trampoline_data[i]); break; } } if (freeSlot == nullptr) { - DEBUG_FUNCTION_LINE("***24-bit relative branch cannot hit target. Trampolin data list is full"); - DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X", value, target, target - (uint32_t) &(freeSlot->trampolin[0])); + DEBUG_FUNCTION_LINE("***24-bit relative branch cannot hit target. Trampoline data list is full"); + DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X", value, target, target - (uint32_t) &(freeSlot->trampoline[0])); return false; } - if (target - (uint32_t) &(freeSlot->trampolin[0]) > 0x1FFFFFC) { + if (target - (uint32_t) &(freeSlot->trampoline[0]) > 0x1FFFFFC) { DEBUG_FUNCTION_LINE("**Cannot link 24-bit jump (too far to tramp buffer)."); - DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X", value, target, (target - (uint32_t) &(freeSlot->trampolin[0]))); + DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X", value, target, (target - (uint32_t) &(freeSlot->trampoline[0]))); return false; } - freeSlot->trampolin[0] = 0x3D600000 | ((((uint32_t) value) >> 16) & 0x0000FFFF); // lis r11, real_addr@h - freeSlot->trampolin[1] = 0x616B0000 | (((uint32_t) value) & 0x0000ffff); // ori r11, r11, real_addr@l - freeSlot->trampolin[2] = 0x7D6903A6; // mtctr r11 - freeSlot->trampolin[3] = 0x4E800420; // bctr - DCFlushRange((void *) freeSlot->trampolin, sizeof(freeSlot->trampolin)); - ICInvalidateRange((unsigned char *) freeSlot->trampolin, sizeof(freeSlot->trampolin)); + freeSlot->trampoline[0] = 0x3D600000 | ((((uint32_t) value) >> 16) & 0x0000FFFF); // lis r11, real_addr@h + freeSlot->trampoline[1] = 0x616B0000 | (((uint32_t) value) & 0x0000ffff); // ori r11, r11, real_addr@l + freeSlot->trampoline[2] = 0x7D6903A6; // mtctr r11 + freeSlot->trampoline[3] = 0x4E800420; // bctr + DCFlushRange((void *) freeSlot->trampoline, sizeof(freeSlot->trampoline)); + ICInvalidateRange((unsigned char *) freeSlot->trampoline, sizeof(freeSlot->trampoline)); - freeSlot->id = trampolinId; + freeSlot->id = trampolineId; DCFlushRange((void *) &freeSlot->id, sizeof(freeSlot->id)); ICInvalidateRange((unsigned char *) &freeSlot->id, sizeof(freeSlot->id)); @@ -122,7 +122,7 @@ bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t des // Relocations for the imports may be overridden freeSlot->status = RELOC_TRAMP_IMPORT_DONE; } - uint32_t symbolValue = (uint32_t) &(freeSlot->trampolin[0]); + auto symbolValue = (uint32_t) &(freeSlot->trampoline[0]); value = symbolValue + addend; distance = static_cast(value) - static_cast(target); } diff --git a/source/utils/ElfUtils.h b/source/utils/ElfUtils.h index 3b95952..cb85d14 100644 --- a/source/utils/ElfUtils.h +++ b/source/utils/ElfUtils.h @@ -46,6 +46,6 @@ uint32_t load_loader_elf(unsigned char *baseAddress, char *elf_data, uint32_t fi class ElfUtils { public: - static bool elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length, - RelocationType reloc_type, uint8_t trampolinId); + static bool elfLinkOne(char type, size_t offset, int32_t addend, uint32_t destination, uint32_t symbol_addr, relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length, + RelocationType reloc_type, uint8_t trampolineId); }; diff --git a/source/utils/exports.cpp b/source/utils/exports.cpp index 4564d0c..e9b9f76 100644 --- a/source/utils/exports.cpp +++ b/source/utils/exports.cpp @@ -9,7 +9,7 @@ #include "exports.h" #include -void fillPluginInformation(plugin_information *out, const std::shared_ptr& metaInformation) { +void fillPluginInformation(plugin_information *out, const std::shared_ptr &metaInformation) { out->plugin_information_version = PLUGIN_INFORMATION_VERSION; strncpy(out->author, metaInformation->getAuthor().c_str(), sizeof(out->author) - 1); strncpy(out->buildTimestamp, metaInformation->getBuildTimestamp().c_str(), sizeof(out->buildTimestamp) - 1); diff --git a/source/utils/json.hpp b/source/utils/json.hpp index 242f034..608fb06 100644 --- a/source/utils/json.hpp +++ b/source/utils/json.hpp @@ -78,28 +78,24 @@ SOFTWARE. #include // size_t -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; + struct position_t { + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const { + return chars_read_total; + } + }; -} // namespace detail + } // namespace detail } // namespace nlohmann // #include @@ -121,96 +117,96 @@ struct position_t #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 13) #if defined(JSON_HEDLEY_VERSION) - #undef JSON_HEDLEY_VERSION +#undef JSON_HEDLEY_VERSION #endif #define JSON_HEDLEY_VERSION 13 #if defined(JSON_HEDLEY_STRINGIFY_EX) - #undef JSON_HEDLEY_STRINGIFY_EX +#undef JSON_HEDLEY_STRINGIFY_EX #endif #define JSON_HEDLEY_STRINGIFY_EX(x) #x #if defined(JSON_HEDLEY_STRINGIFY) - #undef JSON_HEDLEY_STRINGIFY +#undef JSON_HEDLEY_STRINGIFY #endif #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) #if defined(JSON_HEDLEY_CONCAT_EX) - #undef JSON_HEDLEY_CONCAT_EX +#undef JSON_HEDLEY_CONCAT_EX #endif -#define JSON_HEDLEY_CONCAT_EX(a,b) a##b +#define JSON_HEDLEY_CONCAT_EX(a, b) a##b #if defined(JSON_HEDLEY_CONCAT) - #undef JSON_HEDLEY_CONCAT +#undef JSON_HEDLEY_CONCAT #endif -#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) +#define JSON_HEDLEY_CONCAT(a, b) JSON_HEDLEY_CONCAT_EX(a,b) #if defined(JSON_HEDLEY_CONCAT3_EX) - #undef JSON_HEDLEY_CONCAT3_EX +#undef JSON_HEDLEY_CONCAT3_EX #endif -#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c +#define JSON_HEDLEY_CONCAT3_EX(a, b, c) a##b##c #if defined(JSON_HEDLEY_CONCAT3) - #undef JSON_HEDLEY_CONCAT3 +#undef JSON_HEDLEY_CONCAT3 #endif -#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) +#define JSON_HEDLEY_CONCAT3(a, b, c) JSON_HEDLEY_CONCAT3_EX(a,b,c) #if defined(JSON_HEDLEY_VERSION_ENCODE) - #undef JSON_HEDLEY_VERSION_ENCODE +#undef JSON_HEDLEY_VERSION_ENCODE #endif -#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) +#define JSON_HEDLEY_VERSION_ENCODE(major, minor, revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) - #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#undef JSON_HEDLEY_VERSION_DECODE_MAJOR #endif #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) - #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#undef JSON_HEDLEY_VERSION_DECODE_MINOR #endif #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) - #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#undef JSON_HEDLEY_VERSION_DECODE_REVISION #endif #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) #if defined(JSON_HEDLEY_GNUC_VERSION) - #undef JSON_HEDLEY_GNUC_VERSION +#undef JSON_HEDLEY_GNUC_VERSION #endif #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #elif defined(__GNUC__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) #endif #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) - #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#undef JSON_HEDLEY_GNUC_VERSION_CHECK #endif #if defined(JSON_HEDLEY_GNUC_VERSION) - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_GNUC_VERSION_CHECK(major, minor, patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) #endif #if defined(JSON_HEDLEY_MSVC_VERSION) - #undef JSON_HEDLEY_MSVC_VERSION +#undef JSON_HEDLEY_MSVC_VERSION #endif #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) #elif defined(_MSC_FULL_VER) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) #elif defined(_MSC_VER) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) #endif #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) - #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#undef JSON_HEDLEY_MSVC_VERSION_CHECK #endif #if !defined(_MSC_VER) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_MSVC_VERSION_CHECK(major, minor, patch) (0) #elif defined(_MSC_VER) && (_MSC_VER >= 1400) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) #elif defined(_MSC_VER) && (_MSC_VER >= 1200) #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) #else @@ -218,240 +214,240 @@ struct position_t #endif #if defined(JSON_HEDLEY_INTEL_VERSION) - #undef JSON_HEDLEY_INTEL_VERSION +#undef JSON_HEDLEY_INTEL_VERSION #endif #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) #elif defined(__INTEL_COMPILER) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) #endif #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#undef JSON_HEDLEY_INTEL_VERSION_CHECK #endif #if defined(JSON_HEDLEY_INTEL_VERSION) - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_INTEL_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_PGI_VERSION) - #undef JSON_HEDLEY_PGI_VERSION +#undef JSON_HEDLEY_PGI_VERSION #endif #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) - #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) #endif #if defined(JSON_HEDLEY_PGI_VERSION_CHECK) - #undef JSON_HEDLEY_PGI_VERSION_CHECK +#undef JSON_HEDLEY_PGI_VERSION_CHECK #endif #if defined(JSON_HEDLEY_PGI_VERSION) - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_PGI_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_SUNPRO_VERSION) - #undef JSON_HEDLEY_SUNPRO_VERSION +#undef JSON_HEDLEY_SUNPRO_VERSION #endif #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) #elif defined(__SUNPRO_C) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) #elif defined(__SUNPRO_CC) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) #endif #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) - #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK #endif #if defined(JSON_HEDLEY_SUNPRO_VERSION) - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION #endif #if defined(__EMSCRIPTEN__) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) #endif #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK #endif #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_ARM_VERSION) - #undef JSON_HEDLEY_ARM_VERSION +#undef JSON_HEDLEY_ARM_VERSION #endif #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) #elif defined(__CC_ARM) && defined(__ARMCC_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) #endif #if defined(JSON_HEDLEY_ARM_VERSION_CHECK) - #undef JSON_HEDLEY_ARM_VERSION_CHECK +#undef JSON_HEDLEY_ARM_VERSION_CHECK #endif #if defined(JSON_HEDLEY_ARM_VERSION) - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_ARM_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_IBM_VERSION) - #undef JSON_HEDLEY_IBM_VERSION +#undef JSON_HEDLEY_IBM_VERSION #endif #if defined(__ibmxl__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) #elif defined(__xlC__) && defined(__xlC_ver__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) #elif defined(__xlC__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) #endif #if defined(JSON_HEDLEY_IBM_VERSION_CHECK) - #undef JSON_HEDLEY_IBM_VERSION_CHECK +#undef JSON_HEDLEY_IBM_VERSION_CHECK #endif #if defined(JSON_HEDLEY_IBM_VERSION) - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_IBM_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_TI_VERSION) - #undef JSON_HEDLEY_TI_VERSION +#undef JSON_HEDLEY_TI_VERSION #endif #if \ defined(__TI_COMPILER_VERSION__) && \ - ( \ + (\ defined(__TMS470__) || defined(__TI_ARM__) || \ defined(__MSP430__) || \ defined(__TMS320C2000__) \ - ) -#if (__TI_COMPILER_VERSION__ >= 16000000) +) + #if (__TI_COMPILER_VERSION__ >= 16000000) #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) #endif #endif #if defined(JSON_HEDLEY_TI_VERSION_CHECK) - #undef JSON_HEDLEY_TI_VERSION_CHECK +#undef JSON_HEDLEY_TI_VERSION_CHECK #endif #if defined(JSON_HEDLEY_TI_VERSION) - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_TI_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #undef JSON_HEDLEY_TI_CL2000_VERSION +#undef JSON_HEDLEY_TI_CL2000_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) - #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK #endif #if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_TI_CL430_VERSION) - #undef JSON_HEDLEY_TI_CL430_VERSION +#undef JSON_HEDLEY_TI_CL430_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) - #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK #endif #if defined(JSON_HEDLEY_TI_CL430_VERSION) - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #undef JSON_HEDLEY_TI_ARMCL_VERSION +#undef JSON_HEDLEY_TI_ARMCL_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) - #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) - #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK #endif #if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #undef JSON_HEDLEY_TI_CL6X_VERSION +#undef JSON_HEDLEY_TI_CL6X_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) - #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK #endif #if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #undef JSON_HEDLEY_TI_CL7X_VERSION +#undef JSON_HEDLEY_TI_CL7X_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) - #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK #endif #if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #undef JSON_HEDLEY_TI_CLPRU_VERSION +#undef JSON_HEDLEY_TI_CLPRU_VERSION #endif #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) - #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) #endif #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK #endif #if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_CRAY_VERSION) - #undef JSON_HEDLEY_CRAY_VERSION +#undef JSON_HEDLEY_CRAY_VERSION #endif #if defined(_CRAYC) - #if defined(_RELEASE_PATCHLEVEL) + #if defined(_RELEASE_PATCHLEVEL) #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) #else #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) @@ -459,19 +455,19 @@ struct position_t #endif #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) - #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#undef JSON_HEDLEY_CRAY_VERSION_CHECK #endif #if defined(JSON_HEDLEY_CRAY_VERSION) - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_CRAY_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_IAR_VERSION) - #undef JSON_HEDLEY_IAR_VERSION +#undef JSON_HEDLEY_IAR_VERSION #endif #if defined(__IAR_SYSTEMS_ICC__) - #if __VER__ > 1000 + #if __VER__ > 1000 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) #else #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0) @@ -479,80 +475,80 @@ struct position_t #endif #if defined(JSON_HEDLEY_IAR_VERSION_CHECK) - #undef JSON_HEDLEY_IAR_VERSION_CHECK +#undef JSON_HEDLEY_IAR_VERSION_CHECK #endif #if defined(JSON_HEDLEY_IAR_VERSION) - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_IAR_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_TINYC_VERSION) - #undef JSON_HEDLEY_TINYC_VERSION +#undef JSON_HEDLEY_TINYC_VERSION #endif #if defined(__TINYC__) - #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) #endif #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) - #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#undef JSON_HEDLEY_TINYC_VERSION_CHECK #endif #if defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_TINYC_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_DMC_VERSION) - #undef JSON_HEDLEY_DMC_VERSION +#undef JSON_HEDLEY_DMC_VERSION #endif #if defined(__DMC__) - #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) #endif #if defined(JSON_HEDLEY_DMC_VERSION_CHECK) - #undef JSON_HEDLEY_DMC_VERSION_CHECK +#undef JSON_HEDLEY_DMC_VERSION_CHECK #endif #if defined(JSON_HEDLEY_DMC_VERSION) - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_DMC_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_COMPCERT_VERSION) - #undef JSON_HEDLEY_COMPCERT_VERSION +#undef JSON_HEDLEY_COMPCERT_VERSION #endif #if defined(__COMPCERT_VERSION__) - #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) #endif #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) - #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK #endif #if defined(JSON_HEDLEY_COMPCERT_VERSION) - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_PELLES_VERSION) - #undef JSON_HEDLEY_PELLES_VERSION +#undef JSON_HEDLEY_PELLES_VERSION #endif #if defined(__POCC__) - #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) #endif #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) - #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#undef JSON_HEDLEY_PELLES_VERSION_CHECK #endif #if defined(JSON_HEDLEY_PELLES_VERSION) - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_PELLES_VERSION_CHECK(major, minor, patch) (0) #endif #if defined(JSON_HEDLEY_GCC_VERSION) - #undef JSON_HEDLEY_GCC_VERSION +#undef JSON_HEDLEY_GCC_VERSION #endif #if \ defined(JSON_HEDLEY_GNUC_VERSION) && \ @@ -568,233 +564,233 @@ struct position_t !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ !defined(__COMPCERT__) - #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION #endif #if defined(JSON_HEDLEY_GCC_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_VERSION_CHECK +#undef JSON_HEDLEY_GCC_VERSION_CHECK #endif #if defined(JSON_HEDLEY_GCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#define JSON_HEDLEY_GCC_VERSION_CHECK(major, minor, patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) #else - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) #endif #if defined(JSON_HEDLEY_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_ATTRIBUTE +#undef JSON_HEDLEY_HAS_ATTRIBUTE #endif #if defined(__has_attribute) - #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) #else - #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) #endif #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE #endif #if defined(__has_attribute) - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) +#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) #else - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE #endif #if defined(__has_attribute) - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) +#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) #else - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE #endif #if \ defined(__has_cpp_attribute) && \ defined(__cplusplus) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0)) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) #else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) #endif #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS #endif #if !defined(__cplusplus) || !defined(__has_cpp_attribute) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) #elif \ !defined(JSON_HEDLEY_PGI_VERSION) && \ !defined(JSON_HEDLEY_IAR_VERSION) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ - (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19, 20, 0)) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns, attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) #else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) #endif #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE #endif #if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) __has_cpp_attribute(attribute) #else - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE #endif #if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute, major, minor, patch) __has_cpp_attribute(attribute) #else - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_HAS_BUILTIN) - #undef JSON_HEDLEY_HAS_BUILTIN +#undef JSON_HEDLEY_HAS_BUILTIN #endif #if defined(__has_builtin) - #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) #else - #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) #endif #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) - #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#undef JSON_HEDLEY_GNUC_HAS_BUILTIN #endif #if defined(__has_builtin) - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) #else - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin, major, minor, patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) - #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#undef JSON_HEDLEY_GCC_HAS_BUILTIN #endif #if defined(__has_builtin) - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) #else - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_HAS_FEATURE) - #undef JSON_HEDLEY_HAS_FEATURE +#undef JSON_HEDLEY_HAS_FEATURE #endif #if defined(__has_feature) - #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) #else - #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#define JSON_HEDLEY_HAS_FEATURE(feature) (0) #endif #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) - #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#undef JSON_HEDLEY_GNUC_HAS_FEATURE #endif #if defined(__has_feature) - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) #else - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature, major, minor, patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_GCC_HAS_FEATURE) - #undef JSON_HEDLEY_GCC_HAS_FEATURE +#undef JSON_HEDLEY_GCC_HAS_FEATURE #endif #if defined(__has_feature) - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) #else - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GCC_HAS_FEATURE(feature, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_HAS_EXTENSION) - #undef JSON_HEDLEY_HAS_EXTENSION +#undef JSON_HEDLEY_HAS_EXTENSION #endif #if defined(__has_extension) - #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) #else - #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#define JSON_HEDLEY_HAS_EXTENSION(extension) (0) #endif #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) - #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#undef JSON_HEDLEY_GNUC_HAS_EXTENSION #endif #if defined(__has_extension) - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) #else - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension, major, minor, patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) - #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#undef JSON_HEDLEY_GCC_HAS_EXTENSION #endif #if defined(__has_extension) - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) #else - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE #endif #if defined(__has_declspec_attribute) - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) #else - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) #endif #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE #endif #if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) #else - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE #endif #if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) #else - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_HAS_WARNING) - #undef JSON_HEDLEY_HAS_WARNING +#undef JSON_HEDLEY_HAS_WARNING #endif #if defined(__has_warning) - #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) #else - #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#define JSON_HEDLEY_HAS_WARNING(warning) (0) #endif #if defined(JSON_HEDLEY_GNUC_HAS_WARNING) - #undef JSON_HEDLEY_GNUC_HAS_WARNING +#undef JSON_HEDLEY_GNUC_HAS_WARNING #endif #if defined(__has_warning) - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) #else - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GNUC_HAS_WARNING(warning, major, minor, patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_GCC_HAS_WARNING) - #undef JSON_HEDLEY_GCC_HAS_WARNING +#undef JSON_HEDLEY_GCC_HAS_WARNING #endif #if defined(__has_warning) - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) #else - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GCC_HAS_WARNING(warning, major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ #endif #if defined(__cplusplus) # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") -# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") + # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ @@ -811,19 +807,19 @@ struct position_t # endif #endif #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x #endif #if defined(JSON_HEDLEY_CONST_CAST) - #undef JSON_HEDLEY_CONST_CAST +#undef JSON_HEDLEY_CONST_CAST #endif #if defined(__cplusplus) # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) #elif \ JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) + # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ ((T) (expr)); \ @@ -834,35 +830,35 @@ struct position_t #endif #if defined(JSON_HEDLEY_REINTERPRET_CAST) - #undef JSON_HEDLEY_REINTERPRET_CAST +#undef JSON_HEDLEY_REINTERPRET_CAST #endif #if defined(__cplusplus) - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) #else - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) #endif #if defined(JSON_HEDLEY_STATIC_CAST) - #undef JSON_HEDLEY_STATIC_CAST +#undef JSON_HEDLEY_STATIC_CAST #endif #if defined(__cplusplus) - #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) #else - #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) #endif #if defined(JSON_HEDLEY_CPP_CAST) - #undef JSON_HEDLEY_CPP_CAST +#undef JSON_HEDLEY_CPP_CAST #endif #if defined(__cplusplus) # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") -# define JSON_HEDLEY_CPP_CAST(T, expr) \ + # define JSON_HEDLEY_CPP_CAST(T, expr) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ ((T) (expr)) \ JSON_HEDLEY_DIAGNOSTIC_POP -# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) -# define JSON_HEDLEY_CPP_CAST(T, expr) \ +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8, 3, 0) + # define JSON_HEDLEY_CPP_CAST(T, expr) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("diag_suppress=Pe137") \ JSON_HEDLEY_DIAGNOSTIC_POP \ @@ -876,46 +872,46 @@ struct position_t #if \ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ defined(__clang__) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) - #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_PRAGMA(value) __pragma(value) + JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18, 4, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 7, 0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2, 0, 1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 1, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 0, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5, 0, 0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8, 0, 0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) && defined(__C99_PRAGMA_OPERATOR)) +#define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) #else #define JSON_HEDLEY_PRAGMA(value) #endif #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) - #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#undef JSON_HEDLEY_DIAGNOSTIC_PUSH #endif #if defined(JSON_HEDLEY_DIAGNOSTIC_POP) - #undef JSON_HEDLEY_DIAGNOSTIC_POP +#undef JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(__clang__) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") @@ -938,18 +934,18 @@ struct position_t #endif #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED #endif #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) #elif \ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ @@ -976,18 +972,18 @@ struct position_t #endif #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS #endif #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) #elif \ JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ @@ -1003,14 +999,14 @@ struct position_t #endif #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES #endif #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4, 6, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17, 0, 0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) @@ -1029,43 +1025,43 @@ struct position_t #endif #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL #endif #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") #else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL #endif #if defined(JSON_HEDLEY_DEPRECATED) - #undef JSON_HEDLEY_DEPRECATED +#undef JSON_HEDLEY_DEPRECATED #endif #if defined(JSON_HEDLEY_DEPRECATED_FOR) - #undef JSON_HEDLEY_DEPRECATED_FOR +#undef JSON_HEDLEY_DEPRECATED_FOR #endif -#if JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) +#if JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) #elif defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) #elif \ JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + JSON_HEDLEY_GCC_VERSION_CHECK(4, 5, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 13, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18, 1, 0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18, 1, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 3, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 3, 0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) #elif \ JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ @@ -1098,50 +1094,50 @@ struct position_t #endif #if defined(JSON_HEDLEY_UNAVAILABLE) - #undef JSON_HEDLEY_UNAVAILABLE +#undef JSON_HEDLEY_UNAVAILABLE #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) + JSON_HEDLEY_GCC_VERSION_CHECK(4, 3, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) #else - #define JSON_HEDLEY_UNAVAILABLE(available_since) +#define JSON_HEDLEY_UNAVAILABLE(available_since) #endif #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#undef JSON_HEDLEY_WARN_UNUSED_RESULT #endif #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG #endif #if (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) #elif \ JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) + JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) +#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) #elif defined(_Check_return_) /* SAL */ - #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ #else #define JSON_HEDLEY_WARN_UNUSED_RESULT @@ -1149,47 +1145,47 @@ struct position_t #endif #if defined(JSON_HEDLEY_SENTINEL) - #undef JSON_HEDLEY_SENTINEL +#undef JSON_HEDLEY_SENTINEL #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) - #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) + JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5, 4, 0) +#define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) #else - #define JSON_HEDLEY_SENTINEL(position) +#define JSON_HEDLEY_SENTINEL(position) #endif #if defined(JSON_HEDLEY_NO_RETURN) - #undef JSON_HEDLEY_NO_RETURN +#undef JSON_HEDLEY_NO_RETURN #endif -#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NO_RETURN __noreturn -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#if JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) +#define JSON_HEDLEY_NO_RETURN __noreturn +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #define JSON_HEDLEY_NO_RETURN _Noreturn +#define JSON_HEDLEY_NO_RETURN _Noreturn #elif defined(__cplusplus) && (__cplusplus >= 201103L) - #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) #elif \ JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) + JSON_HEDLEY_GCC_VERSION_CHECK(3, 2, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") #elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) @@ -1205,33 +1201,33 @@ struct position_t #endif #if defined(JSON_HEDLEY_NO_ESCAPE) - #undef JSON_HEDLEY_NO_ESCAPE +#undef JSON_HEDLEY_NO_ESCAPE #endif #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) - #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) #else - #define JSON_HEDLEY_NO_ESCAPE +#define JSON_HEDLEY_NO_ESCAPE #endif #if defined(JSON_HEDLEY_UNREACHABLE) - #undef JSON_HEDLEY_UNREACHABLE +#undef JSON_HEDLEY_UNREACHABLE #endif #if defined(JSON_HEDLEY_UNREACHABLE_RETURN) - #undef JSON_HEDLEY_UNREACHABLE_RETURN +#undef JSON_HEDLEY_UNREACHABLE_RETURN #endif #if defined(JSON_HEDLEY_ASSUME) - #undef JSON_HEDLEY_ASSUME +#undef JSON_HEDLEY_ASSUME #endif #if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_ASSUME(expr) __assume(expr) + JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_ASSUME(expr) __assume(expr) #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) - #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) #elif \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #if defined(__cplusplus) + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0) + #if defined(__cplusplus) #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) #else #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) @@ -1239,89 +1235,89 @@ struct position_t #endif #if \ (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) - #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() + JSON_HEDLEY_GCC_VERSION_CHECK(4, 5, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18, 10, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 5) +#define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() #elif defined(JSON_HEDLEY_ASSUME) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) #endif #if !defined(JSON_HEDLEY_ASSUME) - #if defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) - #else - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) - #endif +#if defined(JSON_HEDLEY_UNREACHABLE) +#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) +#else +#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) +#endif #endif #if defined(JSON_HEDLEY_UNREACHABLE) - #if \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) - #else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() - #endif +#if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4, 0, 0) +#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) #else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() +#endif +#else +#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) #endif #if !defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) #endif JSON_HEDLEY_DIAGNOSTIC_PUSH #if JSON_HEDLEY_HAS_WARNING("-Wpedantic") - #pragma clang diagnostic ignored "-Wpedantic" +#pragma clang diagnostic ignored "-Wpedantic" #endif #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) - #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros", 4, 0, 0) +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wvariadic-macros" +#elif defined(JSON_HEDLEY_GCC_VERSION) +#pragma GCC diagnostic ignored "-Wvariadic-macros" #endif -#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) - #if defined(__clang__) - #pragma clang diagnostic ignored "-Wvariadic-macros" - #elif defined(JSON_HEDLEY_GCC_VERSION) - #pragma GCC diagnostic ignored "-Wvariadic-macros" - #endif #endif #if defined(JSON_HEDLEY_NON_NULL) - #undef JSON_HEDLEY_NON_NULL +#undef JSON_HEDLEY_NON_NULL #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) + JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) +#define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) #else - #define JSON_HEDLEY_NON_NULL(...) +#define JSON_HEDLEY_NON_NULL(...) #endif JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_PRINTF_FORMAT) - #undef JSON_HEDLEY_PRINTF_FORMAT +#undef JSON_HEDLEY_PRINTF_FORMAT #endif -#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) -#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format, 4, 4, 0) && !defined(__USE_MINGW_ANSI_STDIO) +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format, 4, 4, 0) && defined(__USE_MINGW_ANSI_STDIO) +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx, first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) #elif \ JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) + JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5, 6, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) #else @@ -1329,56 +1325,56 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(JSON_HEDLEY_CONSTEXPR) - #undef JSON_HEDLEY_CONSTEXPR +#undef JSON_HEDLEY_CONSTEXPR #endif #if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) - #endif +#if __cplusplus >= 201103L +#define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) +#endif #endif #if !defined(JSON_HEDLEY_CONSTEXPR) - #define JSON_HEDLEY_CONSTEXPR +#define JSON_HEDLEY_CONSTEXPR #endif #if defined(JSON_HEDLEY_PREDICT) - #undef JSON_HEDLEY_PREDICT +#undef JSON_HEDLEY_PREDICT #endif #if defined(JSON_HEDLEY_LIKELY) - #undef JSON_HEDLEY_LIKELY +#undef JSON_HEDLEY_LIKELY #endif #if defined(JSON_HEDLEY_UNLIKELY) - #undef JSON_HEDLEY_UNLIKELY +#undef JSON_HEDLEY_UNLIKELY #endif #if defined(JSON_HEDLEY_UNPREDICTABLE) - #undef JSON_HEDLEY_UNPREDICTABLE +#undef JSON_HEDLEY_UNPREDICTABLE #endif #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) - #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) #endif #if \ JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) -# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) + JSON_HEDLEY_GCC_VERSION_CHECK(9, 0, 0) + # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) #elif \ JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) + JSON_HEDLEY_GCC_VERSION_CHECK(3, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 15, 0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 7, 0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3, 1, 0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 1, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) # define JSON_HEDLEY_PREDICT(expr, expected, probability) \ (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ @@ -1394,40 +1390,40 @@ JSON_HEDLEY_DIAGNOSTIC_POP # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) #else -# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) + # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) # define JSON_HEDLEY_LIKELY(expr) (!!(expr)) # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) #endif #if !defined(JSON_HEDLEY_UNPREDICTABLE) - #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) #endif #if defined(JSON_HEDLEY_MALLOC) - #undef JSON_HEDLEY_MALLOC +#undef JSON_HEDLEY_MALLOC #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") + JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) +#define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") #elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) #define JSON_HEDLEY_MALLOC __declspec(restrict) #else @@ -1435,30 +1431,30 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(JSON_HEDLEY_PURE) - #undef JSON_HEDLEY_PURE +#undef JSON_HEDLEY_PURE #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + JSON_HEDLEY_GCC_VERSION_CHECK(2, 96, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) # define JSON_HEDLEY_PURE __attribute__((__pure__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) -# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) + # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") #elif defined(__cplusplus) && \ ( \ JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ @@ -1471,72 +1467,72 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(JSON_HEDLEY_CONST) - #undef JSON_HEDLEY_CONST +#undef JSON_HEDLEY_CONST #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_CONST __attribute__((__const__)) + JSON_HEDLEY_GCC_VERSION_CHECK(2, 5, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) +#define JSON_HEDLEY_CONST __attribute__((__const__)) #elif \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_CONST _Pragma("no_side_effect") + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") #else #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE #endif #if defined(JSON_HEDLEY_RESTRICT) - #undef JSON_HEDLEY_RESTRICT +#undef JSON_HEDLEY_RESTRICT #endif #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT restrict +#define JSON_HEDLEY_RESTRICT restrict #elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3, 1, 0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17, 10, 0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 2, 4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8, 1, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8, 0, 0) || \ defined(__clang__) - #define JSON_HEDLEY_RESTRICT __restrict -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT _Restrict +#define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict #else #define JSON_HEDLEY_RESTRICT #endif #if defined(JSON_HEDLEY_INLINE) - #undef JSON_HEDLEY_INLINE +#undef JSON_HEDLEY_INLINE #endif #if \ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ (defined(__cplusplus) && (__cplusplus >= 199711L)) - #define JSON_HEDLEY_INLINE inline +#define JSON_HEDLEY_INLINE inline #elif \ defined(JSON_HEDLEY_GCC_VERSION) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) - #define JSON_HEDLEY_INLINE __inline__ + JSON_HEDLEY_ARM_VERSION_CHECK(6, 2, 0) + #define JSON_HEDLEY_INLINE __inline__ #elif \ JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ @@ -1552,29 +1548,29 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(JSON_HEDLEY_ALWAYS_INLINE) - #undef JSON_HEDLEY_ALWAYS_INLINE +#undef JSON_HEDLEY_ALWAYS_INLINE #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) -# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12, 0, 0) + # define JSON_HEDLEY_ALWAYS_INLINE __forceinline #elif defined(__cplusplus) && \ ( \ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ @@ -1592,29 +1588,29 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(JSON_HEDLEY_NEVER_INLINE) - #undef JSON_HEDLEY_NEVER_INLINE +#undef JSON_HEDLEY_NEVER_INLINE #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) + JSON_HEDLEY_GCC_VERSION_CHECK(4, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 11, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10, 1, 0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15, 12, 0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4, 8, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5, 2, 0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6, 4, 0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 0, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4, 3, 0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 2, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7, 5, 0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1, 2, 0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2, 1, 0) +#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13, 10, 0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) @@ -1630,20 +1626,20 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(JSON_HEDLEY_PRIVATE) - #undef JSON_HEDLEY_PRIVATE +#undef JSON_HEDLEY_PRIVATE #endif #if defined(JSON_HEDLEY_PUBLIC) - #undef JSON_HEDLEY_PUBLIC +#undef JSON_HEDLEY_PUBLIC #endif #if defined(JSON_HEDLEY_IMPORT) - #undef JSON_HEDLEY_IMPORT +#undef JSON_HEDLEY_IMPORT #endif #if defined(_WIN32) || defined(__CYGWIN__) # define JSON_HEDLEY_PRIVATE # define JSON_HEDLEY_PUBLIC __declspec(dllexport) # define JSON_HEDLEY_IMPORT __declspec(dllimport) #else -# if \ + # if \ JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ @@ -1667,30 +1663,30 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(JSON_HEDLEY_NO_THROW) - #undef JSON_HEDLEY_NO_THROW +#undef JSON_HEDLEY_NO_THROW #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) + JSON_HEDLEY_GCC_VERSION_CHECK(3, 3, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) +#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) #elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NO_THROW __declspec(nothrow) + JSON_HEDLEY_MSVC_VERSION_CHECK(13, 1, 0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) #else #define JSON_HEDLEY_NO_THROW #endif #if defined(JSON_HEDLEY_FALL_THROUGH) - #undef JSON_HEDLEY_FALL_THROUGH +#undef JSON_HEDLEY_FALL_THROUGH #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) - #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) + JSON_HEDLEY_GCC_VERSION_CHECK(7, 0, 0) +#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang, fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) #elif defined(__fallthrough) /* SAL */ @@ -1700,20 +1696,20 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(JSON_HEDLEY_RETURNS_NON_NULL) - #undef JSON_HEDLEY_RETURNS_NON_NULL +#undef JSON_HEDLEY_RETURNS_NON_NULL #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) - #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) + JSON_HEDLEY_GCC_VERSION_CHECK(4, 9, 0) +#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) #elif defined(_Ret_notnull_) /* SAL */ - #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ #else #define JSON_HEDLEY_RETURNS_NON_NULL #endif #if defined(JSON_HEDLEY_ARRAY_PARAM) - #undef JSON_HEDLEY_ARRAY_PARAM +#undef JSON_HEDLEY_ARRAY_PARAM #endif #if \ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ @@ -1721,36 +1717,36 @@ JSON_HEDLEY_DIAGNOSTIC_POP !defined(__cplusplus) && \ !defined(JSON_HEDLEY_PGI_VERSION) && \ !defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#define JSON_HEDLEY_ARRAY_PARAM(name) (name) #else - #define JSON_HEDLEY_ARRAY_PARAM(name) +#define JSON_HEDLEY_ARRAY_PARAM(name) #endif #if defined(JSON_HEDLEY_IS_CONSTANT) - #undef JSON_HEDLEY_IS_CONSTANT +#undef JSON_HEDLEY_IS_CONSTANT #endif #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) - #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#undef JSON_HEDLEY_REQUIRE_CONSTEXPR #endif /* JSON_HEDLEY_IS_CONSTEXPR_ is for HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ #if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #undef JSON_HEDLEY_IS_CONSTEXPR_ +#undef JSON_HEDLEY_IS_CONSTEXPR_ #endif #if \ JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) - #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) + JSON_HEDLEY_GCC_VERSION_CHECK(3, 4, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0, 9, 19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4, 1, 0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13, 1, 0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6, 1, 0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5, 10, 0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8, 1, 0) +#define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) #endif #if !defined(__cplusplus) -# if \ + # if \ JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ @@ -1804,88 +1800,88 @@ JSON_HEDLEY_DIAGNOSTIC_POP # endif #endif #if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #if !defined(JSON_HEDLEY_IS_CONSTANT) + #if !defined(JSON_HEDLEY_IS_CONSTANT) #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) #endif #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) #else - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) (0) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#if !defined(JSON_HEDLEY_IS_CONSTANT) +#define JSON_HEDLEY_IS_CONSTANT(expr) (0) +#endif +#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) #endif #if defined(JSON_HEDLEY_BEGIN_C_DECLS) - #undef JSON_HEDLEY_BEGIN_C_DECLS +#undef JSON_HEDLEY_BEGIN_C_DECLS #endif #if defined(JSON_HEDLEY_END_C_DECLS) - #undef JSON_HEDLEY_END_C_DECLS +#undef JSON_HEDLEY_END_C_DECLS #endif #if defined(JSON_HEDLEY_C_DECL) - #undef JSON_HEDLEY_C_DECL +#undef JSON_HEDLEY_C_DECL #endif #if defined(__cplusplus) - #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { - #define JSON_HEDLEY_END_C_DECLS } - #define JSON_HEDLEY_C_DECL extern "C" +#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { +#define JSON_HEDLEY_END_C_DECLS } +#define JSON_HEDLEY_C_DECL extern "C" #else - #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_BEGIN_C_DECLS #define JSON_HEDLEY_END_C_DECLS #define JSON_HEDLEY_C_DECL #endif #if defined(JSON_HEDLEY_STATIC_ASSERT) - #undef JSON_HEDLEY_STATIC_ASSERT +#undef JSON_HEDLEY_STATIC_ASSERT #endif #if \ - !defined(__cplusplus) && ( \ + !defined(__cplusplus) && (\ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6, 0, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) || \ defined(_Static_assert) \ - ) +) # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) #elif \ (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) + JSON_HEDLEY_MSVC_VERSION_CHECK(16, 0, 0) # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) #else # define JSON_HEDLEY_STATIC_ASSERT(expr, message) #endif #if defined(JSON_HEDLEY_NULL) - #undef JSON_HEDLEY_NULL +#undef JSON_HEDLEY_NULL #endif #if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) - #elif defined(NULL) - #define JSON_HEDLEY_NULL NULL +#if __cplusplus >= 201103L +#define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL #else #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) - #endif +#endif #elif defined(NULL) - #define JSON_HEDLEY_NULL NULL + #define JSON_HEDLEY_NULL NULL #else #define JSON_HEDLEY_NULL ((void*) 0) #endif #if defined(JSON_HEDLEY_MESSAGE) - #undef JSON_HEDLEY_MESSAGE +#undef JSON_HEDLEY_MESSAGE #endif #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_MESSAGE(msg) \ + # define JSON_HEDLEY_MESSAGE(msg) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ JSON_HEDLEY_PRAGMA(message msg) \ JSON_HEDLEY_DIAGNOSTIC_POP #elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + JSON_HEDLEY_GCC_VERSION_CHECK(4, 4, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) -#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5, 0, 0) + # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) @@ -1895,33 +1891,33 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(JSON_HEDLEY_WARNING) - #undef JSON_HEDLEY_WARNING +#undef JSON_HEDLEY_WARNING #endif #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_WARNING(msg) \ + # define JSON_HEDLEY_WARNING(msg) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ JSON_HEDLEY_PRAGMA(clang warning msg) \ JSON_HEDLEY_DIAGNOSTIC_POP #elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + JSON_HEDLEY_GCC_VERSION_CHECK(4, 8, 0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18, 4, 0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13, 0, 0) # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15, 0, 0) + # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) #else # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) #endif #if defined(JSON_HEDLEY_REQUIRE) - #undef JSON_HEDLEY_REQUIRE +#undef JSON_HEDLEY_REQUIRE #endif #if defined(JSON_HEDLEY_REQUIRE_MSG) - #undef JSON_HEDLEY_REQUIRE_MSG +#undef JSON_HEDLEY_REQUIRE_MSG #endif #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) -# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") + # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") # define JSON_HEDLEY_REQUIRE(expr) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ @@ -1938,21 +1934,21 @@ JSON_HEDLEY_DIAGNOSTIC_POP # endif #else # define JSON_HEDLEY_REQUIRE(expr) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +# define JSON_HEDLEY_REQUIRE_MSG(expr, msg) #endif #if defined(JSON_HEDLEY_FLAGS) - #undef JSON_HEDLEY_FLAGS +#undef JSON_HEDLEY_FLAGS #endif #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) - #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) #endif #if defined(JSON_HEDLEY_FLAGS_CAST) - #undef JSON_HEDLEY_FLAGS_CAST +#undef JSON_HEDLEY_FLAGS_CAST #endif -#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) -# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19, 0, 0) + # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("warning(disable:188)") \ ((T) (expr)); \ @@ -1963,57 +1959,57 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if defined(JSON_HEDLEY_EMPTY_BASES) - #undef JSON_HEDLEY_EMPTY_BASES +#undef JSON_HEDLEY_EMPTY_BASES #endif -#if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0) - #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#if JSON_HEDLEY_MSVC_VERSION_CHECK(19, 0, 23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20, 0, 0) +#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) #else - #define JSON_HEDLEY_EMPTY_BASES +#define JSON_HEDLEY_EMPTY_BASES #endif /* Remaining macros are deprecated. */ #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK #endif #if defined(__clang__) - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) #else - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major, minor, patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE #endif #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE #endif #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) - #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#undef JSON_HEDLEY_CLANG_HAS_BUILTIN #endif #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) - #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#undef JSON_HEDLEY_CLANG_HAS_FEATURE #endif #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) - #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#undef JSON_HEDLEY_CLANG_HAS_EXTENSION #endif #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE #endif #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) #if defined(JSON_HEDLEY_CLANG_HAS_WARNING) - #undef JSON_HEDLEY_CLANG_HAS_WARNING +#undef JSON_HEDLEY_CLANG_HAS_WARNING #endif #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) @@ -2025,49 +2021,49 @@ JSON_HEDLEY_DIAGNOSTIC_POP // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) - #if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 +#if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" #endif - #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #endif +#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) +#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 +#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" +#endif +#endif #endif // C++ language standard detection #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) - #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_20 #define JSON_HAS_CPP_17 #define JSON_HAS_CPP_14 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 +#define JSON_HAS_CPP_17 +#define JSON_HAS_CPP_14 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 +#define JSON_HAS_CPP_14 #endif // disable float-equal warnings on GCC/clang #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wfloat-equal" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" #endif // disable documentation warnings on clang #if defined(__clang__) - #pragma GCC diagnostic push + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdocumentation" #endif // allow to disable exceptions #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) - #define JSON_INTERNAL_CATCH(exception) catch(exception) +#define JSON_THROW(exception) throw exception +#define JSON_TRY try +#define JSON_CATCH(exception) catch(exception) +#define JSON_INTERNAL_CATCH(exception) catch(exception) #else - #include + #include #define JSON_THROW(exception) std::abort() #define JSON_TRY if(true) #define JSON_CATCH(exception) if(false) @@ -2076,28 +2072,30 @@ JSON_HEDLEY_DIAGNOSTIC_POP // override exception macros #if defined(JSON_THROW_USER) - #undef JSON_THROW + #undef JSON_THROW #define JSON_THROW JSON_THROW_USER #endif #if defined(JSON_TRY_USER) - #undef JSON_TRY + #undef JSON_TRY #define JSON_TRY JSON_TRY_USER #endif #if defined(JSON_CATCH_USER) - #undef JSON_CATCH + #undef JSON_CATCH #define JSON_CATCH JSON_CATCH_USER #undef JSON_INTERNAL_CATCH #define JSON_INTERNAL_CATCH JSON_CATCH_USER #endif #if defined(JSON_INTERNAL_CATCH_USER) - #undef JSON_INTERNAL_CATCH + #undef JSON_INTERNAL_CATCH #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER #endif // allow to override assert #if !defined(JSON_ASSERT) - #include // assert - #define JSON_ASSERT(x) assert(x) + +#include // assert + +#define JSON_ASSERT(x) assert(x) #endif /*! @@ -2150,8 +2148,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP // Macros to simplify conversion from/to types -#define NLOHMANN_JSON_EXPAND( x ) x -#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_EXPAND(x) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME, ...) NAME #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ NLOHMANN_JSON_PASTE64, \ NLOHMANN_JSON_PASTE63, \ @@ -2303,20 +2301,18 @@ JSON_HEDLEY_DIAGNOSTIC_POP inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } #ifndef JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#define JSON_USE_IMPLICIT_CONVERSIONS 1 #endif #if JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_EXPLICIT +#define JSON_EXPLICIT #else - #define JSON_EXPLICIT explicit +#define JSON_EXPLICIT explicit #endif -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { //////////////// // exceptions // //////////////// @@ -2349,32 +2345,29 @@ caught.,exception} @since version 3.0.0 */ -class exception : public std::exception -{ - public: - /// returns the explanatory string - JSON_HEDLEY_RETURNS_NON_NULL - const char* what() const noexcept override - { - return m.what(); - } + class exception : public std::exception { + public: + /// returns the explanatory string + JSON_HEDLEY_RETURNS_NON_NULL + const char *what() const noexcept override { + return m.what(); + } - /// the id of the exception - const int id; + /// the id of the exception + const int id; - protected: - JSON_HEDLEY_NON_NULL(3) - exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char *what_arg) : id(id_), m(what_arg) {} - static std::string name(const std::string& ename, int id_) - { - return "[json.exception." + ename + "." + std::to_string(id_) + "] "; - } + static std::string name(const std::string &ename, int id_) { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } - private: - /// an exception object as storage for error messages - std::runtime_error m; -}; + private: + /// an exception object as storage for error messages + std::runtime_error m; + }; /*! @brief exception indicating a parse error @@ -2421,10 +2414,9 @@ caught.,parse_error} @since version 3.0.0 */ -class parse_error : public exception -{ - public: - /*! + class parse_error : public exception { + public: + /*! @brief create a parse error exception @param[in] id_ the id of the exception @param[in] pos the position where the error occurred (or with @@ -2433,22 +2425,20 @@ class parse_error : public exception @param[in] what_arg the explanatory string @return parse_error object */ - static parse_error create(int id_, const position_t& pos, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + what_arg; - return parse_error(id_, pos.chars_read_total, w.c_str()); - } + static parse_error create(int id_, const position_t &pos, const std::string &what_arg) { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + what_arg; - return parse_error(id_, byte_, w.c_str()); - } + static parse_error create(int id_, std::size_t byte_, const std::string &what_arg) { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + what_arg; + return parse_error(id_, byte_, w.c_str()); + } - /*! + /*! @brief byte index of the parse error The byte index of the last read character in the input file. @@ -2457,18 +2447,17 @@ class parse_error : public exception n+1 is the index of the terminating null byte or the end of file. This also holds true when reading a byte vector (CBOR or MessagePack). */ - const std::size_t byte; + const std::size_t byte; - private: - parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} + private: + parse_error(int id_, std::size_t byte_, const char *what_arg) + : exception(id_, what_arg), byte(byte_) {} - static std::string position_string(const position_t& pos) - { - return " at line " + std::to_string(pos.lines_read + 1) + - ", column " + std::to_string(pos.chars_read_current_line); - } -}; + static std::string position_string(const position_t &pos) { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } + }; /*! @brief exception indicating errors with iterators @@ -2507,20 +2496,18 @@ caught.,invalid_iterator} @since version 3.0.0 */ -class invalid_iterator : public exception -{ - public: - static invalid_iterator create(int id_, const std::string& what_arg) - { - std::string w = exception::name("invalid_iterator", id_) + what_arg; - return invalid_iterator(id_, w.c_str()); - } + class invalid_iterator : public exception { + public: + static invalid_iterator create(int id_, const std::string &what_arg) { + std::string w = exception::name("invalid_iterator", id_) + what_arg; + return invalid_iterator(id_, w.c_str()); + } - private: - JSON_HEDLEY_NON_NULL(3) - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) {} -}; + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char *what_arg) + : exception(id_, what_arg) {} + }; /*! @brief exception indicating executing a member function with a wrong type @@ -2561,19 +2548,17 @@ caught.,type_error} @since version 3.0.0 */ -class type_error : public exception -{ - public: - static type_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("type_error", id_) + what_arg; - return type_error(id_, w.c_str()); - } + class type_error : public exception { + public: + static type_error create(int id_, const std::string &what_arg) { + std::string w = exception::name("type_error", id_) + what_arg; + return type_error(id_, w.c_str()); + } - private: - JSON_HEDLEY_NON_NULL(3) - type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char *what_arg) : exception(id_, what_arg) {} + }; /*! @brief exception indicating access out of the defined range @@ -2608,19 +2593,17 @@ caught.,out_of_range} @since version 3.0.0 */ -class out_of_range : public exception -{ - public: - static out_of_range create(int id_, const std::string& what_arg) - { - std::string w = exception::name("out_of_range", id_) + what_arg; - return out_of_range(id_, w.c_str()); - } + class out_of_range : public exception { + public: + static out_of_range create(int id_, const std::string &what_arg) { + std::string w = exception::name("out_of_range", id_) + what_arg; + return out_of_range(id_, w.c_str()); + } - private: - JSON_HEDLEY_NON_NULL(3) - out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char *what_arg) : exception(id_, what_arg) {} + }; /*! @brief exception indicating other library errors @@ -2646,20 +2629,18 @@ caught.,other_error} @since version 3.0.0 */ -class other_error : public exception -{ - public: - static other_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("other_error", id_) + what_arg; - return other_error(id_, w.c_str()); - } + class other_error : public exception { + public: + static other_error create(int id_, const std::string &what_arg) { + std::string w = exception::name("other_error", id_) + what_arg; + return other_error(id_, w.c_str()); + } - private: - JSON_HEDLEY_NON_NULL(3) - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; -} // namespace detail + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char *what_arg) : exception(id_, what_arg) {} + }; + } // namespace detail } // namespace nlohmann // #include @@ -2670,62 +2651,68 @@ class other_error : public exception #include // size_t #include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { // alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; + template + using enable_if_t = typename std::enable_if::type; -template -using uncvref_t = typename std::remove_cv::type>::type; + template + using uncvref_t = typename std::remove_cv::type>::type; // implementation of C++14 index_sequence and affiliates // source: https://stackoverflow.com/a/32223343 -template -struct index_sequence -{ - using type = index_sequence; - using value_type = std::size_t; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; + template + struct index_sequence { + using type = index_sequence; + using value_type = std::size_t; -template -struct merge_and_renumber; + static constexpr std::size_t size() noexcept { + return sizeof...(Ints); + } + }; -template -struct merge_and_renumber, index_sequence> - : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + template + struct merge_and_renumber; -template -struct make_index_sequence - : merge_and_renumber < typename make_index_sequence < N / 2 >::type, - typename make_index_sequence < N - N / 2 >::type > {}; + template + struct merge_and_renumber, index_sequence> + : index_sequence { + }; -template<> struct make_index_sequence<0> : index_sequence<> {}; -template<> struct make_index_sequence<1> : index_sequence<0> {}; + template + struct make_index_sequence + : merge_and_renumber::type, + typename make_index_sequence::type> { + }; -template -using index_sequence_for = make_index_sequence; + template<> + struct make_index_sequence<0> : index_sequence<> { + }; + template<> + struct make_index_sequence<1> : index_sequence<0> { + }; + + template + using index_sequence_for = make_index_sequence; // dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; + template + struct priority_tag : priority_tag { + }; + template<> + struct priority_tag<0> { + }; // taken from ranges-v3 -template -struct static_const -{ - static constexpr T value{}; -}; + template + struct static_const { + static constexpr T value{}; + }; -template -constexpr T static_const::value; -} // namespace detail + template + constexpr T static_const::value; + } // namespace detail } // namespace nlohmann // #include @@ -2743,64 +2730,57 @@ constexpr T static_const::value; // #include -namespace nlohmann -{ -namespace detail -{ -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; -} // namespace detail +namespace nlohmann { + namespace detail { + template + struct make_void { + using type = void; + }; + template using void_t = typename make_void::type; + } // namespace detail } // namespace nlohmann // #include -namespace nlohmann -{ -namespace detail -{ -template -struct iterator_types {}; +namespace nlohmann { + namespace detail { + template + struct iterator_types { + }; -template -struct iterator_types < - It, - void_t> -{ - using difference_type = typename It::difference_type; - using value_type = typename It::value_type; - using pointer = typename It::pointer; - using reference = typename It::reference; - using iterator_category = typename It::iterator_category; -}; + template + struct iterator_types< + It, + void_t> { + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; + }; // This is required as some compilers implement std::iterator_traits in a way that // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; + template + struct iterator_traits { + }; -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; + template + struct iterator_traits::value >> + : iterator_types { + }; -template -struct iterator_traits::value>> -{ - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; -}; -} // namespace detail + template + struct iterator_traits::value>> { + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T *; + using reference = T &; + }; + } // namespace detail } // namespace nlohmann // #include @@ -2816,56 +2796,56 @@ struct iterator_traits::value>> // 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; -}; +namespace nlohmann { + namespace detail { + struct nonesuch { + nonesuch() = delete; -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; + ~nonesuch() = delete; -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; + nonesuch(nonesuch const &) = delete; -template class Op, class... Args> -using is_detected = typename detector::value_t; + nonesuch(nonesuch const &&) = delete; -template class Op, class... Args> -using detected_t = typename detector::type; + void operator=(nonesuch const &) = delete; -template class Op, class... Args> -using detected_or = detector; + void operator=(nonesuch &&) = delete; + }; -template class Op, class... Args> -using detected_or_t = typename detected_or::type; + template class Op, + class... Args> + struct detector { + using value_t = std::false_type; + using type = Default; + }; -template class Op, class... Args> -using is_detected_exact = std::is_same>; + 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_convertible = - std::is_convertible, To>; -} // namespace detail + template class Op, class... Args> + using is_detected = typename detector::value_t; + + 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 @@ -2883,8 +2863,7 @@ using is_detected_convertible = @see https://github.com/nlohmann @since version 1.0.0 */ -namespace nlohmann -{ +namespace nlohmann { /*! @brief default JSONSerializer template argument @@ -2892,21 +2871,21 @@ 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; + template + struct adl_serializer; -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; + 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 @@ -2919,8 +2898,8 @@ within a JSON document. It can be used with functions `at` and @since version 2.0.0 */ -template -class json_pointer; + template + class json_pointer; /*! @brief default JSON class @@ -2930,10 +2909,10 @@ uses the standard template types. @since version 1.0.0 */ -using json = basic_json<>; + using json = basic_json<>; -template -struct ordered_map; + template + struct ordered_map; /*! @brief ordered JSON class @@ -2942,15 +2921,14 @@ This type preserves the insertion order of object keys. @since version 3.9.0 */ -using ordered_json = basic_json; + using ordered_json = basic_json; } // namespace nlohmann #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ -namespace nlohmann -{ +namespace nlohmann { /*! @brief detail namespace with internal helper functions @@ -2959,8 +2937,7 @@ implementations of some @ref basic_json methods, and meta-programming helpers. @since version 2.1.0 */ -namespace detail -{ + namespace detail { ///////////// // helpers // ///////////// @@ -2974,364 +2951,386 @@ namespace detail // In this case, T has to be properly CV-qualified to constraint the function arguments // (e.g. to_json(BasicJsonType&, const T&)) -template struct is_basic_json : std::false_type {}; + template + struct is_basic_json : std::false_type { + }; -NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct is_basic_json : std::true_type {}; + NLOHMANN_BASIC_JSON_TPL_DECLARATION + struct is_basic_json : std::true_type { + }; ////////////////////// // json_ref helpers // ////////////////////// -template -class json_ref; + template + class json_ref; -template -struct is_json_ref : std::false_type {}; + template + struct is_json_ref : std::false_type { + }; -template -struct is_json_ref> : std::true_type {}; + template + struct is_json_ref> : std::true_type { + }; ////////////////////////// // aliases for detected // ////////////////////////// -template -using mapped_type_t = typename T::mapped_type; + template + using mapped_type_t = typename T::mapped_type; -template -using key_type_t = typename T::key_type; + template + using key_type_t = typename T::key_type; -template -using value_type_t = typename T::value_type; + template + using value_type_t = typename T::value_type; -template -using difference_type_t = typename T::difference_type; + template + using difference_type_t = typename T::difference_type; -template -using pointer_t = typename T::pointer; + template + using pointer_t = typename T::pointer; -template -using reference_t = typename T::reference; + template + using reference_t = typename T::reference; -template -using iterator_category_t = typename T::iterator_category; + template + using iterator_category_t = typename T::iterator_category; -template -using iterator_t = typename T::iterator; + template + using iterator_t = typename T::iterator; -template -using to_json_function = decltype(T::to_json(std::declval()...)); + template + using to_json_function = decltype(T::to_json(std::declval()...)); -template -using from_json_function = decltype(T::from_json(std::declval()...)); + template + using from_json_function = decltype(T::from_json(std::declval()...)); -template -using get_template_function = decltype(std::declval().template get()); + template + using get_template_function = decltype(std::declval().template get()); // trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json : std::false_type {}; + template + struct has_from_json : std::false_type { + }; // trait checking if j.get is valid // use this trait instead of std::is_constructible or std::is_convertible, // both rely on, or make use of implicit conversions, and thus fail when T // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) -template -struct is_getable -{ - static constexpr bool value = is_detected::value; -}; + template + struct is_getable { + static constexpr bool value = is_detected::value; + }; -template -struct has_from_json < BasicJsonType, T, - enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; + template + struct has_from_json::value >> { + using serializer = typename BasicJsonType::template json_serializer; - static constexpr bool value = - is_detected_exact::value; -}; + static constexpr bool value = + is_detected_exact::value; + }; // This trait checks if JSONSerializer::from_json(json const&) exists // this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json : std::false_type {}; + template + struct has_non_default_from_json : std::false_type { + }; -template -struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; + template + struct has_non_default_from_json::value >> { + using serializer = typename BasicJsonType::template json_serializer; - static constexpr bool value = - is_detected_exact::value; -}; + static constexpr bool value = + is_detected_exact::value; + }; // This trait checks if BasicJsonType::json_serializer::to_json exists // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. -template -struct has_to_json : std::false_type {}; + template + struct has_to_json : std::false_type { + }; -template -struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; + template + struct has_to_json::value >> { + using serializer = typename BasicJsonType::template json_serializer; - static constexpr bool value = - is_detected_exact::value; -}; + static constexpr bool value = + is_detected_exact::value; + }; /////////////////// // is_ functions // /////////////////// -template -struct is_iterator_traits : std::false_type {}; + template + struct is_iterator_traits : std::false_type { + }; -template -struct is_iterator_traits> -{ - private: - using traits = iterator_traits; + template + struct is_iterator_traits> { + private: + using traits = iterator_traits; - public: - static constexpr auto value = - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value; -}; + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; + }; // source: https://stackoverflow.com/a/37193089/4116453 -template -struct is_complete_type : std::false_type {}; + template + struct is_complete_type : std::false_type { + }; -template -struct is_complete_type : std::true_type {}; + template + struct is_complete_type : std::true_type { + }; -template -struct is_compatible_object_type_impl : std::false_type {}; + template + struct is_compatible_object_type_impl : std::false_type { + }; -template -struct is_compatible_object_type_impl < - BasicJsonType, CompatibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ + template + struct is_compatible_object_type_impl< + BasicJsonType, CompatibleObjectType, + enable_if_t::value && + is_detected::value >> { - using object_t = typename BasicJsonType::object_t; + using object_t = typename BasicJsonType::object_t; - // macOS's is_constructible does not play well with nonesuch... - static constexpr bool value = - std::is_constructible::value && - std::is_constructible::value; -}; + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + std::is_constructible::value && + std::is_constructible::value; + }; -template -struct is_compatible_object_type - : is_compatible_object_type_impl {}; + template + struct is_compatible_object_type + : is_compatible_object_type_impl { + }; -template -struct is_constructible_object_type_impl : std::false_type {}; + template + struct is_constructible_object_type_impl : std::false_type { + }; -template -struct is_constructible_object_type_impl < - BasicJsonType, ConstructibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; + template + struct is_constructible_object_type_impl< + BasicJsonType, ConstructibleObjectType, + enable_if_t::value && + is_detected::value >> { + using object_t = typename BasicJsonType::object_t; - static constexpr bool value = - (std::is_default_constructible::value && - (std::is_move_assignable::value || - std::is_copy_assignable::value) && - (std::is_constructible::value && - std::is_same < - typename object_t::mapped_type, - typename ConstructibleObjectType::mapped_type >::value)) || - (has_from_json::value || - has_non_default_from_json < - BasicJsonType, - typename ConstructibleObjectType::mapped_type >::value); -}; + static constexpr bool value = + (std::is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (std::is_constructible::value && + std::is_same< + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type>::value)) || + (has_from_json::value || + has_non_default_from_json< + BasicJsonType, + typename ConstructibleObjectType::mapped_type>::value); + }; -template -struct is_constructible_object_type - : is_constructible_object_type_impl {}; + template + struct is_constructible_object_type + : is_constructible_object_type_impl { + }; -template -struct is_compatible_string_type_impl : std::false_type {}; + template + struct is_compatible_string_type_impl : std::false_type { + }; -template -struct is_compatible_string_type_impl < - BasicJsonType, CompatibleStringType, - enable_if_t::value >> -{ - static constexpr auto value = - std::is_constructible::value; -}; + template + struct is_compatible_string_type_impl< + BasicJsonType, CompatibleStringType, + enable_if_t::value >> { + static constexpr auto value = + std::is_constructible::value; + }; -template -struct is_compatible_string_type - : is_compatible_string_type_impl {}; + template + struct is_compatible_string_type + : is_compatible_string_type_impl { + }; -template -struct is_constructible_string_type_impl : std::false_type {}; + template + struct is_constructible_string_type_impl : std::false_type { + }; -template -struct is_constructible_string_type_impl < - BasicJsonType, ConstructibleStringType, - enable_if_t::value >> -{ - static constexpr auto value = - std::is_constructible::value; -}; + template + struct is_constructible_string_type_impl< + BasicJsonType, ConstructibleStringType, + enable_if_t::value >> { + static constexpr auto value = + std::is_constructible::value; + }; -template -struct is_constructible_string_type - : is_constructible_string_type_impl {}; + template + struct is_constructible_string_type + : is_constructible_string_type_impl { + }; -template -struct is_compatible_array_type_impl : std::false_type {}; + template + struct is_compatible_array_type_impl : std::false_type { + }; -template -struct is_compatible_array_type_impl < - BasicJsonType, CompatibleArrayType, - enable_if_t < is_detected::value&& - is_detected::value&& -// This is needed because json_reverse_iterator has a ::iterator type... -// Therefore it is detected as a CompatibleArrayType. -// The real fix would be to have an Iterable concept. - !is_iterator_traits < - iterator_traits>::value >> -{ - static constexpr bool value = - std::is_constructible::value; -}; + template + struct is_compatible_array_type_impl< + BasicJsonType, CompatibleArrayType, + enable_if_t::value && + is_detected::value && + // This is needed because json_reverse_iterator has a ::iterator type... + // Therefore it is detected as a CompatibleArrayType. + // The real fix would be to have an Iterable concept. + !is_iterator_traits< + iterator_traits>::value >> { + static constexpr bool value = + std::is_constructible::value; + }; -template -struct is_compatible_array_type - : is_compatible_array_type_impl {}; + template + struct is_compatible_array_type + : is_compatible_array_type_impl { + }; -template -struct is_constructible_array_type_impl : std::false_type {}; + template + struct is_constructible_array_type_impl : std::false_type { + }; -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t::value >> - : std::true_type {}; + template + struct is_constructible_array_type_impl< + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type { + }; -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t < !std::is_same::value&& - std::is_default_constructible::value&& -(std::is_move_assignable::value || - std::is_copy_assignable::value)&& -is_detected::value&& -is_detected::value&& -is_complete_type < -detected_t>::value >> -{ - static constexpr bool value = - // This is needed because json_reverse_iterator has a ::iterator type, - // furthermore, std::back_insert_iterator (and other iterators) have a - // base class `iterator`... Therefore it is detected as a - // ConstructibleArrayType. The real fix would be to have an Iterable - // concept. - !is_iterator_traits>::value && + template + struct is_constructible_array_type_impl< + BasicJsonType, ConstructibleArrayType, + enable_if_t::value && + std::is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + is_detected::value && + is_detected::value && + is_complete_type< + detected_t>::value >> { + static constexpr bool value = + // This is needed because json_reverse_iterator has a ::iterator type, + // furthermore, std::back_insert_iterator (and other iterators) have a + // base class `iterator`... Therefore it is detected as a + // ConstructibleArrayType. The real fix would be to have an Iterable + // concept. + !is_iterator_traits>::value && - (std::is_same::value || - has_from_json::value || - has_non_default_from_json < - BasicJsonType, typename ConstructibleArrayType::value_type >::value); -}; + (std::is_same::value || + has_from_json::value || + has_non_default_from_json< + BasicJsonType, typename ConstructibleArrayType::value_type>::value); + }; -template -struct is_constructible_array_type - : is_constructible_array_type_impl {}; + template + struct is_constructible_array_type + : is_constructible_array_type_impl { + }; -template -struct is_compatible_integer_type_impl : std::false_type {}; + template + struct is_compatible_integer_type_impl : std::false_type { + }; -template -struct is_compatible_integer_type_impl < - RealIntegerType, CompatibleNumberIntegerType, - enable_if_t < std::is_integral::value&& - std::is_integral::value&& - !std::is_same::value >> -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; + template + struct is_compatible_integer_type_impl< + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t::value && + std::is_integral::value && + !std::is_same::value >> { + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; - static constexpr auto value = - std::is_constructible::value && - CompatibleLimits::is_integer && - RealLimits::is_signed == CompatibleLimits::is_signed; -}; + static constexpr auto value = + std::is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; + }; -template -struct is_compatible_integer_type - : is_compatible_integer_type_impl {}; + template + struct is_compatible_integer_type + : is_compatible_integer_type_impl { + }; -template -struct is_compatible_type_impl: std::false_type {}; + template + struct is_compatible_type_impl : std::false_type { + }; -template -struct is_compatible_type_impl < - BasicJsonType, CompatibleType, - enable_if_t::value >> -{ - static constexpr bool value = - has_to_json::value; -}; + template + struct is_compatible_type_impl< + BasicJsonType, CompatibleType, + enable_if_t::value >> { + static constexpr bool value = + has_to_json::value; + }; -template -struct is_compatible_type - : is_compatible_type_impl {}; + template + struct is_compatible_type + : is_compatible_type_impl { + }; // https://en.cppreference.com/w/cpp/types/conjunction -template struct conjunction : std::true_type { }; -template struct conjunction : B1 { }; -template -struct conjunction -: std::conditional, B1>::type {}; + template + struct conjunction : std::true_type { + }; + template + struct conjunction : B1 { + }; + template + struct conjunction + : std::conditional, B1>::type { + }; -template -struct is_constructible_tuple : std::false_type {}; + template + struct is_constructible_tuple : std::false_type { + }; -template -struct is_constructible_tuple> : conjunction...> {}; -} // namespace detail + template + struct is_constructible_tuple> : conjunction...> { + }; + } // namespace detail } // namespace nlohmann // #include @@ -3342,10 +3341,8 @@ struct is_constructible_tuple> : conjunction // uint8_t #include // string -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /////////////////////////// // JSON type enumeration // /////////////////////////// @@ -3374,19 +3371,18 @@ value with the default value for a given type @since version 1.0.0 */ -enum class value_t : std::uint8_t -{ - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - binary, ///< binary array (ordered collection of bytes) - discarded ///< discarded by the parser callback function -}; + enum class value_t : std::uint8_t { + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function + }; /*! @brief comparison operator for JSON types @@ -3401,405 +3397,343 @@ Returns an ordering that is similar to Python: @since version 1.0.0 */ -inline bool operator<(const value_t lhs, const value_t rhs) noexcept -{ - static constexpr std::array order = {{ - 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, - 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, - 6 /* binary */ - } - }; + inline bool operator<(const value_t lhs, const value_t rhs) noexcept { + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; - const auto l_index = static_cast(lhs); - const auto r_index = static_cast(rhs); - return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; -} -} // namespace detail + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; + } + } // namespace detail } // namespace nlohmann -namespace nlohmann -{ -namespace detail -{ -template -void from_json(const BasicJsonType& j, typename std::nullptr_t& n) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_null())) - { - JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()))); - } - n = nullptr; -} +namespace nlohmann { + namespace detail { + template + void from_json(const BasicJsonType &j, typename std::nullptr_t &n) { + if (JSON_HEDLEY_UNLIKELY(!j.is_null())) { + JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()))); + } + n = nullptr; + } // overloads for basic_json template parameters -template < typename BasicJsonType, typename ArithmeticType, - enable_if_t < std::is_arithmetic::value&& - !std::is_same::value, - int > = 0 > -void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; + template::value && + !std::is_same::value, + int> = 0> + void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val) { + switch (static_cast(j)) { + case value_t::number_unsigned: { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: { + val = static_cast(*j.template get_ptr()); + break; + } + + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); + } } - default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); - } -} + template + void from_json(const BasicJsonType &j, typename BasicJsonType::boolean_t &b) { + if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) { + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); + } + b = *j.template get_ptr(); + } -template -void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) - { - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); - } - b = *j.template get_ptr(); -} + template + void from_json(const BasicJsonType &j, typename BasicJsonType::string_t &s) { + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); + } + s = *j.template get_ptr(); + } -template -void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); - } - s = *j.template get_ptr(); -} + template< + typename BasicJsonType, typename ConstructibleStringType, + enable_if_t< + is_constructible_string_type::value && + !std::is_same::value, + int> = 0> + void from_json(const BasicJsonType &j, ConstructibleStringType &s) { + if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); + } -template < - typename BasicJsonType, typename ConstructibleStringType, - enable_if_t < - is_constructible_string_type::value&& - !std::is_same::value, - int > = 0 > -void from_json(const BasicJsonType& j, ConstructibleStringType& s) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); - } + s = *j.template get_ptr(); + } - s = *j.template get_ptr(); -} + template + void from_json(const BasicJsonType &j, typename BasicJsonType::number_float_t &val) { + get_arithmetic_value(j, val); + } -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) -{ - get_arithmetic_value(j, val); -} + template + void from_json(const BasicJsonType &j, typename BasicJsonType::number_unsigned_t &val) { + get_arithmetic_value(j, val); + } -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) -{ - get_arithmetic_value(j, val); -} + template + void from_json(const BasicJsonType &j, typename BasicJsonType::number_integer_t &val) { + get_arithmetic_value(j, val); + } -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) -{ - get_arithmetic_value(j, val); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, EnumType& e) -{ - typename std::underlying_type::type val; - get_arithmetic_value(j, val); - e = static_cast(val); -} + template::value, int> = 0> + void from_json(const BasicJsonType &j, EnumType &e) { + typename std::underlying_type::type val; + get_arithmetic_value(j, val); + e = static_cast(val); + } // forward_list doesn't have an insert method -template::value, int> = 0> -void from_json(const BasicJsonType& j, std::forward_list& l) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - l.clear(); - std::transform(j.rbegin(), j.rend(), - std::front_inserter(l), [](const BasicJsonType & i) - { - return i.template get(); - }); -} + template::value, int> = 0> + void from_json(const BasicJsonType &j, std::forward_list &l) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + l.clear(); + std::transform(j.rbegin(), j.rend(), + std::front_inserter(l), [](const BasicJsonType &i) { + return i.template get(); + }); + } // valarray doesn't have an insert method -template::value, int> = 0> -void from_json(const BasicJsonType& j, std::valarray& l) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - l.resize(j.size()); - std::transform(j.begin(), j.end(), std::begin(l), - [](const BasicJsonType & elem) - { - return elem.template get(); - }); -} + template::value, int> = 0> + void from_json(const BasicJsonType &j, std::valarray &l) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + l.resize(j.size()); + std::transform(j.begin(), j.end(), std::begin(l), + [](const BasicJsonType &elem) { + return elem.template get(); + }); + } -template -auto from_json(const BasicJsonType& j, T (&arr)[N]) --> decltype(j.template get(), void()) -{ - for (std::size_t i = 0; i < N; ++i) - { - arr[i] = j.at(i).template get(); - } -} + template + auto from_json(const BasicJsonType &j, T (&arr)[N]) + -> decltype(j.template get(), void()) { + for (std::size_t i = 0; i < N; ++i) { + arr[i] = j.at(i).template get(); + } + } -template -void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) -{ - arr = *j.template get_ptr(); -} + template + void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag<3> /*unused*/) { + arr = *j.template get_ptr(); + } -template -auto from_json_array_impl(const BasicJsonType& j, std::array& arr, - priority_tag<2> /*unused*/) --> decltype(j.template get(), void()) -{ - for (std::size_t i = 0; i < N; ++i) - { - arr[i] = j.at(i).template get(); - } -} + template + auto from_json_array_impl(const BasicJsonType &j, std::array &arr, + priority_tag<2> /*unused*/) + -> decltype(j.template get(), void()) { + for (std::size_t i = 0; i < N; ++i) { + arr[i] = j.at(i).template get(); + } + } -template -auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) --> decltype( - arr.reserve(std::declval()), - j.template get(), - void()) -{ - using std::end; + template + auto from_json_array_impl(const BasicJsonType &j, ConstructibleArrayType &arr, priority_tag<1> /*unused*/) + -> decltype( + arr.reserve(std::declval()), + j.template get(), + void()) { + using std::end; - ConstructibleArrayType ret; - ret.reserve(j.size()); - std::transform(j.begin(), j.end(), - std::inserter(ret, end(ret)), [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); - arr = std::move(ret); -} + ConstructibleArrayType ret; + ret.reserve(j.size()); + std::transform(j.begin(), j.end(), + std::inserter(ret, end(ret)), [](const BasicJsonType &i) { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); + } -template -void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, - priority_tag<0> /*unused*/) -{ - using std::end; + template + void from_json_array_impl(const BasicJsonType &j, ConstructibleArrayType &arr, + priority_tag<0> /*unused*/) { + using std::end; - ConstructibleArrayType ret; - std::transform( - j.begin(), j.end(), std::inserter(ret, end(ret)), - [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); - arr = std::move(ret); -} + ConstructibleArrayType ret; + std::transform( + j.begin(), j.end(), std::inserter(ret, end(ret)), + [](const BasicJsonType &i) { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); + } -template < typename BasicJsonType, typename ConstructibleArrayType, - enable_if_t < - is_constructible_array_type::value&& - !is_constructible_object_type::value&& - !is_constructible_string_type::value&& - !std::is_same::value&& - !is_basic_json::value, - int > = 0 > -auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) --> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), -j.template get(), -void()) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + - std::string(j.type_name()))); - } + template::value && + !is_constructible_object_type::value && + !is_constructible_string_type::value && + !std::is_same::value && + !is_basic_json::value, + int> = 0> + auto from_json(const BasicJsonType &j, ConstructibleArrayType &arr) + -> decltype(from_json_array_impl(j, arr, priority_tag<3>{}), + j.template get(), + void()) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW(type_error::create(302, "type must be array, but is " + + std::string(j.type_name()))); + } - from_json_array_impl(j, arr, priority_tag<3> {}); -} + from_json_array_impl(j, arr, priority_tag<3>{}); + } -template -void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()))); - } + template + void from_json(const BasicJsonType &j, typename BasicJsonType::binary_t &bin) { + if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()))); + } - bin = *j.template get_ptr(); -} + bin = *j.template get_ptr(); + } -template::value, int> = 0> -void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_object())) - { - JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); - } + template::value, int> = 0> + void from_json(const BasicJsonType &j, ConstructibleObjectType &obj) { + if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { + JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); + } - ConstructibleObjectType ret; - auto inner_object = j.template get_ptr(); - using value_type = typename ConstructibleObjectType::value_type; - std::transform( - inner_object->begin(), inner_object->end(), - std::inserter(ret, ret.begin()), - [](typename BasicJsonType::object_t::value_type const & p) - { - return value_type(p.first, p.second.template get()); - }); - obj = std::move(ret); -} + ConstructibleObjectType ret; + auto inner_object = j.template get_ptr(); + using value_type = typename ConstructibleObjectType::value_type; + std::transform( + inner_object->begin(), inner_object->end(), + std::inserter(ret, ret.begin()), + [](typename BasicJsonType::object_t::value_type const &p) { + return value_type(p.first, p.second.template get()); + }); + obj = std::move(ret); + } // overload for arithmetic types, not chosen for basic_json template arguments // (BooleanType, etc..); note: Is it really necessary to provide explicit // overloads for boolean_t etc. in case of a custom BooleanType which is not // an arithmetic type? -template < typename BasicJsonType, typename ArithmeticType, - enable_if_t < - std::is_arithmetic::value&& - !std::is_same::value&& - !std::is_same::value&& - !std::is_same::value&& - !std::is_same::value, - int > = 0 > -void from_json(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::boolean: - { - val = static_cast(*j.template get_ptr()); - break; + template::value && + !std::is_same::value && + !std::is_same::value && + !std::is_same::value && + !std::is_same::value, + int> = 0> + void from_json(const BasicJsonType &j, ArithmeticType &val) { + switch (static_cast(j)) { + case value_t::number_unsigned: { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::boolean: { + val = static_cast(*j.template get_ptr()); + break; + } + + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); + } } - default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); - } -} - -template -void from_json(const BasicJsonType& j, std::pair& p) -{ - p = {j.at(0).template get(), j.at(1).template get()}; -} - -template -void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence /*unused*/) -{ - t = std::make_tuple(j.at(Idx).template get::type>()...); -} - -template -void from_json(const BasicJsonType& j, std::tuple& t) -{ - from_json_tuple_impl(j, t, index_sequence_for {}); -} - -template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, - typename = enable_if_t < !std::is_constructible < - typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::map& m) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - m.clear(); - for (const auto& p : j) - { - if (JSON_HEDLEY_UNLIKELY(!p.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); + template + void from_json(const BasicJsonType &j, std::pair &p) { + p = {j.at(0).template get(), j.at(1).template get()}; } - m.emplace(p.at(0).template get(), p.at(1).template get()); - } -} -template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, - typename = enable_if_t < !std::is_constructible < - typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::unordered_map& m) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - m.clear(); - for (const auto& p : j) - { - if (JSON_HEDLEY_UNLIKELY(!p.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); + template + void from_json_tuple_impl(const BasicJsonType &j, Tuple &t, index_sequence /*unused*/) { + t = std::make_tuple(j.at(Idx).template get::type>()...); } - m.emplace(p.at(0).template get(), p.at(1).template get()); - } -} -struct from_json_fn -{ - template - auto operator()(const BasicJsonType& j, T& val) const - noexcept(noexcept(from_json(j, val))) - -> decltype(from_json(j, val), void()) - { - return from_json(j, val); - } -}; -} // namespace detail + template + void from_json(const BasicJsonType &j, std::tuple &t) { + from_json_tuple_impl(j, t, index_sequence_for{}); + } + + template::value >> + void from_json(const BasicJsonType &j, std::map &m) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + m.clear(); + for (const auto &p: j) { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } + } + + template::value >> + void from_json(const BasicJsonType &j, std::unordered_map &m) { + if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + m.clear(); + for (const auto &p: j) { + if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } + } + + struct from_json_fn { + template + auto operator()(const BasicJsonType &j, T &val) const + noexcept(noexcept(from_json(j, val))) + -> decltype(from_json(j, val), void()) { + return from_json(j, val); + } + }; + } // namespace detail /// namespace to hold default `from_json` function /// to see why this is required: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html -namespace -{ -constexpr const auto& from_json = detail::static_const::value; -} // namespace + namespace { + constexpr const auto &from_json = detail::static_const::value; + } // namespace } // namespace nlohmann // #include @@ -3827,172 +3761,160 @@ constexpr const auto& from_json = detail::static_const::va // #include -namespace nlohmann -{ -namespace detail -{ -template -void int_to_string( string_type& target, std::size_t value ) -{ - // For ADL - using std::to_string; - target = to_string(value); -} -template class iteration_proxy_value -{ - public: - using difference_type = std::ptrdiff_t; - using value_type = iteration_proxy_value; - using pointer = value_type * ; - using reference = value_type & ; - using iterator_category = std::input_iterator_tag; - using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; +namespace nlohmann { + namespace detail { + template + void int_to_string(string_type &target, std::size_t value) { + // For ADL + using std::to_string; + target = to_string(value); + } - private: - /// the iterator - IteratorType anchor; - /// an index for arrays (used to create key names) - std::size_t array_index = 0; - /// last stringified array index - mutable std::size_t array_index_last = 0; - /// a string representation of the array index - mutable string_type array_index_str = "0"; - /// an empty string (to return a reference for primitive values) - const string_type empty_str = ""; + template + class iteration_proxy_value { + public: + using difference_type = std::ptrdiff_t; + using value_type = iteration_proxy_value; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::input_iterator_tag; + using string_type = typename std::remove_cv().key())>::type>::type; - public: - explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {} + private: + /// the iterator + IteratorType anchor; + /// an index for arrays (used to create key names) + std::size_t array_index = 0; + /// last stringified array index + mutable std::size_t array_index_last = 0; + /// a string representation of the array index + mutable string_type array_index_str = "0"; + /// an empty string (to return a reference for primitive values) + const string_type empty_str = ""; - /// dereference operator (needed for range-based for) - iteration_proxy_value& operator*() - { - return *this; - } + public: + explicit iteration_proxy_value(IteratorType it) noexcept: anchor(it) {} - /// increment operator (needed for range-based for) - iteration_proxy_value& operator++() - { - ++anchor; - ++array_index; - - return *this; - } - - /// equality operator (needed for InputIterator) - bool operator==(const iteration_proxy_value& o) const - { - return anchor == o.anchor; - } - - /// inequality operator (needed for range-based for) - bool operator!=(const iteration_proxy_value& o) const - { - return anchor != o.anchor; - } - - /// return key of the iterator - const string_type& key() const - { - JSON_ASSERT(anchor.m_object != nullptr); - - switch (anchor.m_object->type()) - { - // use integer array index as key - case value_t::array: - { - if (array_index != array_index_last) - { - int_to_string( array_index_str, array_index ); - array_index_last = array_index; - } - return array_index_str; + /// dereference operator (needed for range-based for) + iteration_proxy_value &operator*() { + return *this; } - // use key from the object - case value_t::object: - return anchor.key(); + /// increment operator (needed for range-based for) + iteration_proxy_value &operator++() { + ++anchor; + ++array_index; - // use an empty key for all primitive types - default: - return empty_str; - } - } + return *this; + } - /// return value of the iterator - typename IteratorType::reference value() const - { - return anchor.value(); - } -}; + /// equality operator (needed for InputIterator) + bool operator==(const iteration_proxy_value &o) const { + return anchor == o.anchor; + } + + /// inequality operator (needed for range-based for) + bool operator!=(const iteration_proxy_value &o) const { + return anchor != o.anchor; + } + + /// return key of the iterator + const string_type &key() const { + JSON_ASSERT(anchor.m_object != nullptr); + + switch (anchor.m_object->type()) { + // use integer array index as key + case value_t::array: { + if (array_index != array_index_last) { + int_to_string(array_index_str, array_index); + array_index_last = array_index; + } + return array_index_str; + } + + // use key from the object + case value_t::object: + return anchor.key(); + + // use an empty key for all primitive types + default: + return empty_str; + } + } + + /// return value of the iterator + typename IteratorType::reference value() const { + return anchor.value(); + } + }; /// proxy class for the items() function -template class iteration_proxy -{ - private: - /// the container to iterate - typename IteratorType::reference container; + template + class iteration_proxy { + private: + /// the container to iterate + typename IteratorType::reference container; - public: - /// construct iteration proxy from a container - explicit iteration_proxy(typename IteratorType::reference cont) noexcept - : container(cont) {} + public: + /// construct iteration proxy from a container + explicit iteration_proxy(typename IteratorType::reference cont) noexcept + : container(cont) {} - /// return iterator begin (needed for range-based for) - iteration_proxy_value begin() noexcept - { - return iteration_proxy_value(container.begin()); - } + /// return iterator begin (needed for range-based for) + iteration_proxy_value begin() noexcept { + return iteration_proxy_value(container.begin()); + } + + /// return iterator end (needed for range-based for) + iteration_proxy_value end() noexcept { + return iteration_proxy_value(container.end()); + } + }; - /// return iterator end (needed for range-based for) - iteration_proxy_value end() noexcept - { - return iteration_proxy_value(container.end()); - } -}; // Structured Bindings Support // For further reference see https://blog.tartanllama.xyz/structured-bindings/ // And see https://github.com/nlohmann/json/pull/1391 -template = 0> -auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) -{ - return i.key(); -} + template = 0> + auto get(const nlohmann::detail::iteration_proxy_value &i) -> decltype(i.key()) { + return i.key(); + } + // Structured Bindings Support // For further reference see https://blog.tartanllama.xyz/structured-bindings/ // And see https://github.com/nlohmann/json/pull/1391 -template = 0> -auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) -{ - return i.value(); -} -} // namespace detail + template = 0> + auto get(const nlohmann::detail::iteration_proxy_value &i) -> decltype(i.value()) { + return i.value(); + } + } // namespace detail } // namespace nlohmann // The Addition to the STD Namespace is required to add // Structured Bindings Support to the iteration_proxy_value class // For further reference see https://blog.tartanllama.xyz/structured-bindings/ // And see https://github.com/nlohmann/json/pull/1391 -namespace std -{ +namespace std { #if defined(__clang__) - // Fix: https://github.com/nlohmann/json/issues/1401 + // 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> - : public std::integral_constant {}; -template -class tuple_element> -{ - public: - using type = decltype( - get(std::declval < - ::nlohmann::detail::iteration_proxy_value> ())); -}; + template + class tuple_size<::nlohmann::detail::iteration_proxy_value> + : public std::integral_constant { + }; + + template + class tuple_element> { + public: + using type = decltype( + get(std::declval< + ::nlohmann::detail::iteration_proxy_value>())); + }; + #if defined(__clang__) - #pragma clang diagnostic pop +#pragma clang diagnostic pop #endif } // namespace std @@ -4003,373 +3925,321 @@ class tuple_element> // #include -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { ////////////////// // constructors // ////////////////// -template struct external_constructor; + template + struct external_constructor; -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept - { - j.m_type = value_t::boolean; - j.m_value = b; - j.assert_invariant(); - } -}; + template<> + struct external_constructor { + template + static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept { + j.m_type = value_t::boolean; + j.m_value = b; + j.assert_invariant(); + } + }; -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) - { - j.m_type = value_t::string; - j.m_value = s; - j.assert_invariant(); - } + template<> + struct external_constructor { + template + static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s) { + j.m_type = value_t::string; + j.m_value = s; + j.assert_invariant(); + } - template - static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) - { - j.m_type = value_t::string; - j.m_value = std::move(s); - j.assert_invariant(); - } + template + static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s) { + j.m_type = value_t::string; + j.m_value = std::move(s); + j.assert_invariant(); + } - template < typename BasicJsonType, typename CompatibleStringType, - enable_if_t < !std::is_same::value, - int > = 0 > - static void construct(BasicJsonType& j, const CompatibleStringType& str) - { - j.m_type = value_t::string; - j.m_value.string = j.template create(str); - j.assert_invariant(); - } -}; + template::value, + int> = 0> + static void construct(BasicJsonType &j, const CompatibleStringType &str) { + j.m_type = value_t::string; + j.m_value.string = j.template create(str); + j.assert_invariant(); + } + }; -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) - { - j.m_type = value_t::binary; - typename BasicJsonType::binary_t value{b}; - j.m_value = value; - j.assert_invariant(); - } + template<> + struct external_constructor { + template + static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b) { + j.m_type = value_t::binary; + typename BasicJsonType::binary_t value{b}; + j.m_value = value; + j.assert_invariant(); + } - template - static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) - { - j.m_type = value_t::binary; - typename BasicJsonType::binary_t value{std::move(b)}; - j.m_value = value; - j.assert_invariant(); - } -}; + template + static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b) { + j.m_type = value_t::binary; + typename BasicJsonType::binary_t value{std::move(b)}; + j.m_value = value; + j.assert_invariant(); + } + }; -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept - { - j.m_type = value_t::number_float; - j.m_value = val; - j.assert_invariant(); - } -}; + template<> + struct external_constructor { + template + static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept { + j.m_type = value_t::number_float; + j.m_value = val; + j.assert_invariant(); + } + }; -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept - { - j.m_type = value_t::number_unsigned; - j.m_value = val; - j.assert_invariant(); - } -}; + template<> + struct external_constructor { + template + static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept { + j.m_type = value_t::number_unsigned; + j.m_value = val; + j.assert_invariant(); + } + }; -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept - { - j.m_type = value_t::number_integer; - j.m_value = val; - j.assert_invariant(); - } -}; + template<> + struct external_constructor { + template + static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept { + j.m_type = value_t::number_integer; + j.m_value = val; + j.assert_invariant(); + } + }; -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) - { - j.m_type = value_t::array; - j.m_value = arr; - j.assert_invariant(); - } + template<> + struct external_constructor { + template + static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr) { + j.m_type = value_t::array; + j.m_value = arr; + j.assert_invariant(); + } - template - static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) - { - j.m_type = value_t::array; - j.m_value = std::move(arr); - j.assert_invariant(); - } + template + static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr) { + j.m_type = value_t::array; + j.m_value = std::move(arr); + j.assert_invariant(); + } - template < typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < !std::is_same::value, - int > = 0 > - static void construct(BasicJsonType& j, const CompatibleArrayType& arr) - { - using std::begin; - using std::end; - j.m_type = value_t::array; - j.m_value.array = j.template create(begin(arr), end(arr)); - j.assert_invariant(); - } + template::value, + int> = 0> + static void construct(BasicJsonType &j, const CompatibleArrayType &arr) { + using std::begin; + using std::end; + j.m_type = value_t::array; + j.m_value.array = j.template create(begin(arr), end(arr)); + j.assert_invariant(); + } - template - static void construct(BasicJsonType& j, const std::vector& arr) - { - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->reserve(arr.size()); - for (const bool x : arr) - { - j.m_value.array->push_back(x); - } - j.assert_invariant(); - } + template + static void construct(BasicJsonType &j, const std::vector &arr) { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); + for (const bool x: arr) { + j.m_value.array->push_back(x); + } + j.assert_invariant(); + } - template::value, int> = 0> - static void construct(BasicJsonType& j, const std::valarray& arr) - { - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->resize(arr.size()); - if (arr.size() > 0) - { - std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); - } - j.assert_invariant(); - } -}; + template::value, int> = 0> + static void construct(BasicJsonType &j, const std::valarray &arr) { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->resize(arr.size()); + if (arr.size() > 0) { + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + } + j.assert_invariant(); + } + }; -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) - { - j.m_type = value_t::object; - j.m_value = obj; - j.assert_invariant(); - } + template<> + struct external_constructor { + template + static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj) { + j.m_type = value_t::object; + j.m_value = obj; + j.assert_invariant(); + } - template - static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) - { - j.m_type = value_t::object; - j.m_value = std::move(obj); - j.assert_invariant(); - } + template + static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj) { + j.m_type = value_t::object; + j.m_value = std::move(obj); + j.assert_invariant(); + } - template < typename BasicJsonType, typename CompatibleObjectType, - enable_if_t < !std::is_same::value, int > = 0 > - static void construct(BasicJsonType& j, const CompatibleObjectType& obj) - { - using std::begin; - using std::end; + template::value, int> = 0> + static void construct(BasicJsonType &j, const CompatibleObjectType &obj) { + using std::begin; + using std::end; - j.m_type = value_t::object; - j.m_value.object = j.template create(begin(obj), end(obj)); - j.assert_invariant(); - } -}; + j.m_type = value_t::object; + j.m_value.object = j.template create(begin(obj), end(obj)); + j.assert_invariant(); + } + }; ///////////// // to_json // ///////////// -template::value, int> = 0> -void to_json(BasicJsonType& j, T b) noexcept -{ - external_constructor::construct(j, b); -} + template::value, int> = 0> + void to_json(BasicJsonType &j, T b) noexcept { + external_constructor::construct(j, b); + } -template::value, int> = 0> -void to_json(BasicJsonType& j, const CompatibleString& s) -{ - external_constructor::construct(j, s); -} + template::value, int> = 0> + void to_json(BasicJsonType &j, const CompatibleString &s) { + external_constructor::construct(j, s); + } -template -void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) -{ - external_constructor::construct(j, std::move(s)); -} + template + void to_json(BasicJsonType &j, typename BasicJsonType::string_t &&s) { + external_constructor::construct(j, std::move(s)); + } -template::value, int> = 0> -void to_json(BasicJsonType& j, FloatType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} + template::value, int> = 0> + void to_json(BasicJsonType &j, FloatType val) noexcept { + external_constructor::construct(j, static_cast(val)); + } -template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} + template::value, int> = 0> + void to_json(BasicJsonType &j, CompatibleNumberUnsignedType val) noexcept { + external_constructor::construct(j, static_cast(val)); + } -template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} + template::value, int> = 0> + void to_json(BasicJsonType &j, CompatibleNumberIntegerType val) noexcept { + external_constructor::construct(j, static_cast(val)); + } -template::value, int> = 0> -void to_json(BasicJsonType& j, EnumType e) noexcept -{ - using underlying_type = typename std::underlying_type::type; - external_constructor::construct(j, static_cast(e)); -} + template::value, int> = 0> + void to_json(BasicJsonType &j, EnumType e) noexcept { + using underlying_type = typename std::underlying_type::type; + external_constructor::construct(j, static_cast(e)); + } -template -void to_json(BasicJsonType& j, const std::vector& e) -{ - external_constructor::construct(j, e); -} + template + void to_json(BasicJsonType &j, const std::vector &e) { + external_constructor::construct(j, e); + } -template < typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < is_compatible_array_type::value&& - !is_compatible_object_type::value&& - !is_compatible_string_type::value&& - !std::is_same::value&& - !is_basic_json::value, - int > = 0 > -void to_json(BasicJsonType& j, const CompatibleArrayType& arr) -{ - external_constructor::construct(j, arr); -} + template::value && + !is_compatible_object_type::value && + !is_compatible_string_type::value && + !std::is_same::value && + !is_basic_json::value, + int> = 0> + void to_json(BasicJsonType &j, const CompatibleArrayType &arr) { + external_constructor::construct(j, arr); + } -template -void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) -{ - external_constructor::construct(j, bin); -} + template + void to_json(BasicJsonType &j, const typename BasicJsonType::binary_t &bin) { + external_constructor::construct(j, bin); + } -template::value, int> = 0> -void to_json(BasicJsonType& j, const std::valarray& arr) -{ - external_constructor::construct(j, std::move(arr)); -} + template::value, int> = 0> + void to_json(BasicJsonType &j, const std::valarray &arr) { + external_constructor::construct(j, std::move(arr)); + } -template -void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) -{ - external_constructor::construct(j, std::move(arr)); -} + template + void to_json(BasicJsonType &j, typename BasicJsonType::array_t &&arr) { + external_constructor::construct(j, std::move(arr)); + } -template < typename BasicJsonType, typename CompatibleObjectType, - enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > -void to_json(BasicJsonType& j, const CompatibleObjectType& obj) -{ - external_constructor::construct(j, obj); -} + template::value && !is_basic_json::value, int> = 0> + void to_json(BasicJsonType &j, const CompatibleObjectType &obj) { + external_constructor::construct(j, obj); + } -template -void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) -{ - external_constructor::construct(j, std::move(obj)); -} + template + void to_json(BasicJsonType &j, typename BasicJsonType::object_t &&obj) { + external_constructor::construct(j, std::move(obj)); + } -template < - typename BasicJsonType, typename T, std::size_t N, - enable_if_t < !std::is_constructible::value, - int > = 0 > -void to_json(BasicJsonType& j, const T(&arr)[N]) -{ - external_constructor::construct(j, arr); -} + template< + typename BasicJsonType, typename T, std::size_t N, + enable_if_t::value, + int> = 0> + void to_json(BasicJsonType &j, const T(&arr)[N]) { + external_constructor::construct(j, arr); + } -template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > -void to_json(BasicJsonType& j, const std::pair& p) -{ - j = { p.first, p.second }; -} + template::value && std::is_constructible::value, int> = 0> + void to_json(BasicJsonType &j, const std::pair &p) { + j = {p.first, p.second}; + } // for https://github.com/nlohmann/json/pull/1134 -template>::value, int> = 0> -void to_json(BasicJsonType& j, const T& b) -{ - j = { {b.key(), b.value()} }; -} + template>::value, int> = 0> + void to_json(BasicJsonType &j, const T &b) { + j = {{b.key(), b.value()}}; + } -template -void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) -{ - j = { std::get(t)... }; -} + template + void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence /*unused*/) { + j = {std::get(t)...}; + } -template::value, int > = 0> -void to_json(BasicJsonType& j, const T& t) -{ - to_json_tuple_impl(j, t, make_index_sequence::value> {}); -} + template::value, int> = 0> + void to_json(BasicJsonType &j, const T &t) { + to_json_tuple_impl(j, t, make_index_sequence::value>{}); + } -struct to_json_fn -{ - template - auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) - -> decltype(to_json(j, std::forward(val)), void()) - { - return to_json(j, std::forward(val)); - } -}; -} // namespace detail + struct to_json_fn { + template + auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward(val)))) + -> decltype(to_json(j, std::forward(val)), void()) { + return to_json(j, std::forward(val)); + } + }; + } // namespace detail /// namespace to hold default `to_json` function -namespace -{ -constexpr const auto& to_json = detail::static_const::value; -} // namespace + namespace { + constexpr const auto &to_json = detail::static_const::value; + } // namespace } // namespace nlohmann -namespace nlohmann -{ +namespace nlohmann { -template -struct adl_serializer -{ - /*! + template + struct adl_serializer { + /*! @brief convert a JSON value to any value type This function is usually called by the `get()` function of the @@ -4378,15 +4248,14 @@ struct adl_serializer @param[in] j JSON value to read from @param[in,out] val value to write to */ - template - static auto from_json(BasicJsonType&& j, ValueType& val) noexcept( + template + static auto from_json(BasicJsonType &&j, ValueType &val) noexcept( noexcept(::nlohmann::from_json(std::forward(j), val))) - -> decltype(::nlohmann::from_json(std::forward(j), val), void()) - { - ::nlohmann::from_json(std::forward(j), val); - } + -> decltype(::nlohmann::from_json(std::forward(j), val), void()) { + ::nlohmann::from_json(std::forward(j), val); + } - /*! + /*! @brief convert any value type to a JSON value This function is usually called by the constructors of the @ref basic_json @@ -4395,14 +4264,13 @@ struct adl_serializer @param[in,out] j JSON value to write to @param[in] val value to read from */ - template - static auto to_json(BasicJsonType& j, ValueType&& val) noexcept( + template + static auto to_json(BasicJsonType &j, ValueType &&val) noexcept( noexcept(::nlohmann::to_json(j, std::forward(val)))) - -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) - { - ::nlohmann::to_json(j, std::forward(val)); - } -}; + -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) { + ::nlohmann::to_json(j, std::forward(val)); + } + }; } // namespace nlohmann @@ -4413,8 +4281,7 @@ struct adl_serializer #include // tie #include // move -namespace nlohmann -{ +namespace nlohmann { /*! @brief an internal type for a backed binary type @@ -4429,49 +4296,37 @@ order to override the binary type. @since version 3.8.0 */ -template -class byte_container_with_subtype : public BinaryType -{ - public: - /// the type of the underlying container - using container_type = BinaryType; + template + class byte_container_with_subtype : public BinaryType { + public: + /// the type of the underlying container + using container_type = BinaryType; - byte_container_with_subtype() noexcept(noexcept(container_type())) - : container_type() - {} + byte_container_with_subtype() noexcept(noexcept(container_type())) + : container_type() {} - byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) - : container_type(b) - {} + byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b))) + : container_type(b) {} - byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) - : container_type(std::move(b)) - {} + byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b)))) + : container_type(std::move(b)) {} - byte_container_with_subtype(const container_type& b, std::uint8_t subtype) noexcept(noexcept(container_type(b))) - : container_type(b) - , m_subtype(subtype) - , m_has_subtype(true) - {} + byte_container_with_subtype(const container_type &b, std::uint8_t subtype) noexcept(noexcept(container_type(b))) + : container_type(b), m_subtype(subtype), m_has_subtype(true) {} - byte_container_with_subtype(container_type&& b, std::uint8_t subtype) noexcept(noexcept(container_type(std::move(b)))) - : container_type(std::move(b)) - , m_subtype(subtype) - , m_has_subtype(true) - {} + byte_container_with_subtype(container_type &&b, std::uint8_t subtype) noexcept(noexcept(container_type(std::move(b)))) + : container_type(std::move(b)), m_subtype(subtype), m_has_subtype(true) {} - bool operator==(const byte_container_with_subtype& rhs) const - { - return std::tie(static_cast(*this), m_subtype, m_has_subtype) == - std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); - } + bool operator==(const byte_container_with_subtype &rhs) const { + return std::tie(static_cast(*this), m_subtype, m_has_subtype) == + std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); + } - bool operator!=(const byte_container_with_subtype& rhs) const - { - return !(rhs == *this); - } + bool operator!=(const byte_container_with_subtype &rhs) const { + return !(rhs == *this); + } - /*! + /*! @brief sets the binary subtype Sets the binary subtype of the value, also flags a binary JSON value as @@ -4489,13 +4344,12 @@ class byte_container_with_subtype : public BinaryType @since version 3.8.0 */ - void set_subtype(std::uint8_t subtype) noexcept - { - m_subtype = subtype; - m_has_subtype = true; - } + void set_subtype(std::uint8_t subtype) noexcept { + m_subtype = subtype; + m_has_subtype = true; + } - /*! + /*! @brief return the binary subtype Returns the numerical subtype of the value if it has a subtype. If it does @@ -4516,12 +4370,11 @@ class byte_container_with_subtype : public BinaryType @since version 3.8.0 */ - constexpr std::uint8_t subtype() const noexcept - { - return m_subtype; - } + constexpr std::uint8_t subtype() const noexcept { + return m_subtype; + } - /*! + /*! @brief return whether the value has a subtype @return whether the value has a subtype @@ -4537,12 +4390,11 @@ class byte_container_with_subtype : public BinaryType @since version 3.8.0 */ - constexpr bool has_subtype() const noexcept - { - return m_has_subtype; - } + constexpr bool has_subtype() const noexcept { + return m_has_subtype; + } - /*! + /*! @brief clears the binary subtype Clears the binary subtype and flags the value as not having a subtype, which @@ -4561,16 +4413,15 @@ class byte_container_with_subtype : public BinaryType @since version 3.8.0 */ - void clear_subtype() noexcept - { - m_subtype = 0; - m_has_subtype = false; - } + void clear_subtype() noexcept { + m_subtype = 0; + m_has_subtype = false; + } - private: - std::uint8_t m_subtype = 0; - bool m_has_subtype = false; -}; + private: + std::uint8_t m_subtype = 0; + bool m_has_subtype = false; + }; } // namespace nlohmann @@ -4586,17 +4437,14 @@ class byte_container_with_subtype : public BinaryType #include // size_t, uint8_t #include // hash -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { // boost::hash_combine -inline std::size_t combine(std::size_t seed, std::size_t h) noexcept -{ - seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); - return seed; -} + inline std::size_t combine(std::size_t seed, std::size_t h) noexcept { + seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); + return seed; + } /*! @brief hash a JSON value @@ -4609,94 +4457,80 @@ null, 0, 0U, and false, etc. @param j JSON value to hash @return hash value of j */ -template -std::size_t hash(const BasicJsonType& j) -{ - using string_t = typename BasicJsonType::string_t; - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; + template + std::size_t hash(const BasicJsonType &j) { + using string_t = typename BasicJsonType::string_t; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; - const auto type = static_cast(j.type()); - switch (j.type()) - { - case BasicJsonType::value_t::null: - case BasicJsonType::value_t::discarded: - { - return combine(type, 0); - } + const auto type = static_cast(j.type()); + switch (j.type()) { + case BasicJsonType::value_t::null: + case BasicJsonType::value_t::discarded: { + return combine(type, 0); + } - case BasicJsonType::value_t::object: - { - auto seed = combine(type, j.size()); - for (const auto& element : j.items()) - { - const auto h = std::hash {}(element.key()); - seed = combine(seed, h); - seed = combine(seed, hash(element.value())); + case BasicJsonType::value_t::object: { + auto seed = combine(type, j.size()); + for (const auto &element: j.items()) { + const auto h = std::hash{}(element.key()); + seed = combine(seed, h); + seed = combine(seed, hash(element.value())); + } + return seed; + } + + case BasicJsonType::value_t::array: { + auto seed = combine(type, j.size()); + for (const auto &element: j) { + seed = combine(seed, hash(element)); + } + return seed; + } + + case BasicJsonType::value_t::string: { + const auto h = std::hash{}(j.template get_ref()); + return combine(type, h); + } + + case BasicJsonType::value_t::boolean: { + const auto h = std::hash{}(j.template get()); + return combine(type, h); + } + + case BasicJsonType::value_t::number_integer: { + const auto h = std::hash{}(j.template get()); + return combine(type, h); + } + + case nlohmann::detail::value_t::number_unsigned: { + const auto h = std::hash{}(j.template get()); + return combine(type, h); + } + + case nlohmann::detail::value_t::number_float: { + const auto h = std::hash{}(j.template get()); + return combine(type, h); + } + + case nlohmann::detail::value_t::binary: { + auto seed = combine(type, j.get_binary().size()); + const auto h = std::hash{}(j.get_binary().has_subtype()); + seed = combine(seed, h); + seed = combine(seed, j.get_binary().subtype()); + for (const auto byte: j.get_binary()) { + seed = combine(seed, std::hash{}(byte)); + } + return seed; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // LCOV_EXCL_LINE } - return seed; } - case BasicJsonType::value_t::array: - { - auto seed = combine(type, j.size()); - for (const auto& element : j) - { - seed = combine(seed, hash(element)); - } - return seed; - } - - case BasicJsonType::value_t::string: - { - const auto h = std::hash {}(j.template get_ref()); - return combine(type, h); - } - - case BasicJsonType::value_t::boolean: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::number_integer: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case nlohmann::detail::value_t::number_unsigned: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case nlohmann::detail::value_t::number_float: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case nlohmann::detail::value_t::binary: - { - auto seed = combine(type, j.get_binary().size()); - const auto h = std::hash {}(j.get_binary().has_subtype()); - seed = combine(seed, h); - seed = combine(seed, j.get_binary().subtype()); - for (const auto byte : j.get_binary()) - { - seed = combine(seed, std::hash {}(byte)); - } - return seed; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } -} - -} // namespace detail + } // namespace detail } // namespace nlohmann // #include @@ -4736,12 +4570,12 @@ std::size_t hash(const BasicJsonType& j) // #include -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /// the supported input formats -enum class input_format_t { json, cbor, msgpack, ubjson, bson }; + enum class input_format_t { + json, cbor, msgpack, ubjson, bson + }; //////////////////// // input adapters // @@ -4751,31 +4585,31 @@ enum class input_format_t { json, cbor, msgpack, ubjson, bson }; Input adapter for stdio file access. This adapter read only 1 byte and do not use any buffer. This adapter is a very low level adapter. */ -class file_input_adapter -{ - public: - using char_type = char; + class file_input_adapter { + public: + using char_type = char; - JSON_HEDLEY_NON_NULL(2) - explicit file_input_adapter(std::FILE* f) noexcept - : m_file(f) - {} + JSON_HEDLEY_NON_NULL(2) + explicit file_input_adapter(std::FILE *f) noexcept + : m_file(f) {} - // make class move-only - file_input_adapter(const file_input_adapter&) = delete; - file_input_adapter(file_input_adapter&&) = default; - file_input_adapter& operator=(const file_input_adapter&) = delete; - file_input_adapter& operator=(file_input_adapter&&) = delete; + // make class move-only + file_input_adapter(const file_input_adapter &) = delete; - std::char_traits::int_type get_character() noexcept - { - return std::fgetc(m_file); - } + file_input_adapter(file_input_adapter &&) = default; - private: - /// the file pointer to read from - std::FILE* m_file; -}; + file_input_adapter &operator=(const file_input_adapter &) = delete; + + file_input_adapter &operator=(file_input_adapter &&) = delete; + + std::char_traits::int_type get_character() noexcept { + return std::fgetc(m_file); + } + + private: + /// the file pointer to read from + std::FILE *m_file; + }; /*! @@ -4787,391 +4621,333 @@ characters following those used in parsing the JSON input. Clears the std::istream flags; any input errors (e.g., EOF) will be detected by the first subsequent call for input from the std::istream. */ -class input_stream_adapter -{ - public: - using char_type = char; + class input_stream_adapter { + public: + using char_type = char; - ~input_stream_adapter() - { - // clear stream flags; we use underlying streambuf I/O, do not - // maintain ifstream flags, except eof - if (is != nullptr) - { - is->clear(is->rdstate() & std::ios::eofbit); - } - } + ~input_stream_adapter() { + // clear stream flags; we use underlying streambuf I/O, do not + // maintain ifstream flags, except eof + if (is != nullptr) { + is->clear(is->rdstate() & std::ios::eofbit); + } + } - explicit input_stream_adapter(std::istream& i) - : is(&i), sb(i.rdbuf()) - {} + explicit input_stream_adapter(std::istream &i) + : is(&i), sb(i.rdbuf()) {} - // delete because of pointer members - input_stream_adapter(const input_stream_adapter&) = delete; - input_stream_adapter& operator=(input_stream_adapter&) = delete; - input_stream_adapter& operator=(input_stream_adapter&& rhs) = delete; + // delete because of pointer members + input_stream_adapter(const input_stream_adapter &) = delete; - input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb) - { - rhs.is = nullptr; - rhs.sb = nullptr; - } + input_stream_adapter &operator=(input_stream_adapter &) = delete; - // std::istream/std::streambuf use std::char_traits::to_int_type, to - // ensure that std::char_traits::eof() and the character 0xFF do not - // end up as the same value, eg. 0xFFFFFFFF. - std::char_traits::int_type get_character() - { - auto res = sb->sbumpc(); - // set eof manually, as we don't use the istream interface. - if (JSON_HEDLEY_UNLIKELY(res == EOF)) - { - is->clear(is->rdstate() | std::ios::eofbit); - } - return res; - } + input_stream_adapter &operator=(input_stream_adapter &&rhs) = delete; - private: - /// the associated input stream - std::istream* is = nullptr; - std::streambuf* sb = nullptr; -}; + input_stream_adapter(input_stream_adapter &&rhs) noexcept: is(rhs.is), sb(rhs.sb) { + rhs.is = nullptr; + rhs.sb = nullptr; + } + + // std::istream/std::streambuf use std::char_traits::to_int_type, to + // ensure that std::char_traits::eof() and the character 0xFF do not + // end up as the same value, eg. 0xFFFFFFFF. + std::char_traits::int_type get_character() { + auto res = sb->sbumpc(); + // set eof manually, as we don't use the istream interface. + if (JSON_HEDLEY_UNLIKELY(res == EOF)) { + is->clear(is->rdstate() | std::ios::eofbit); + } + return res; + } + + private: + /// the associated input stream + std::istream *is = nullptr; + std::streambuf *sb = nullptr; + }; // General-purpose iterator-based adapter. It might not be as fast as // theoretically possible for some containers, but it is extremely versatile. -template -class iterator_input_adapter -{ - public: - using char_type = typename std::iterator_traits::value_type; + template + class iterator_input_adapter { + public: + using char_type = typename std::iterator_traits::value_type; - iterator_input_adapter(IteratorType first, IteratorType last) - : current(std::move(first)), end(std::move(last)) {} + iterator_input_adapter(IteratorType first, IteratorType last) + : current(std::move(first)), end(std::move(last)) {} - typename std::char_traits::int_type get_character() - { - if (JSON_HEDLEY_LIKELY(current != end)) - { - auto result = std::char_traits::to_int_type(*current); - std::advance(current, 1); - return result; - } - else - { - return std::char_traits::eof(); - } - } - - private: - IteratorType current; - IteratorType end; - - template - friend struct wide_string_input_helper; - - bool empty() const - { - return current == end; - } - -}; - - -template -struct wide_string_input_helper; - -template -struct wide_string_input_helper -{ - // UTF-32 - static void fill_buffer(BaseInputAdapter& input, - std::array::int_type, 4>& utf8_bytes, - size_t& utf8_bytes_index, - size_t& utf8_bytes_filled) - { - utf8_bytes_index = 0; - - if (JSON_HEDLEY_UNLIKELY(input.empty())) - { - utf8_bytes[0] = std::char_traits::eof(); - utf8_bytes_filled = 1; - } - else - { - // get the current character - const auto wc = input.get_character(); - - // UTF-32 to UTF-8 encoding - if (wc < 0x80) - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - else if (wc <= 0x7FF) - { - utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); - utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 2; - } - else if (wc <= 0xFFFF) - { - utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 3; - } - else if (wc <= 0x10FFFF) - { - utf8_bytes[0] = static_cast::int_type>(0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[3] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 4; - } - else - { - // unknown character - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - } - } -}; - -template -struct wide_string_input_helper -{ - // UTF-16 - static void fill_buffer(BaseInputAdapter& input, - std::array::int_type, 4>& utf8_bytes, - size_t& utf8_bytes_index, - size_t& utf8_bytes_filled) - { - utf8_bytes_index = 0; - - if (JSON_HEDLEY_UNLIKELY(input.empty())) - { - utf8_bytes[0] = std::char_traits::eof(); - utf8_bytes_filled = 1; - } - else - { - // get the current character - const auto wc = input.get_character(); - - // UTF-16 to UTF-8 encoding - if (wc < 0x80) - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - else if (wc <= 0x7FF) - { - utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u))); - utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 2; - } - else if (0xD800 > wc || wc >= 0xE000) - { - utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u))); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 3; - } - else - { - if (JSON_HEDLEY_UNLIKELY(!input.empty())) - { - const auto wc2 = static_cast(input.get_character()); - const auto charcode = 0x10000u + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); - utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); - utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); - utf8_bytes_filled = 4; + typename std::char_traits::int_type get_character() { + if (JSON_HEDLEY_LIKELY(current != end)) { + auto result = std::char_traits::to_int_type(*current); + std::advance(current, 1); + return result; + } else { + return std::char_traits::eof(); } - else - { - utf8_bytes[0] = static_cast::int_type>(wc); + } + + private: + IteratorType current; + IteratorType end; + + template + friend + struct wide_string_input_helper; + + bool empty() const { + return current == end; + } + + }; + + + template + struct wide_string_input_helper; + + template + struct wide_string_input_helper { + // UTF-32 + static void fill_buffer(BaseInputAdapter &input, + std::array::int_type, 4> &utf8_bytes, + size_t &utf8_bytes_index, + size_t &utf8_bytes_filled) { + utf8_bytes_index = 0; + + if (JSON_HEDLEY_UNLIKELY(input.empty())) { + utf8_bytes[0] = std::char_traits::eof(); utf8_bytes_filled = 1; + } else { + // get the current character + const auto wc = input.get_character(); + + // UTF-32 to UTF-8 encoding + if (wc < 0x80) { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } else if (wc <= 0x7FF) { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 2; + } else if (wc <= 0xFFFF) { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 3; + } else if (wc <= 0x10FFFF) { + utf8_bytes[0] = static_cast::int_type>(0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 4; + } else { + // unknown character + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } } } - } - } -}; + }; + + template + struct wide_string_input_helper { + // UTF-16 + static void fill_buffer(BaseInputAdapter &input, + std::array::int_type, 4> &utf8_bytes, + size_t &utf8_bytes_index, + size_t &utf8_bytes_filled) { + utf8_bytes_index = 0; + + if (JSON_HEDLEY_UNLIKELY(input.empty())) { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } else { + // get the current character + const auto wc = input.get_character(); + + // UTF-16 to UTF-8 encoding + if (wc < 0x80) { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } else if (wc <= 0x7FF) { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 2; + } else if (0xD800 > wc || wc >= 0xE000) { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); + utf8_bytes_filled = 3; + } else { + if (JSON_HEDLEY_UNLIKELY(!input.empty())) { + const auto wc2 = static_cast(input.get_character()); + const auto charcode = 0x10000u + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); + utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); + utf8_bytes_filled = 4; + } else { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } + } + }; // Wraps another input apdater to convert wide character types into individual bytes. -template -class wide_string_input_adapter -{ - public: - using char_type = char; + template + class wide_string_input_adapter { + public: + using char_type = char; - wide_string_input_adapter(BaseInputAdapter base) - : base_adapter(base) {} + wide_string_input_adapter(BaseInputAdapter base) + : base_adapter(base) {} - typename std::char_traits::int_type get_character() noexcept - { - // check if buffer needs to be filled - if (utf8_bytes_index == utf8_bytes_filled) - { - fill_buffer(); + typename std::char_traits::int_type get_character() noexcept { + // check if buffer needs to be filled + if (utf8_bytes_index == utf8_bytes_filled) { + fill_buffer(); - JSON_ASSERT(utf8_bytes_filled > 0); - JSON_ASSERT(utf8_bytes_index == 0); - } + JSON_ASSERT(utf8_bytes_filled > 0); + JSON_ASSERT(utf8_bytes_index == 0); + } - // use buffer - JSON_ASSERT(utf8_bytes_filled > 0); - JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); - return utf8_bytes[utf8_bytes_index++]; - } + // use buffer + JSON_ASSERT(utf8_bytes_filled > 0); + JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); + return utf8_bytes[utf8_bytes_index++]; + } - private: - BaseInputAdapter base_adapter; + private: + BaseInputAdapter base_adapter; - template - void fill_buffer() - { - wide_string_input_helper::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); - } + template + void fill_buffer() { + wide_string_input_helper::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); + } - /// a buffer for UTF-8 bytes - std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; + /// a buffer for UTF-8 bytes + std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; - /// index to the utf8_codes array for the next valid byte - std::size_t utf8_bytes_index = 0; - /// number of valid bytes in the utf8_codes array - std::size_t utf8_bytes_filled = 0; -}; + /// index to the utf8_codes array for the next valid byte + std::size_t utf8_bytes_index = 0; + /// number of valid bytes in the utf8_codes array + std::size_t utf8_bytes_filled = 0; + }; -template -struct iterator_input_adapter_factory -{ - using iterator_type = IteratorType; - using char_type = typename std::iterator_traits::value_type; - using adapter_type = iterator_input_adapter; + template + struct iterator_input_adapter_factory { + using iterator_type = IteratorType; + using char_type = typename std::iterator_traits::value_type; + using adapter_type = iterator_input_adapter; - static adapter_type create(IteratorType first, IteratorType last) - { - return adapter_type(std::move(first), std::move(last)); - } -}; + static adapter_type create(IteratorType first, IteratorType last) { + return adapter_type(std::move(first), std::move(last)); + } + }; -template -struct is_iterator_of_multibyte -{ - using value_type = typename std::iterator_traits::value_type; - enum - { - value = sizeof(value_type) > 1 - }; -}; + template + struct is_iterator_of_multibyte { + using value_type = typename std::iterator_traits::value_type; + enum { + value = sizeof(value_type) > 1 + }; + }; -template -struct iterator_input_adapter_factory::value>> -{ - using iterator_type = IteratorType; - using char_type = typename std::iterator_traits::value_type; - using base_adapter_type = iterator_input_adapter; - using adapter_type = wide_string_input_adapter; + template + struct iterator_input_adapter_factory::value>> { + using iterator_type = IteratorType; + using char_type = typename std::iterator_traits::value_type; + using base_adapter_type = iterator_input_adapter; + using adapter_type = wide_string_input_adapter; - static adapter_type create(IteratorType first, IteratorType last) - { - return adapter_type(base_adapter_type(std::move(first), std::move(last))); - } -}; + static adapter_type create(IteratorType first, IteratorType last) { + return adapter_type(base_adapter_type(std::move(first), std::move(last))); + } + }; // General purpose iterator-based input -template -typename iterator_input_adapter_factory::adapter_type input_adapter(IteratorType first, IteratorType last) -{ - using factory_type = iterator_input_adapter_factory; - return factory_type::create(first, last); -} + template + typename iterator_input_adapter_factory::adapter_type input_adapter(IteratorType first, IteratorType last) { + using factory_type = iterator_input_adapter_factory; + return factory_type::create(first, last); + } // Convenience shorthand from container to iterator -template -auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container))) -{ - // Enable ADL - using std::begin; - using std::end; + template + auto input_adapter(const ContainerType &container) -> decltype(input_adapter(begin(container), end(container))) { + // Enable ADL + using std::begin; + using std::end; - return input_adapter(begin(container), end(container)); -} + return input_adapter(begin(container), end(container)); + } // Special cases with fast paths -inline file_input_adapter input_adapter(std::FILE* file) -{ - return file_input_adapter(file); -} + inline file_input_adapter input_adapter(std::FILE *file) { + return file_input_adapter(file); + } -inline input_stream_adapter input_adapter(std::istream& stream) -{ - return input_stream_adapter(stream); -} + inline input_stream_adapter input_adapter(std::istream &stream) { + return input_stream_adapter(stream); + } -inline input_stream_adapter input_adapter(std::istream&& stream) -{ - return input_stream_adapter(stream); -} + inline input_stream_adapter input_adapter(std::istream &&stream) { + return input_stream_adapter(stream); + } -using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); + using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); // Null-delimited strings, and the like. -template < typename CharT, - typename std::enable_if < - std::is_pointer::value&& - !std::is_array::value&& - std::is_integral::type>::value&& - sizeof(typename std::remove_pointer::type) == 1, - int >::type = 0 > -contiguous_bytes_input_adapter input_adapter(CharT b) -{ - auto length = std::strlen(reinterpret_cast(b)); - const auto* ptr = reinterpret_cast(b); - return input_adapter(ptr, ptr + length); -} + template::value && + !std::is_array::value && + std::is_integral::type>::value && + sizeof(typename std::remove_pointer::type) == 1, + int>::type = 0> + contiguous_bytes_input_adapter input_adapter(CharT b) { + auto length = std::strlen(reinterpret_cast(b)); + const auto *ptr = reinterpret_cast(b); + return input_adapter(ptr, ptr + length); + } -template -auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) -{ - return input_adapter(array, array + N); -} + template + auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) { + return input_adapter(array, array + N); + } // This class only handles inputs of input_buffer_adapter type. // It's required so that expressions like {ptr, len} can be implicitely casted // to the correct adapter. -class span_input_adapter -{ - public: - template < typename CharT, - typename std::enable_if < - std::is_pointer::value&& - std::is_integral::type>::value&& - sizeof(typename std::remove_pointer::type) == 1, - int >::type = 0 > - span_input_adapter(CharT b, std::size_t l) - : ia(reinterpret_cast(b), reinterpret_cast(b) + l) {} + class span_input_adapter { + public: + template::value && + std::is_integral::type>::value && + sizeof(typename std::remove_pointer::type) == 1, + int>::type = 0> + span_input_adapter(CharT b, std::size_t l) + : ia(reinterpret_cast(b), reinterpret_cast(b) + l) {} - template::iterator_category, std::random_access_iterator_tag>::value, - int>::type = 0> - span_input_adapter(IteratorType first, IteratorType last) - : ia(input_adapter(first, last)) {} + template::iterator_category, std::random_access_iterator_tag>::value, + int>::type = 0> + span_input_adapter(IteratorType first, IteratorType last) + : ia(input_adapter(first, last)) {} - contiguous_bytes_input_adapter&& get() - { - return std::move(ia); - } + contiguous_bytes_input_adapter &&get() { + return std::move(ia); + } - private: - contiguous_bytes_input_adapter ia; -}; -} // namespace detail + private: + contiguous_bytes_input_adapter ia; + }; + } // namespace detail } // namespace nlohmann // #include @@ -5187,8 +4963,7 @@ class span_input_adapter // #include -namespace nlohmann -{ +namespace nlohmann { /*! @brief SAX interface @@ -5198,119 +4973,117 @@ Each function is called in different situations while the input is parsed. The boolean return value informs the parser whether to continue processing the input. */ -template -struct json_sax -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; + template + struct json_sax { + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; - /*! + /*! @brief a null value was read @return whether parsing should proceed */ - virtual bool null() = 0; + virtual bool null() = 0; - /*! + /*! @brief a boolean value was read @param[in] val boolean value @return whether parsing should proceed */ - virtual bool boolean(bool val) = 0; + virtual bool boolean(bool val) = 0; - /*! + /*! @brief an integer number was read @param[in] val integer value @return whether parsing should proceed */ - virtual bool number_integer(number_integer_t val) = 0; + virtual bool number_integer(number_integer_t val) = 0; - /*! + /*! @brief an unsigned integer number was read @param[in] val unsigned integer value @return whether parsing should proceed */ - virtual bool number_unsigned(number_unsigned_t val) = 0; + virtual bool number_unsigned(number_unsigned_t val) = 0; - /*! + /*! @brief an floating-point number was read @param[in] val floating-point value @param[in] s raw token value @return whether parsing should proceed */ - virtual bool number_float(number_float_t val, const string_t& s) = 0; + virtual bool number_float(number_float_t val, const string_t &s) = 0; - /*! + /*! @brief a string was read @param[in] val string value @return whether parsing should proceed @note It is safe to move the passed string. */ - virtual bool string(string_t& val) = 0; + virtual bool string(string_t &val) = 0; - /*! + /*! @brief a binary string was read @param[in] val binary value @return whether parsing should proceed @note It is safe to move the passed binary. */ - virtual bool binary(binary_t& val) = 0; + virtual bool binary(binary_t &val) = 0; - /*! + /*! @brief the beginning of an object was read @param[in] elements number of object elements or -1 if unknown @return whether parsing should proceed @note binary formats may report the number of elements */ - virtual bool start_object(std::size_t elements) = 0; + virtual bool start_object(std::size_t elements) = 0; - /*! + /*! @brief an object key was read @param[in] val object key @return whether parsing should proceed @note It is safe to move the passed string. */ - virtual bool key(string_t& val) = 0; + virtual bool key(string_t &val) = 0; - /*! + /*! @brief the end of an object was read @return whether parsing should proceed */ - virtual bool end_object() = 0; + virtual bool end_object() = 0; - /*! + /*! @brief the beginning of an array was read @param[in] elements number of array elements or -1 if unknown @return whether parsing should proceed @note binary formats may report the number of elements */ - virtual bool start_array(std::size_t elements) = 0; + virtual bool start_array(std::size_t elements) = 0; - /*! + /*! @brief the end of an array was read @return whether parsing should proceed */ - virtual bool end_array() = 0; + virtual bool end_array() = 0; - /*! + /*! @brief a parse error occurred @param[in] position the position in the input where the error occurs @param[in] last_token the last read token @param[in] ex an exception object describing the error @return whether parsing should proceed (must return false) */ - virtual bool parse_error(std::size_t position, - const std::string& last_token, - const detail::exception& ex) = 0; + virtual bool parse_error(std::size_t position, + const std::string &last_token, + const detail::exception &ex) = 0; - virtual ~json_sax() = default; -}; + virtual ~json_sax() = default; + }; -namespace detail -{ + namespace detail { /*! @brief SAX implementation to create a JSON value from SAX events @@ -5324,378 +5097,337 @@ constructor contains the parsed value. @tparam BasicJsonType the JSON type */ -template -class json_sax_dom_parser -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; + template + class json_sax_dom_parser { + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; - /*! + /*! @param[in, out] r reference to a JSON value that is manipulated while parsing @param[in] allow_exceptions_ whether parse errors yield exceptions */ - explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) - : root(r), allow_exceptions(allow_exceptions_) - {} + explicit json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_ = true) + : root(r), allow_exceptions(allow_exceptions_) {} - // make class move-only - json_sax_dom_parser(const json_sax_dom_parser&) = delete; - json_sax_dom_parser(json_sax_dom_parser&&) = default; - json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; - json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; - ~json_sax_dom_parser() = default; + // make class move-only + json_sax_dom_parser(const json_sax_dom_parser &) = delete; - bool null() - { - handle_value(nullptr); - return true; - } + json_sax_dom_parser(json_sax_dom_parser &&) = default; - bool boolean(bool val) - { - handle_value(val); - return true; - } + json_sax_dom_parser &operator=(const json_sax_dom_parser &) = delete; - bool number_integer(number_integer_t val) - { - handle_value(val); - return true; - } + json_sax_dom_parser &operator=(json_sax_dom_parser &&) = default; - bool number_unsigned(number_unsigned_t val) - { - handle_value(val); - return true; - } + ~json_sax_dom_parser() = default; - bool number_float(number_float_t val, const string_t& /*unused*/) - { - handle_value(val); - return true; - } + bool null() { + handle_value(nullptr); + return true; + } - bool string(string_t& val) - { - handle_value(val); - return true; - } + bool boolean(bool val) { + handle_value(val); + return true; + } - bool binary(binary_t& val) - { - handle_value(std::move(val)); - return true; - } + bool number_integer(number_integer_t val) { + handle_value(val); + return true; + } - bool start_object(std::size_t len) - { - ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); + bool number_unsigned(number_unsigned_t val) { + handle_value(val); + return true; + } - if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, - "excessive object size: " + std::to_string(len))); - } + bool number_float(number_float_t val, const string_t & /*unused*/) { + handle_value(val); + return true; + } - return true; - } + bool string(string_t &val) { + handle_value(val); + return true; + } - bool key(string_t& val) - { - // add null at given key and store the reference for later - object_element = &(ref_stack.back()->m_value.object->operator[](val)); - return true; - } + bool binary(binary_t &val) { + handle_value(std::move(val)); + return true; + } - bool end_object() - { - ref_stack.pop_back(); - return true; - } + bool start_object(std::size_t len) { + ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); - bool start_array(std::size_t len) - { - ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); + if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { + JSON_THROW(out_of_range::create(408, + "excessive object size: " + std::to_string(len))); + } - if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, - "excessive array size: " + std::to_string(len))); - } + return true; + } - return true; - } + bool key(string_t &val) { + // add null at given key and store the reference for later + object_element = &(ref_stack.back()->m_value.object->operator[](val)); + return true; + } - bool end_array() - { - ref_stack.pop_back(); - return true; - } + bool end_object() { + ref_stack.pop_back(); + return true; + } - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) - { - errored = true; - static_cast(ex); - if (allow_exceptions) - { - JSON_THROW(ex); - } - return false; - } + bool start_array(std::size_t len) { + ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); - constexpr bool is_errored() const - { - return errored; - } + if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { + JSON_THROW(out_of_range::create(408, + "excessive array size: " + std::to_string(len))); + } - private: - /*! + return true; + } + + bool end_array() { + ref_stack.pop_back(); + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string & /*unused*/, + const Exception &ex) { + errored = true; + static_cast(ex); + if (allow_exceptions) { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const { + return errored; + } + + private: + /*! @invariant If the ref stack is empty, then the passed value will be the new root. @invariant If the ref stack contains a value, then it is an array or an object to which we can add elements */ - template - JSON_HEDLEY_RETURNS_NON_NULL - BasicJsonType* handle_value(Value&& v) - { - if (ref_stack.empty()) - { - root = BasicJsonType(std::forward(v)); - return &root; - } - - JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - - 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()); - } - - JSON_ASSERT(ref_stack.back()->is_object()); - JSON_ASSERT(object_element); - *object_element = BasicJsonType(std::forward(v)); - return object_element; - } - - /// the parsed JSON value - BasicJsonType& root; - /// stack to model hierarchy of values - std::vector ref_stack {}; - /// helper to hold the reference for the next object element - BasicJsonType* object_element = nullptr; - /// whether a syntax error occurred - bool errored = false; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; -}; - -template -class json_sax_dom_callback_parser -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using parser_callback_t = typename BasicJsonType::parser_callback_t; - using parse_event_t = typename BasicJsonType::parse_event_t; - - json_sax_dom_callback_parser(BasicJsonType& r, - const parser_callback_t cb, - const bool allow_exceptions_ = true) - : root(r), callback(cb), allow_exceptions(allow_exceptions_) - { - keep_stack.push_back(true); - } - - // make class move-only - json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; - json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; - ~json_sax_dom_callback_parser() = default; - - bool null() - { - handle_value(nullptr); - return true; - } - - bool boolean(bool val) - { - handle_value(val); - return true; - } - - bool number_integer(number_integer_t val) - { - handle_value(val); - return true; - } - - bool number_unsigned(number_unsigned_t val) - { - handle_value(val); - return true; - } - - bool number_float(number_float_t val, const string_t& /*unused*/) - { - handle_value(val); - return true; - } - - bool string(string_t& val) - { - handle_value(val); - return true; - } - - bool binary(binary_t& val) - { - handle_value(std::move(val)); - return true; - } - - bool start_object(std::size_t len) - { - // check callback for object start - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); - keep_stack.push_back(keep); - - auto val = handle_value(BasicJsonType::value_t::object, true); - ref_stack.push_back(val.second); - - // check object limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len))); - } - - return true; - } - - bool key(string_t& val) - { - BasicJsonType k = BasicJsonType(val); - - // check callback for key - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); - key_keep_stack.push_back(keep); - - // 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); - } - - return true; - } - - bool end_object() - { - if (ref_stack.back() && !callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) - { - // discard object - *ref_stack.back() = discarded; - } - - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(!keep_stack.empty()); - ref_stack.pop_back(); - keep_stack.pop_back(); - - if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) - { - // remove discarded value - for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) - { - if (it->is_discarded()) - { - ref_stack.back()->erase(it); - break; + template + JSON_HEDLEY_RETURNS_NON_NULL + BasicJsonType *handle_value(Value &&v) { + if (ref_stack.empty()) { + root = BasicJsonType(std::forward(v)); + return &root; } + + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + 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()); + } + + JSON_ASSERT(ref_stack.back()->is_object()); + JSON_ASSERT(object_element); + *object_element = BasicJsonType(std::forward(v)); + return object_element; } - } - return true; - } + /// the parsed JSON value + BasicJsonType &root; + /// stack to model hierarchy of values + std::vector ref_stack{}; + /// helper to hold the reference for the next object element + BasicJsonType *object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + }; - bool start_array(std::size_t len) - { - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); - keep_stack.push_back(keep); + template + class json_sax_dom_callback_parser { + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using parser_callback_t = typename BasicJsonType::parser_callback_t; + using parse_event_t = typename BasicJsonType::parse_event_t; - auto val = handle_value(BasicJsonType::value_t::array, true); - ref_stack.push_back(val.second); - - // check array limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len))); - } - - return true; - } - - bool end_array() - { - bool keep = true; - - if (ref_stack.back()) - { - keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); - if (!keep) - { - // discard array - *ref_stack.back() = discarded; + json_sax_dom_callback_parser(BasicJsonType &r, + const parser_callback_t cb, + const bool allow_exceptions_ = true) + : root(r), callback(cb), allow_exceptions(allow_exceptions_) { + keep_stack.push_back(true); } - } - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(!keep_stack.empty()); - ref_stack.pop_back(); - keep_stack.pop_back(); + // make class move-only + json_sax_dom_callback_parser(const json_sax_dom_callback_parser &) = delete; - // remove discarded value - if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->pop_back(); - } + json_sax_dom_callback_parser(json_sax_dom_callback_parser &&) = default; - return true; - } + json_sax_dom_callback_parser &operator=(const json_sax_dom_callback_parser &) = delete; - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) - { - errored = true; - static_cast(ex); - if (allow_exceptions) - { - JSON_THROW(ex); - } - return false; - } + json_sax_dom_callback_parser &operator=(json_sax_dom_callback_parser &&) = default; - constexpr bool is_errored() const - { - return errored; - } + ~json_sax_dom_callback_parser() = default; - private: - /*! + bool null() { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t & /*unused*/) { + handle_value(val); + return true; + } + + bool string(string_t &val) { + handle_value(val); + return true; + } + + bool binary(binary_t &val) { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) { + // check callback for object start + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::object, true); + ref_stack.push_back(val.second); + + // check object limit + if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len))); + } + + return true; + } + + bool key(string_t &val) { + BasicJsonType k = BasicJsonType(val); + + // check callback for key + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); + key_keep_stack.push_back(keep); + + // 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); + } + + return true; + } + + bool end_object() { + if (ref_stack.back() && !callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) { + // discard object + *ref_stack.back() = discarded; + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) { + // remove discarded value + for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) { + if (it->is_discarded()) { + ref_stack.back()->erase(it); + break; + } + } + } + + return true; + } + + bool start_array(std::size_t len) { + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::array, true); + ref_stack.push_back(val.second); + + // check array limit + if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len))); + } + + return true; + } + + bool end_array() { + bool keep = true; + + if (ref_stack.back()) { + keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); + if (!keep) { + // discard array + *ref_stack.back() = discarded; + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + // remove discarded value + if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) { + ref_stack.back()->m_value.array->pop_back(); + } + + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string & /*unused*/, + const Exception &ex) { + errored = true; + static_cast(ex); + if (allow_exceptions) { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const { + return errored; + } + + private: + /*! @param[in] v value to add to the JSON value we build during parsing @param[in] skip_callback whether we should skip calling the callback function; this is required after start_array() and @@ -5710,166 +5442,145 @@ class json_sax_dom_callback_parser @return pair of boolean (whether value should be kept) and pointer (to the passed value in the ref_stack hierarchy; nullptr if not kept) */ - template - std::pair handle_value(Value&& v, const bool skip_callback = false) - { - JSON_ASSERT(!keep_stack.empty()); + template + std::pair handle_value(Value &&v, const bool skip_callback = false) { + JSON_ASSERT(!keep_stack.empty()); - // do not handle this value if we know it would be added to a discarded - // container - if (!keep_stack.back()) - { - return {false, nullptr}; - } + // do not handle this value if we know it would be added to a discarded + // container + if (!keep_stack.back()) { + return {false, nullptr}; + } - // create value - auto value = BasicJsonType(std::forward(v)); + // create value + auto value = BasicJsonType(std::forward(v)); - // check callback - const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); + // check callback + const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); - // do not handle this value if we just learnt it shall be discarded - if (!keep) - { - return {false, nullptr}; - } + // do not handle this value if we just learnt it shall be discarded + if (!keep) { + return {false, nullptr}; + } - if (ref_stack.empty()) - { - root = std::move(value); - return {true, &root}; - } + if (ref_stack.empty()) { + root = std::move(value); + return {true, &root}; + } - // skip this value if we already decided to skip the parent - // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) - if (!ref_stack.back()) - { - return {false, nullptr}; - } + // skip this value if we already decided to skip the parent + // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) + if (!ref_stack.back()) { + return {false, nullptr}; + } - // we now only expect arrays and objects - JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + // we now only expect arrays and objects + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - // array - if (ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->push_back(std::move(value)); - return {true, &(ref_stack.back()->m_value.array->back())}; - } + // array + if (ref_stack.back()->is_array()) { + ref_stack.back()->m_value.array->push_back(std::move(value)); + return {true, &(ref_stack.back()->m_value.array->back())}; + } - // object - JSON_ASSERT(ref_stack.back()->is_object()); - // check if we should store an element for the current key - JSON_ASSERT(!key_keep_stack.empty()); - const bool store_element = key_keep_stack.back(); - key_keep_stack.pop_back(); + // object + JSON_ASSERT(ref_stack.back()->is_object()); + // check if we should store an element for the current key + JSON_ASSERT(!key_keep_stack.empty()); + const bool store_element = key_keep_stack.back(); + key_keep_stack.pop_back(); - if (!store_element) - { - return {false, nullptr}; - } + if (!store_element) { + return {false, nullptr}; + } - JSON_ASSERT(object_element); - *object_element = std::move(value); - return {true, object_element}; - } + JSON_ASSERT(object_element); + *object_element = std::move(value); + return {true, object_element}; + } - /// the parsed JSON value - BasicJsonType& root; - /// stack to model hierarchy of values - std::vector ref_stack {}; - /// stack to manage which values to keep - std::vector keep_stack {}; - /// stack to manage which object keys to keep - std::vector key_keep_stack {}; - /// helper to hold the reference for the next object element - BasicJsonType* object_element = nullptr; - /// whether a syntax error occurred - bool errored = false; - /// callback function - const parser_callback_t callback = nullptr; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; - /// a discarded value for the callback - BasicJsonType discarded = BasicJsonType::value_t::discarded; -}; + /// the parsed JSON value + BasicJsonType &root; + /// stack to model hierarchy of values + std::vector ref_stack{}; + /// stack to manage which values to keep + std::vector keep_stack{}; + /// stack to manage which object keys to keep + std::vector key_keep_stack{}; + /// helper to hold the reference for the next object element + BasicJsonType *object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// callback function + const parser_callback_t callback = nullptr; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + /// a discarded value for the callback + BasicJsonType discarded = BasicJsonType::value_t::discarded; + }; -template -class json_sax_acceptor -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; + template + class json_sax_acceptor { + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; - bool null() - { - return true; - } + bool null() { + return true; + } - bool boolean(bool /*unused*/) - { - return true; - } + bool boolean(bool /*unused*/) { + return true; + } - bool number_integer(number_integer_t /*unused*/) - { - return true; - } + bool number_integer(number_integer_t /*unused*/) { + return true; + } - bool number_unsigned(number_unsigned_t /*unused*/) - { - return true; - } + bool number_unsigned(number_unsigned_t /*unused*/) { + return true; + } - bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) - { - return true; - } + bool number_float(number_float_t /*unused*/, const string_t & /*unused*/) { + return true; + } - bool string(string_t& /*unused*/) - { - return true; - } + bool string(string_t & /*unused*/) { + return true; + } - bool binary(binary_t& /*unused*/) - { - return true; - } + bool binary(binary_t & /*unused*/) { + return true; + } - bool start_object(std::size_t /*unused*/ = std::size_t(-1)) - { - return true; - } + bool start_object(std::size_t /*unused*/ = std::size_t(-1)) { + return true; + } - bool key(string_t& /*unused*/) - { - return true; - } + bool key(string_t & /*unused*/) { + return true; + } - bool end_object() - { - return true; - } + bool end_object() { + return true; + } - bool start_array(std::size_t /*unused*/ = std::size_t(-1)) - { - return true; - } + bool start_array(std::size_t /*unused*/ = std::size_t(-1)) { + return true; + } - bool end_array() - { - return true; - } + bool end_array() { + return true; + } - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) - { - return false; - } -}; -} // namespace detail + bool parse_error(std::size_t /*unused*/, const std::string & /*unused*/, const detail::exception & /*unused*/) { + return false; + } + }; + } // namespace detail } // namespace nlohmann @@ -5893,136 +5604,130 @@ class json_sax_acceptor // #include -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /////////// // lexer // /////////// -template -class lexer_base -{ - public: - /// token types for the parser - enum class token_type - { - uninitialized, ///< indicating the scanner is uninitialized - literal_true, ///< the `true` literal - literal_false, ///< the `false` literal - literal_null, ///< the `null` literal - value_string, ///< a string -- use get_string() for actual value - value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value - value_integer, ///< a signed integer -- use get_number_integer() for actual value - value_float, ///< an floating point number -- use get_number_float() for actual value - begin_array, ///< the character for array begin `[` - begin_object, ///< the character for object begin `{` - end_array, ///< the character for array end `]` - end_object, ///< the character for object end `}` - name_separator, ///< the name separator `:` - value_separator, ///< the value separator `,` - parse_error, ///< indicating a parse error - end_of_input, ///< indicating the end of the input buffer - literal_or_value ///< a literal or the begin of a value (only for diagnostics) - }; + template + class lexer_base { + public: + /// token types for the parser + enum class token_type { + uninitialized, ///< indicating the scanner is uninitialized + literal_true, ///< the `true` literal + literal_false, ///< the `false` literal + literal_null, ///< the `null` literal + value_string, ///< a string -- use get_string() for actual value + value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value + value_integer, ///< a signed integer -- use get_number_integer() for actual value + value_float, ///< an floating point number -- use get_number_float() for actual value + begin_array, ///< the character for array begin `[` + begin_object, ///< the character for object begin `{` + end_array, ///< the character for array end `]` + end_object, ///< the character for object end `}` + name_separator, ///< the name separator `:` + value_separator, ///< the value separator `,` + parse_error, ///< indicating a parse error + end_of_input, ///< indicating the end of the input buffer + literal_or_value ///< a literal or the begin of a value (only for diagnostics) + }; + + /// return name of values of type token_type (only used for errors) + JSON_HEDLEY_RETURNS_NON_NULL + JSON_HEDLEY_CONST + static const char *token_type_name(const token_type t) noexcept { + switch (t) { + case token_type::uninitialized: + return ""; + case token_type::literal_true: + return "true literal"; + case token_type::literal_false: + return "false literal"; + case token_type::literal_null: + return "null literal"; + case token_type::value_string: + return "string literal"; + case token_type::value_unsigned: + case token_type::value_integer: + case token_type::value_float: + return "number literal"; + case token_type::begin_array: + return "'['"; + case token_type::begin_object: + return "'{'"; + case token_type::end_array: + return "']'"; + case token_type::end_object: + return "'}'"; + case token_type::name_separator: + return "':'"; + case token_type::value_separator: + return "','"; + case token_type::parse_error: + return ""; + case token_type::end_of_input: + return "end of input"; + case token_type::literal_or_value: + return "'[', '{', or a literal"; + // LCOV_EXCL_START + default: // catch non-enum values + return "unknown token"; + // LCOV_EXCL_STOP + } + } + }; - /// return name of values of type token_type (only used for errors) - JSON_HEDLEY_RETURNS_NON_NULL - JSON_HEDLEY_CONST - static const char* token_type_name(const token_type t) noexcept - { - switch (t) - { - case token_type::uninitialized: - return ""; - case token_type::literal_true: - return "true literal"; - case token_type::literal_false: - return "false literal"; - case token_type::literal_null: - return "null literal"; - case token_type::value_string: - return "string literal"; - case token_type::value_unsigned: - case token_type::value_integer: - case token_type::value_float: - return "number literal"; - case token_type::begin_array: - return "'['"; - case token_type::begin_object: - return "'{'"; - case token_type::end_array: - return "']'"; - case token_type::end_object: - return "'}'"; - case token_type::name_separator: - return "':'"; - case token_type::value_separator: - return "','"; - case token_type::parse_error: - return ""; - case token_type::end_of_input: - return "end of input"; - case token_type::literal_or_value: - return "'[', '{', or a literal"; - // LCOV_EXCL_START - default: // catch non-enum values - return "unknown token"; - // LCOV_EXCL_STOP - } - } -}; /*! @brief lexical analysis This class organizes the lexical analysis during JSON deserialization. */ -template -class lexer : public lexer_base -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using char_type = typename InputAdapterType::char_type; - using char_int_type = typename std::char_traits::int_type; + template + class lexer : public lexer_base { + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using char_type = typename InputAdapterType::char_type; + using char_int_type = typename std::char_traits::int_type; - public: - using token_type = typename lexer_base::token_type; + public: + using token_type = typename lexer_base::token_type; - explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) - : ia(std::move(adapter)) - , ignore_comments(ignore_comments_) - , decimal_point_char(static_cast(get_decimal_point())) - {} + explicit lexer(InputAdapterType &&adapter, bool ignore_comments_ = false) + : ia(std::move(adapter)), ignore_comments(ignore_comments_), decimal_point_char(static_cast(get_decimal_point())) {} - // delete because of pointer members - lexer(const lexer&) = delete; - lexer(lexer&&) = default; - lexer& operator=(lexer&) = delete; - lexer& operator=(lexer&&) = default; - ~lexer() = default; + // delete because of pointer members + lexer(const lexer &) = delete; - private: - ///////////////////// - // locales - ///////////////////// + lexer(lexer &&) = default; - /// return the locale-dependent decimal point - JSON_HEDLEY_PURE - static char get_decimal_point() noexcept - { - const auto* loc = localeconv(); - JSON_ASSERT(loc != nullptr); - return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); - } + lexer &operator=(lexer &) = delete; - ///////////////////// - // scan functions - ///////////////////// + lexer &operator=(lexer &&) = default; - /*! + ~lexer() = default; + + private: + ///////////////////// + // locales + ///////////////////// + + /// return the locale-dependent decimal point + JSON_HEDLEY_PURE + static char get_decimal_point() noexcept { + const auto *loc = localeconv(); + JSON_ASSERT(loc != nullptr); + return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); + } + + ///////////////////// + // scan functions + ///////////////////// + + /*! @brief get codepoint from 4 hex characters following `\u` For input "\u c1 c2 c3 c4" the codepoint is: @@ -6037,40 +5742,31 @@ class lexer : public lexer_base @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or non-hex character) */ - int get_codepoint() - { - // this function only makes sense after reading `\u` - JSON_ASSERT(current == 'u'); - int codepoint = 0; + int get_codepoint() { + // this function only makes sense after reading `\u` + JSON_ASSERT(current == 'u'); + int codepoint = 0; - const auto factors = { 12u, 8u, 4u, 0u }; - for (const auto factor : factors) - { - get(); + const auto factors = {12u, 8u, 4u, 0u}; + for (const auto factor: factors) { + get(); - if (current >= '0' && current <= '9') - { - codepoint += static_cast((static_cast(current) - 0x30u) << factor); - } - else if (current >= 'A' && current <= 'F') - { - codepoint += static_cast((static_cast(current) - 0x37u) << factor); - } - else if (current >= 'a' && current <= 'f') - { - codepoint += static_cast((static_cast(current) - 0x57u) << factor); - } - else - { - return -1; - } - } + if (current >= '0' && current <= '9') { + codepoint += static_cast((static_cast(current) - 0x30u) << factor); + } else if (current >= 'A' && current <= 'F') { + codepoint += static_cast((static_cast(current) - 0x37u) << factor); + } else if (current >= 'a' && current <= 'f') { + codepoint += static_cast((static_cast(current) - 0x57u) << factor); + } else { + return -1; + } + } - JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); - return codepoint; - } + JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); + return codepoint; + } - /*! + /*! @brief check if the next byte(s) are inside a given range Adds the current byte and, for each passed range, reads a new byte and @@ -6085,29 +5781,24 @@ class lexer : public lexer_base @return true if and only if no range violation was detected */ - bool next_byte_in_range(std::initializer_list ranges) - { - JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); - add(current); - - for (auto range = ranges.begin(); range != ranges.end(); ++range) - { - get(); - if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) - { + bool next_byte_in_range(std::initializer_list ranges) { + JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); add(current); - } - else - { - error_message = "invalid string: ill-formed UTF-8 byte"; - return false; - } - } - return true; - } + for (auto range = ranges.begin(); range != ranges.end(); ++range) { + get(); + if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) { + add(current); + } else { + error_message = "invalid string: ill-formed UTF-8 byte"; + return false; + } + } - /*! + return true; + } + + /*! @brief scan a string literal This function scans a string according to Sect. 7 of RFC 7159. While @@ -6122,101 +5813,88 @@ class lexer : public lexer_base @note In case of errors, variable error_message contains a textual description. */ - token_type scan_string() - { - // reset token_buffer (ignore opening quote) - reset(); + token_type scan_string() { + // reset token_buffer (ignore opening quote) + reset(); - // we entered the function by reading an open quote - JSON_ASSERT(current == '\"'); + // we entered the function by reading an open quote + JSON_ASSERT(current == '\"'); - while (true) - { - // get next character - switch (get()) - { - // end of file while parsing string - case std::char_traits::eof(): - { - error_message = "invalid string: missing closing quote"; - return token_type::parse_error; - } + while (true) { + // get next character + switch (get()) { + // end of file while parsing string + case std::char_traits::eof(): { + error_message = "invalid string: missing closing quote"; + return token_type::parse_error; + } - // closing quote - case '\"': - { - return token_type::value_string; - } + // closing quote + case '\"': { + return token_type::value_string; + } - // escapes - case '\\': - { - switch (get()) - { - // quotation mark - case '\"': - add('\"'); - break; - // reverse solidus - case '\\': - add('\\'); - break; - // solidus - case '/': - add('/'); - break; - // backspace - case 'b': - add('\b'); - break; - // form feed - case 'f': - add('\f'); - break; - // line feed - case 'n': - add('\n'); - break; - // carriage return - case 'r': - add('\r'); - break; - // tab - case 't': - add('\t'); - break; + // escapes + case '\\': { + switch (get()) { + // quotation mark + case '\"': + add('\"'); + break; + // reverse solidus + case '\\': + add('\\'); + break; + // solidus + case '/': + add('/'); + break; + // backspace + case 'b': + add('\b'); + break; + // form feed + case 'f': + add('\f'); + break; + // line feed + case 'n': + add('\n'); + break; + // carriage return + case 'r': + add('\r'); + break; + // tab + case 't': + add('\t'); + break; - // unicode escapes - case 'u': - { - const int codepoint1 = get_codepoint(); - int codepoint = codepoint1; // start with codepoint1 + // unicode escapes + case 'u': { + const int codepoint1 = get_codepoint(); + int codepoint = codepoint1; // start with codepoint1 - if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) - { - error_message = "invalid string: '\\u' must be followed by 4 hex digits"; - return token_type::parse_error; - } - - // check if code point is a high surrogate - if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) - { - // expect next \uxxxx entry - if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) - { - const int codepoint2 = get_codepoint(); - - if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) - { + if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) { error_message = "invalid string: '\\u' must be followed by 4 hex digits"; return token_type::parse_error; } - // check if codepoint2 is a low surrogate - if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) - { - // overwrite codepoint - codepoint = static_cast( + // check if code point is a high surrogate + if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) { + // expect next \uxxxx entry + if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) { + const int codepoint2 = get_codepoint(); + + if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if codepoint2 is a low surrogate + if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) { + // overwrite codepoint + codepoint = static_cast( // high surrogate occupies the most significant 22 bits (static_cast(codepoint1) << 10u) // low surrogate occupies the least significant 15 bits @@ -6225,579 +5903,501 @@ class lexer : public lexer_base // in the result so we have to subtract with: // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 - 0x35FDC00u); + } else { + error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } else { + error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } else { + if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) { + error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; + return token_type::parse_error; + } } - else - { - error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; - return token_type::parse_error; + + // result of the above calculation yields a proper codepoint + JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); + + // translate codepoint into bytes + if (codepoint < 0x80) { + // 1-byte characters: 0xxxxxxx (ASCII) + add(static_cast(codepoint)); + } else if (codepoint <= 0x7FF) { + // 2-byte characters: 110xxxxx 10xxxxxx + add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } else if (codepoint <= 0xFFFF) { + // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx + add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } else { + // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); } - } - else - { - error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; - return token_type::parse_error; - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) - { - error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; - return token_type::parse_error; - } - } - // result of the above calculation yields a proper codepoint - JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); + break; + } - // translate codepoint into bytes - if (codepoint < 0x80) - { - // 1-byte characters: 0xxxxxxx (ASCII) - add(static_cast(codepoint)); - } - else if (codepoint <= 0x7FF) - { - // 2-byte characters: 110xxxxx 10xxxxxx - add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - else if (codepoint <= 0xFFFF) - { - // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx - add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - else - { - // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + // other characters after escape + default: + error_message = "invalid string: forbidden character after backslash"; + return token_type::parse_error; } break; } - // other characters after escape - default: - error_message = "invalid string: forbidden character after backslash"; + // invalid control characters + case 0x00: { + error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; return token_type::parse_error; + } + + case 0x01: { + error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; + return token_type::parse_error; + } + + case 0x02: { + error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; + return token_type::parse_error; + } + + case 0x03: { + error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; + return token_type::parse_error; + } + + case 0x04: { + error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; + return token_type::parse_error; + } + + case 0x05: { + error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; + return token_type::parse_error; + } + + case 0x06: { + error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; + return token_type::parse_error; + } + + case 0x07: { + error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; + return token_type::parse_error; + } + + case 0x08: { + error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; + return token_type::parse_error; + } + + case 0x09: { + error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; + return token_type::parse_error; + } + + case 0x0A: { + error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; + return token_type::parse_error; + } + + case 0x0B: { + error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; + return token_type::parse_error; + } + + case 0x0C: { + error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; + return token_type::parse_error; + } + + case 0x0D: { + error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; + return token_type::parse_error; + } + + case 0x0E: { + error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; + return token_type::parse_error; + } + + case 0x0F: { + error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; + return token_type::parse_error; + } + + case 0x10: { + error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; + return token_type::parse_error; + } + + case 0x11: { + error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; + return token_type::parse_error; + } + + case 0x12: { + error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; + return token_type::parse_error; + } + + case 0x13: { + error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; + return token_type::parse_error; + } + + case 0x14: { + error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; + return token_type::parse_error; + } + + case 0x15: { + error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; + return token_type::parse_error; + } + + case 0x16: { + error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; + return token_type::parse_error; + } + + case 0x17: { + error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; + return token_type::parse_error; + } + + case 0x18: { + error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; + return token_type::parse_error; + } + + case 0x19: { + error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; + return token_type::parse_error; + } + + case 0x1A: { + error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; + return token_type::parse_error; + } + + case 0x1B: { + error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; + return token_type::parse_error; + } + + case 0x1C: { + error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; + return token_type::parse_error; + } + + case 0x1D: { + error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; + return token_type::parse_error; + } + + case 0x1E: { + error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; + return token_type::parse_error; + } + + case 0x1F: { + error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; + return token_type::parse_error; + } + + // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) + case 0x20: + case 0x21: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: { + add(current); + break; + } + + // U+0080..U+07FF: bytes C2..DF 80..BF + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: { + if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) { + return token_type::parse_error; + } + break; + } + + // U+0800..U+0FFF: bytes E0 A0..BF 80..BF + case 0xE0: { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) { + return token_type::parse_error; + } + break; + } + + // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF + // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xEE: + case 0xEF: { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) { + return token_type::parse_error; + } + break; + } + + // U+D000..U+D7FF: bytes ED 80..9F 80..BF + case 0xED: { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) { + return token_type::parse_error; + } + break; + } + + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + case 0xF0: { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) { + return token_type::parse_error; + } + break; + } + + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + case 0xF1: + case 0xF2: + case 0xF3: { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) { + return token_type::parse_error; + } + break; + } + + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + case 0xF4: { + if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) { + return token_type::parse_error; + } + break; + } + + // remaining bytes (80..C1 and F5..FF) are ill-formed + default: { + error_message = "invalid string: ill-formed UTF-8 byte"; + return token_type::parse_error; + } } - - break; - } - - // invalid control characters - case 0x00: - { - error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; - return token_type::parse_error; - } - - case 0x01: - { - error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; - return token_type::parse_error; - } - - case 0x02: - { - error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; - return token_type::parse_error; - } - - case 0x03: - { - error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; - return token_type::parse_error; - } - - case 0x04: - { - error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; - return token_type::parse_error; - } - - case 0x05: - { - error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; - return token_type::parse_error; - } - - case 0x06: - { - error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; - return token_type::parse_error; - } - - case 0x07: - { - error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; - return token_type::parse_error; - } - - case 0x08: - { - error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; - return token_type::parse_error; - } - - case 0x09: - { - error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; - return token_type::parse_error; - } - - case 0x0A: - { - error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; - return token_type::parse_error; - } - - case 0x0B: - { - error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; - return token_type::parse_error; - } - - case 0x0C: - { - error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; - return token_type::parse_error; - } - - case 0x0D: - { - error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; - return token_type::parse_error; - } - - case 0x0E: - { - error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; - return token_type::parse_error; - } - - case 0x0F: - { - error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; - return token_type::parse_error; - } - - case 0x10: - { - error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; - return token_type::parse_error; - } - - case 0x11: - { - error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; - return token_type::parse_error; - } - - case 0x12: - { - error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; - return token_type::parse_error; - } - - case 0x13: - { - error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; - return token_type::parse_error; - } - - case 0x14: - { - error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; - return token_type::parse_error; - } - - case 0x15: - { - error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; - return token_type::parse_error; - } - - case 0x16: - { - error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; - return token_type::parse_error; - } - - case 0x17: - { - error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; - return token_type::parse_error; - } - - case 0x18: - { - error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; - return token_type::parse_error; - } - - case 0x19: - { - error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; - return token_type::parse_error; - } - - case 0x1A: - { - error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; - return token_type::parse_error; - } - - case 0x1B: - { - error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; - return token_type::parse_error; - } - - case 0x1C: - { - error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; - return token_type::parse_error; - } - - case 0x1D: - { - error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; - return token_type::parse_error; - } - - case 0x1E: - { - error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; - return token_type::parse_error; - } - - case 0x1F: - { - error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; - return token_type::parse_error; - } - - // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) - case 0x20: - case 0x21: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5D: - case 0x5E: - case 0x5F: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x79: - case 0x7A: - case 0x7B: - case 0x7C: - case 0x7D: - case 0x7E: - case 0x7F: - { - add(current); - break; - } - - // U+0080..U+07FF: bytes C2..DF 80..BF - case 0xC2: - case 0xC3: - case 0xC4: - case 0xC5: - case 0xC6: - case 0xC7: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD5: - case 0xD6: - case 0xD7: - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: - { - if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) - { - return token_type::parse_error; - } - break; - } - - // U+0800..U+0FFF: bytes E0 A0..BF 80..BF - case 0xE0: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF - // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xEE: - case 0xEF: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+D000..U+D7FF: bytes ED 80..9F 80..BF - case 0xED: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF - case 0xF0: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF - case 0xF1: - case 0xF2: - case 0xF3: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF - case 0xF4: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // remaining bytes (80..C1 and F5..FF) are ill-formed - default: - { - error_message = "invalid string: ill-formed UTF-8 byte"; - return token_type::parse_error; } } - } - } - /*! + /*! * @brief scan a comment * @return whether comment could be scanned successfully */ - bool scan_comment() - { - switch (get()) - { - // single-line comments skip input until a newline or EOF is read - case '/': - { - while (true) - { - switch (get()) - { - case '\n': - case '\r': - case std::char_traits::eof(): - case '\0': - return true; - - default: - break; - } - } - } - - // multi-line comments skip input until */ is read - case '*': - { - while (true) - { - switch (get()) - { - case std::char_traits::eof(): - case '\0': - { - error_message = "invalid comment; missing closing '*/'"; - return false; - } - - case '*': - { - switch (get()) - { - case '/': + bool scan_comment() { + switch (get()) { + // single-line comments skip input until a newline or EOF is read + case '/': { + while (true) { + switch (get()) { + case '\n': + case '\r': + case std::char_traits::eof(): + case '\0': return true; default: - { - unget(); - continue; - } + break; } } + } - default: - continue; + // multi-line comments skip input until */ is read + case '*': { + while (true) { + switch (get()) { + case std::char_traits::eof(): + case '\0': { + error_message = "invalid comment; missing closing '*/'"; + return false; + } + + case '*': { + switch (get()) { + case '/': + return true; + + default: { + unget(); + continue; + } + } + } + + default: + continue; + } + } + } + + // unexpected character after reading '/' + default: { + error_message = "invalid comment; expecting '/' or '*' after '/'"; + return false; } } } - // unexpected character after reading '/' - default: - { - error_message = "invalid comment; expecting '/' or '*' after '/'"; - return false; + JSON_HEDLEY_NON_NULL(2) + static void strtof(float &f, const char *str, char **endptr) noexcept { + f = std::strtof(str, endptr); } - } - } - JSON_HEDLEY_NON_NULL(2) - static void strtof(float& f, const char* str, char** endptr) noexcept - { - f = std::strtof(str, endptr); - } + JSON_HEDLEY_NON_NULL(2) + static void strtof(double &f, const char *str, char **endptr) noexcept { + f = std::strtod(str, endptr); + } - JSON_HEDLEY_NON_NULL(2) - static void strtof(double& f, const char* str, char** endptr) noexcept - { - f = std::strtod(str, endptr); - } + JSON_HEDLEY_NON_NULL(2) + static void strtof(long double &f, const char *str, char **endptr) noexcept { + f = std::strtold(str, endptr); + } - JSON_HEDLEY_NON_NULL(2) - static void strtof(long double& f, const char* str, char** endptr) noexcept - { - f = std::strtold(str, endptr); - } - - /*! + /*! @brief scan a number literal This function scans a string according to Sect. 6 of RFC 7159. @@ -6837,365 +6437,324 @@ class lexer : public lexer_base locale's decimal point is used instead of `.` to work with the locale-dependent converters. */ - token_type scan_number() // lgtm [cpp/use-of-goto] - { - // reset token_buffer to store the number's bytes - reset(); - - // the type of the parsed number; initially set to unsigned; will be - // changed if minus sign, decimal point or exponent is read - token_type number_type = token_type::value_unsigned; - - // state (init): we just found out we need to scan a number - switch (current) - { - case '-': + token_type scan_number() // lgtm [cpp/use-of-goto] { - add(current); - goto scan_number_minus; - } + // reset token_buffer to store the number's bytes + reset(); - case '0': - { - add(current); - goto scan_number_zero; - } + // the type of the parsed number; initially set to unsigned; will be + // changed if minus sign, decimal point or exponent is read + token_type number_type = token_type::value_unsigned; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } + // state (init): we just found out we need to scan a number + switch (current) { + case '-': { + add(current); + goto scan_number_minus; + } - // all other characters are rejected outside scan_number() - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } + case '0': { + add(current); + goto scan_number_zero; + } -scan_number_minus: - // state: we just parsed a leading minus sign - number_type = token_type::value_integer; - switch (get()) - { - case '0': - { - add(current); - goto scan_number_zero; - } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any1; + } - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - default: - { - error_message = "invalid number; expected digit after '-'"; - return token_type::parse_error; - } - } - -scan_number_zero: - // state: we just parse a zero (maybe with a leading minus sign) - switch (get()) - { - case '.': - { - add(decimal_point_char); - goto scan_number_decimal1; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_any1: - // state: we just parsed a number 0-9 (maybe with a leading minus sign) - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - case '.': - { - add(decimal_point_char); - goto scan_number_decimal1; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_decimal1: - // state: we just parsed a decimal point - number_type = token_type::value_float; - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_decimal2; - } - - default: - { - error_message = "invalid number; expected digit after '.'"; - return token_type::parse_error; - } - } - -scan_number_decimal2: - // we just parsed at least one number after a decimal point - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_decimal2; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_exponent: - // we just parsed an exponent - number_type = token_type::value_float; - switch (get()) - { - case '+': - case '-': - { - add(current); - goto scan_number_sign; - } - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - { - error_message = - "invalid number; expected '+', '-', or digit after exponent"; - return token_type::parse_error; - } - } - -scan_number_sign: - // we just parsed an exponent sign - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - { - error_message = "invalid number; expected digit after exponent sign"; - return token_type::parse_error; - } - } - -scan_number_any2: - // we just parsed a number after the exponent or exponent sign - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - goto scan_number_done; - } - -scan_number_done: - // unget the character after the number (we only read it to know that - // we are done scanning a number) - unget(); - - char* endptr = nullptr; - errno = 0; - - // try to parse integers first and fall back to floats - if (number_type == token_type::value_unsigned) - { - const auto x = std::strtoull(token_buffer.data(), &endptr, 10); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - if (errno == 0) - { - value_unsigned = static_cast(x); - if (value_unsigned == x) - { - return token_type::value_unsigned; + // all other characters are rejected outside scan_number() + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // LCOV_EXCL_LINE } - } - } - else if (number_type == token_type::value_integer) - { - const auto x = std::strtoll(token_buffer.data(), &endptr, 10); - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + scan_number_minus: + // state: we just parsed a leading minus sign + number_type = token_type::value_integer; + switch (get()) { + case '0': { + add(current); + goto scan_number_zero; + } - if (errno == 0) - { - value_integer = static_cast(x); - if (value_integer == x) - { - return token_type::value_integer; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any1; + } + + default: { + error_message = "invalid number; expected digit after '-'"; + return token_type::parse_error; + } } + + scan_number_zero: + // state: we just parse a zero (maybe with a leading minus sign) + switch (get()) { + case '.': { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + + scan_number_any1: + // state: we just parsed a number 0-9 (maybe with a leading minus sign) + switch (get()) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any1; + } + + case '.': { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + + scan_number_decimal1: + // state: we just parsed a decimal point + number_type = token_type::value_float; + switch (get()) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_decimal2; + } + + default: { + error_message = "invalid number; expected digit after '.'"; + return token_type::parse_error; + } + } + + scan_number_decimal2: + // we just parsed at least one number after a decimal point + switch (get()) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_decimal2; + } + + case 'e': + case 'E': { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + + scan_number_exponent: + // we just parsed an exponent + number_type = token_type::value_float; + switch (get()) { + case '+': + case '-': { + add(current); + goto scan_number_sign; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any2; + } + + default: { + error_message = + "invalid number; expected '+', '-', or digit after exponent"; + return token_type::parse_error; + } + } + + scan_number_sign: + // we just parsed an exponent sign + switch (get()) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any2; + } + + default: { + error_message = "invalid number; expected digit after exponent sign"; + return token_type::parse_error; + } + } + + scan_number_any2: + // we just parsed a number after the exponent or exponent sign + switch (get()) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + add(current); + goto scan_number_any2; + } + + default: + goto scan_number_done; + } + + scan_number_done: + // unget the character after the number (we only read it to know that + // we are done scanning a number) + unget(); + + char *endptr = nullptr; + errno = 0; + + // try to parse integers first and fall back to floats + if (number_type == token_type::value_unsigned) { + const auto x = std::strtoull(token_buffer.data(), &endptr, 10); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) { + value_unsigned = static_cast(x); + if (value_unsigned == x) { + return token_type::value_unsigned; + } + } + } else if (number_type == token_type::value_integer) { + const auto x = std::strtoll(token_buffer.data(), &endptr, 10); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) { + value_integer = static_cast(x); + if (value_integer == x) { + return token_type::value_integer; + } + } + } + + // this code is reached if we parse a floating-point number or if an + // integer conversion above failed + strtof(value_float, token_buffer.data(), &endptr); + + // we checked the number format before + JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); + + return token_type::value_float; } - } - // this code is reached if we parse a floating-point number or if an - // integer conversion above failed - strtof(value_float, token_buffer.data(), &endptr); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - return token_type::value_float; - } - - /*! + /*! @param[in] literal_text the literal text to expect @param[in] length the length of the passed literal text @param[in] return_type the token type to return on success */ - JSON_HEDLEY_NON_NULL(2) - token_type scan_literal(const char_type* literal_text, const std::size_t length, - token_type return_type) - { - JSON_ASSERT(std::char_traits::to_char_type(current) == literal_text[0]); - for (std::size_t i = 1; i < length; ++i) - { - if (JSON_HEDLEY_UNLIKELY(std::char_traits::to_char_type(get()) != literal_text[i])) - { - error_message = "invalid literal"; - return token_type::parse_error; + JSON_HEDLEY_NON_NULL(2) + token_type scan_literal(const char_type *literal_text, const std::size_t length, + token_type return_type) { + JSON_ASSERT(std::char_traits::to_char_type(current) == literal_text[0]); + for (std::size_t i = 1; i < length; ++i) { + if (JSON_HEDLEY_UNLIKELY(std::char_traits::to_char_type(get()) != literal_text[i])) { + error_message = "invalid literal"; + return token_type::parse_error; + } + } + return return_type; } - } - return return_type; - } - ///////////////////// - // input management - ///////////////////// + ///////////////////// + // input management + ///////////////////// - /// reset token_buffer; current character is beginning of token - void reset() noexcept - { - token_buffer.clear(); - token_string.clear(); - token_string.push_back(std::char_traits::to_char_type(current)); - } + /// reset token_buffer; current character is beginning of token + void reset() noexcept { + token_buffer.clear(); + token_string.clear(); + token_string.push_back(std::char_traits::to_char_type(current)); + } - /* + /* @brief get next character from the input This function provides the interface to the used input adapter. It does @@ -7205,36 +6764,30 @@ scan_number_done: @return character read from the input */ - char_int_type get() - { - ++position.chars_read_total; - ++position.chars_read_current_line; + char_int_type get() { + ++position.chars_read_total; + ++position.chars_read_current_line; - if (next_unget) - { - // just reset the next_unget variable and work with current - next_unget = false; - } - else - { - current = ia.get_character(); - } + if (next_unget) { + // just reset the next_unget variable and work with current + next_unget = false; + } else { + current = ia.get_character(); + } - if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) - { - token_string.push_back(std::char_traits::to_char_type(current)); - } + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) { + token_string.push_back(std::char_traits::to_char_type(current)); + } - if (current == '\n') - { - ++position.lines_read; - position.chars_read_current_line = 0; - } + if (current == '\n') { + ++position.lines_read; + position.chars_read_current_line = 0; + } - return current; - } + return current; + } - /*! + /*! @brief unget current character (read it again on next get) We implement unget by setting variable next_unget to true. The input is not @@ -7242,263 +6795,232 @@ scan_number_done: chars_read_current_line, and token_string. The next call to get() will behave as if the unget character is read again. */ - void unget() - { - next_unget = true; + void unget() { + next_unget = true; - --position.chars_read_total; + --position.chars_read_total; - // in case we "unget" a newline, we have to also decrement the lines_read - if (position.chars_read_current_line == 0) - { - if (position.lines_read > 0) - { - --position.lines_read; + // in case we "unget" a newline, we have to also decrement the lines_read + if (position.chars_read_current_line == 0) { + if (position.lines_read > 0) { + --position.lines_read; + } + } else { + --position.chars_read_current_line; + } + + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) { + JSON_ASSERT(!token_string.empty()); + token_string.pop_back(); + } } - } - else - { - --position.chars_read_current_line; - } - if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) - { - JSON_ASSERT(!token_string.empty()); - token_string.pop_back(); - } - } + /// add a character to token_buffer + void add(char_int_type c) { + token_buffer.push_back(static_cast(c)); + } - /// add a character to token_buffer - void add(char_int_type c) - { - token_buffer.push_back(static_cast(c)); - } + public: + ///////////////////// + // value getters + ///////////////////// - public: - ///////////////////// - // value getters - ///////////////////// + /// return integer value + constexpr number_integer_t get_number_integer() const noexcept { + return value_integer; + } - /// return integer value - constexpr number_integer_t get_number_integer() const noexcept - { - return value_integer; - } + /// return unsigned integer value + constexpr number_unsigned_t get_number_unsigned() const noexcept { + return value_unsigned; + } - /// return unsigned integer value - constexpr number_unsigned_t get_number_unsigned() const noexcept - { - return value_unsigned; - } + /// return floating-point value + constexpr number_float_t get_number_float() const noexcept { + return value_float; + } - /// return floating-point value - constexpr number_float_t get_number_float() const noexcept - { - return value_float; - } + /// return current string value (implicitly resets the token; useful only once) + string_t &get_string() { + return token_buffer; + } - /// return current string value (implicitly resets the token; useful only once) - string_t& get_string() - { - return token_buffer; - } + ///////////////////// + // diagnostics + ///////////////////// - ///////////////////// - // diagnostics - ///////////////////// + /// return position of last read token + constexpr position_t get_position() const noexcept { + return position; + } - /// return position of last read token - constexpr position_t get_position() const noexcept - { - return position; - } - - /// return the last read token (for errors only). Will never contain EOF - /// (an arbitrary value that is not a valid char value, often -1), because - /// 255 may legitimately occur. May contain NUL, which should be escaped. - std::string get_token_string() const - { - // escape control characters - std::string result; - for (const auto c : token_string) - { - if (static_cast(c) <= '\x1F') - { + /// return the last read token (for errors only). Will never contain EOF + /// (an arbitrary value that is not a valid char value, often -1), because + /// 255 may legitimately occur. May contain NUL, which should be escaped. + std::string get_token_string() const { // escape control characters - std::array cs{{}}; - (std::snprintf)(cs.data(), cs.size(), "", static_cast(c)); - result += cs.data(); + std::string result; + for (const auto c: token_string) { + if (static_cast(c) <= '\x1F') { + // escape control characters + std::array cs{{}}; + (std::snprintf) (cs.data(), cs.size(), "", static_cast(c)); + result += cs.data(); + } else { + // add character as is + result.push_back(static_cast(c)); + } + } + + return result; } - else - { - // add character as is - result.push_back(static_cast(c)); + + /// return syntax error message + JSON_HEDLEY_RETURNS_NON_NULL + constexpr const char *get_error_message() const noexcept { + return error_message; } - } - return result; - } + ///////////////////// + // actual scanner + ///////////////////// - /// return syntax error message - JSON_HEDLEY_RETURNS_NON_NULL - constexpr const char* get_error_message() const noexcept - { - return error_message; - } - - ///////////////////// - // actual scanner - ///////////////////// - - /*! + /*! @brief skip the UTF-8 byte order mark @return true iff there is no BOM or the correct BOM has been skipped */ - bool skip_bom() - { - if (get() == 0xEF) - { - // check if we completely parse the BOM - return get() == 0xBB && get() == 0xBF; - } + bool skip_bom() { + if (get() == 0xEF) { + // check if we completely parse the BOM + return get() == 0xBB && get() == 0xBF; + } - // the first character is not the beginning of the BOM; unget it to - // process is later - unget(); - return true; - } - - void skip_whitespace() - { - do - { - get(); - } - while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); - } - - token_type scan() - { - // initially, skip the BOM - if (position.chars_read_total == 0 && !skip_bom()) - { - error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; - return token_type::parse_error; - } - - // read next character and ignore whitespace - skip_whitespace(); - - // ignore comments - while (ignore_comments && current == '/') - { - if (!scan_comment()) - { - return token_type::parse_error; + // the first character is not the beginning of the BOM; unget it to + // process is later + unget(); + return true; } - // skip following whitespace - skip_whitespace(); - } - - switch (current) - { - // structural characters - case '[': - return token_type::begin_array; - case ']': - return token_type::end_array; - case '{': - return token_type::begin_object; - case '}': - return token_type::end_object; - case ':': - return token_type::name_separator; - case ',': - return token_type::value_separator; - - // literals - case 't': - { - std::array true_literal = {{'t', 'r', 'u', 'e'}}; - return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); - } - case 'f': - { - std::array false_literal = {{'f', 'a', 'l', 's', 'e'}}; - return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); - } - case 'n': - { - std::array null_literal = {{'n', 'u', 'l', 'l'}}; - return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); + void skip_whitespace() { + do { + get(); + } while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); } - // string - case '\"': - return scan_string(); + token_type scan() { + // initially, skip the BOM + if (position.chars_read_total == 0 && !skip_bom()) { + error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; + return token_type::parse_error; + } - // number - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return scan_number(); + // read next character and ignore whitespace + skip_whitespace(); - // end of input (the null byte is needed when parsing from - // string literals) - case '\0': - case std::char_traits::eof(): - return token_type::end_of_input; + // ignore comments + while (ignore_comments && current == '/') { + if (!scan_comment()) { + return token_type::parse_error; + } - // error - default: - error_message = "invalid literal"; - return token_type::parse_error; - } - } + // skip following whitespace + skip_whitespace(); + } - private: - /// input adapter - InputAdapterType ia; + switch (current) { + // structural characters + case '[': + return token_type::begin_array; + case ']': + return token_type::end_array; + case '{': + return token_type::begin_object; + case '}': + return token_type::end_object; + case ':': + return token_type::name_separator; + case ',': + return token_type::value_separator; - /// whether comments should be ignored (true) or signaled as errors (false) - const bool ignore_comments = false; + // literals + case 't': { + std::array true_literal = {{'t', 'r', 'u', 'e'}}; + return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); + } + case 'f': { + std::array false_literal = {{'f', 'a', 'l', 's', 'e'}}; + return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); + } + case 'n': { + std::array null_literal = {{'n', 'u', 'l', 'l'}}; + return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); + } - /// the current character - char_int_type current = std::char_traits::eof(); + // string + case '\"': + return scan_string(); - /// whether the next get() call should just return current - bool next_unget = false; + // number + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return scan_number(); - /// the start position of the current token - position_t position {}; + // end of input (the null byte is needed when parsing from + // string literals) + case '\0': + case std::char_traits::eof(): + return token_type::end_of_input; - /// raw input token string (for error messages) - std::vector token_string {}; + // error + default: + error_message = "invalid literal"; + return token_type::parse_error; + } + } - /// buffer for variable-length tokens (numbers, strings) - string_t token_buffer {}; + private: + /// input adapter + InputAdapterType ia; - /// a description of occurred lexer errors - const char* error_message = ""; + /// whether comments should be ignored (true) or signaled as errors (false) + const bool ignore_comments = false; - // number values - number_integer_t value_integer = 0; - number_unsigned_t value_unsigned = 0; - number_float_t value_float = 0; + /// the current character + char_int_type current = std::char_traits::eof(); - /// the decimal point - const char_int_type decimal_point_char = '.'; -}; -} // namespace detail + /// whether the next get() call should just return current + bool next_unget = false; + + /// the start position of the current token + position_t position{}; + + /// raw input token string (for error messages) + std::vector token_string{}; + + /// buffer for variable-length tokens (numbers, strings) + string_t token_buffer{}; + + /// a description of occurred lexer errors + const char *error_message = ""; + + // number values + number_integer_t value_integer = 0; + number_unsigned_t value_unsigned = 0; + number_float_t value_float = 0; + + /// the decimal point + const char_int_type decimal_point_char = '.'; + }; + } // namespace detail } // namespace nlohmann // #include @@ -7515,161 +7037,154 @@ scan_number_done: // #include -namespace nlohmann -{ -namespace detail -{ -template -using null_function_t = decltype(std::declval().null()); +namespace nlohmann { + namespace detail { + template + using null_function_t = decltype(std::declval().null()); -template -using boolean_function_t = - decltype(std::declval().boolean(std::declval())); + template + using boolean_function_t = + decltype(std::declval().boolean(std::declval())); -template -using number_integer_function_t = - decltype(std::declval().number_integer(std::declval())); + template + using number_integer_function_t = + decltype(std::declval().number_integer(std::declval())); -template -using number_unsigned_function_t = - decltype(std::declval().number_unsigned(std::declval())); + template + using number_unsigned_function_t = + decltype(std::declval().number_unsigned(std::declval())); -template -using number_float_function_t = decltype(std::declval().number_float( - std::declval(), std::declval())); + template + using number_float_function_t = decltype(std::declval().number_float( + std::declval(), std::declval())); -template -using string_function_t = - decltype(std::declval().string(std::declval())); + template + using string_function_t = + decltype(std::declval().string(std::declval())); -template -using binary_function_t = - decltype(std::declval().binary(std::declval())); + template + using binary_function_t = + decltype(std::declval().binary(std::declval())); -template -using start_object_function_t = - decltype(std::declval().start_object(std::declval())); + template + using start_object_function_t = + decltype(std::declval().start_object(std::declval())); -template -using key_function_t = - decltype(std::declval().key(std::declval())); + template + using key_function_t = + decltype(std::declval().key(std::declval())); -template -using end_object_function_t = decltype(std::declval().end_object()); + template + using end_object_function_t = decltype(std::declval().end_object()); -template -using start_array_function_t = - decltype(std::declval().start_array(std::declval())); + template + using start_array_function_t = + decltype(std::declval().start_array(std::declval())); -template -using end_array_function_t = decltype(std::declval().end_array()); + template + using end_array_function_t = decltype(std::declval().end_array()); -template -using parse_error_function_t = decltype(std::declval().parse_error( - std::declval(), std::declval(), - std::declval())); + template + using parse_error_function_t = decltype(std::declval().parse_error( + std::declval(), std::declval(), + std::declval())); -template -struct is_sax -{ - private: - static_assert(is_basic_json::value, - "BasicJsonType must be of type basic_json<...>"); + template + struct is_sax { + private: + static_assert(is_basic_json::value, + "BasicJsonType must be of type basic_json<...>"); - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using exception_t = typename BasicJsonType::exception; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using exception_t = typename BasicJsonType::exception; - public: - static constexpr bool value = - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value; -}; + public: + static constexpr bool value = + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value && + is_detected_exact::value; + }; -template -struct is_sax_static_asserts -{ - private: - static_assert(is_basic_json::value, - "BasicJsonType must be of type basic_json<...>"); + template + struct is_sax_static_asserts { + private: + static_assert(is_basic_json::value, + "BasicJsonType must be of type basic_json<...>"); - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using exception_t = typename BasicJsonType::exception; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using exception_t = typename BasicJsonType::exception; - public: - static_assert(is_detected_exact::value, - "Missing/invalid function: bool null()"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool boolean(bool)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool boolean(bool)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool number_integer(number_integer_t)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool string(string_t&)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool binary(binary_t&)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool start_object(std::size_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool key(string_t&)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool end_object()"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool start_array(std::size_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool end_array()"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool parse_error(std::size_t, const " - "std::string&, const exception&)"); -}; -} // namespace detail + public: + static_assert(is_detected_exact::value, + "Missing/invalid function: bool null()"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool boolean(bool)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool boolean(bool)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool number_integer(number_integer_t)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool string(string_t&)"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool binary(binary_t&)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool start_object(std::size_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool key(string_t&)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool end_object()"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool start_array(std::size_t)"); + static_assert(is_detected_exact::value, + "Missing/invalid function: bool end_array()"); + static_assert( + is_detected_exact::value, + "Missing/invalid function: bool parse_error(std::size_t, const " + "std::string&, const exception&)"); + }; + } // namespace detail } // namespace nlohmann // #include -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /// how to treat CBOR tags -enum class cbor_tag_handler_t -{ - error, ///< throw a parse_error exception in case of a tag - ignore ///< ignore tags -}; + enum class cbor_tag_handler_t { + error, ///< throw a parse_error exception in case of a tag + ignore ///< ignore tags + }; /*! @brief determine system byte order @@ -7678,10 +7193,9 @@ enum class cbor_tag_handler_t @note from https://stackoverflow.com/a/1001328/266378 */ -static inline bool little_endianess(int num = 1) noexcept -{ - return *reinterpret_cast(&num) == 1; -} + static inline bool little_endianess(int num = 1) noexcept { + return *reinterpret_cast(&num) == 1; + } /////////////////// @@ -7691,37 +7205,39 @@ static inline bool little_endianess(int num = 1) noexcept /*! @brief deserialization of CBOR, MessagePack, and UBJSON values */ -template> -class binary_reader -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using json_sax_t = SAX; - using char_type = typename InputAdapterType::char_type; - using char_int_type = typename std::char_traits::int_type; + template> + class binary_reader { + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using json_sax_t = SAX; + using char_type = typename InputAdapterType::char_type; + using char_int_type = typename std::char_traits::int_type; - public: - /*! + public: + /*! @brief create a binary reader @param[in] adapter input adapter to read from */ - explicit binary_reader(InputAdapterType&& adapter) : ia(std::move(adapter)) - { - (void)detail::is_sax_static_asserts {}; - } + explicit binary_reader(InputAdapterType &&adapter) : ia(std::move(adapter)) { + (void) detail::is_sax_static_asserts{}; + } - // make class move-only - binary_reader(const binary_reader&) = delete; - binary_reader(binary_reader&&) = default; - binary_reader& operator=(const binary_reader&) = delete; - binary_reader& operator=(binary_reader&&) = default; - ~binary_reader() = default; + // make class move-only + binary_reader(const binary_reader &) = delete; - /*! + binary_reader(binary_reader &&) = default; + + binary_reader &operator=(const binary_reader &) = delete; + + binary_reader &operator=(binary_reader &&) = default; + + ~binary_reader() = default; + + /*! @param[in] format the binary format to parse @param[in] sax_ a SAX event processor @param[in] strict whether to expect the input to be consumed completed @@ -7729,112 +7245,98 @@ class binary_reader @return */ - JSON_HEDLEY_NON_NULL(3) - bool sax_parse(const input_format_t format, - json_sax_t* sax_, - const bool strict = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - sax = sax_; - bool result = false; + JSON_HEDLEY_NON_NULL(3) + bool sax_parse(const input_format_t format, + json_sax_t *sax_, + const bool strict = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { + sax = sax_; + bool result = false; - switch (format) - { - case input_format_t::bson: - result = parse_bson_internal(); - break; + switch (format) { + case input_format_t::bson: + result = parse_bson_internal(); + break; - case input_format_t::cbor: - result = parse_cbor_internal(true, tag_handler); - break; + case input_format_t::cbor: + result = parse_cbor_internal(true, tag_handler); + break; - case input_format_t::msgpack: - result = parse_msgpack_internal(); - break; + case input_format_t::msgpack: + result = parse_msgpack_internal(); + break; - case input_format_t::ubjson: - result = parse_ubjson_internal(); - break; + case input_format_t::ubjson: + result = parse_ubjson_internal(); + break; - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // LCOV_EXCL_LINE + } - // strict mode: next byte must be EOF - if (result && strict) - { - if (format == input_format_t::ubjson) - { - get_ignore_noop(); - } - else - { - get(); + // strict mode: next byte must be EOF + if (result && strict) { + if (format == input_format_t::ubjson) { + get_ignore_noop(); + } else { + get(); + } + + if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"))); + } + } + + return result; } - if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) - { - return sax->parse_error(chars_read, get_token_string(), - parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"))); - } - } + private: + ////////// + // BSON // + ////////// - return result; - } - - private: - ////////// - // BSON // - ////////// - - /*! + /*! @brief Reads in a BSON-object and passes it to the SAX-parser. @return whether a valid BSON-value was passed to the SAX parser */ - bool parse_bson_internal() - { - std::int32_t document_size{}; - get_number(input_format_t::bson, document_size); + bool parse_bson_internal() { + std::int32_t document_size{}; + get_number(input_format_t::bson, document_size); - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) { + return false; + } - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) - { - return false; - } + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) { + return false; + } - return sax->end_object(); - } + return sax->end_object(); + } - /*! + /*! @brief Parses a C-style string from the BSON input. @param[in, out] result A reference to the string variable where the read string is to be stored. @return `true` if the \x00-byte indicating the end of the string was encountered before the EOF; false` indicates an unexpected EOF. */ - bool get_bson_cstr(string_t& result) - { - auto out = std::back_inserter(result); - while (true) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) - { - return false; + bool get_bson_cstr(string_t &result) { + auto out = std::back_inserter(result); + while (true) { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) { + return false; + } + if (current == 0x00) { + return true; + } + *out++ = static_cast(current); + } } - if (current == 0x00) - { - return true; - } - *out++ = static_cast(current); - } - } - /*! + /*! @brief Parses a zero-terminated string of length @a len from the BSON input. @param[in] len The length (including the zero-byte at the end) of the @@ -7845,19 +7347,18 @@ class binary_reader @pre len >= 1 @return `true` if the string was successfully parsed */ - template - bool get_bson_string(const NumberType len, string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(len < 1)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"))); - } + template + bool get_bson_string(const NumberType len, string_t &result) { + if (JSON_HEDLEY_UNLIKELY(len < 1)) { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"))); + } - return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); - } + return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); + } - /*! + /*! @brief Parses a byte array input of length @a len from the BSON input. @param[in] len The length of the byte array to be read. @param[in, out] result A reference to the binary variable where the read @@ -7866,24 +7367,23 @@ class binary_reader @pre len >= 0 @return `true` if the byte array was successfully parsed */ - template - bool get_bson_binary(const NumberType len, binary_t& result) - { - if (JSON_HEDLEY_UNLIKELY(len < 0)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"))); - } + template + bool get_bson_binary(const NumberType len, binary_t &result) { + if (JSON_HEDLEY_UNLIKELY(len < 0)) { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"))); + } - // All BSON binary values have a subtype - std::uint8_t subtype{}; - get_number(input_format_t::bson, subtype); - result.set_subtype(subtype); + // All BSON binary values have a subtype + std::uint8_t subtype{}; + get_number(input_format_t::bson, subtype); + result.set_subtype(subtype); - return get_binary(input_format_t::bson, len, result); - } + return get_binary(input_format_t::bson, len, result); + } - /*! + /*! @brief Read a BSON document element of the given @a element_type. @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html @param[in] element_type_parse_position The position in the input stream, @@ -7893,73 +7393,72 @@ class binary_reader Unsupported BSON record type 0x... @return whether a valid BSON-object/array was passed to the SAX parser */ - bool parse_bson_element_internal(const char_int_type element_type, - const std::size_t element_type_parse_position) - { - switch (element_type) - { - case 0x01: // double - { - double number{}; - return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); + bool parse_bson_element_internal(const char_int_type element_type, + const std::size_t element_type_parse_position) { + switch (element_type) { + case 0x01: // double + { + double number{}; + return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); + } + + case 0x02: // string + { + std::int32_t len{}; + string_t value; + return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); + } + + case 0x03: // object + { + return parse_bson_internal(); + } + + case 0x04: // array + { + return parse_bson_array(); + } + + case 0x05: // binary + { + std::int32_t len{}; + binary_t value; + return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); + } + + case 0x08: // boolean + { + return sax->boolean(get() != 0); + } + + case 0x0A: // null + { + return sax->null(); + } + + case 0x10: // int32 + { + std::int32_t value{}; + return get_number(input_format_t::bson, value) && sax->number_integer(value); + } + + case 0x12: // int64 + { + std::int64_t value{}; + return get_number(input_format_t::bson, value) && sax->number_integer(value); + } + + default: // anything else not supported (yet) + { + std::array cr{{}}; + (std::snprintf) (cr.data(), cr.size(), "%.2hhX", static_cast(element_type)); + return sax->parse_error(element_type_parse_position, std::string(cr.data()), + parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()))); + } + } } - case 0x02: // string - { - std::int32_t len{}; - string_t value; - return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); - } - - case 0x03: // object - { - return parse_bson_internal(); - } - - case 0x04: // array - { - return parse_bson_array(); - } - - case 0x05: // binary - { - std::int32_t len{}; - binary_t value; - return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); - } - - case 0x08: // boolean - { - return sax->boolean(get() != 0); - } - - case 0x0A: // null - { - return sax->null(); - } - - case 0x10: // int32 - { - std::int32_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(value); - } - - case 0x12: // int64 - { - std::int64_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(value); - } - - default: // anything else not supported (yet) - { - std::array cr{{}}; - (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type)); - return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()))); - } - } - } - - /*! + /*! @brief Read a BSON element list (as specified in the BSON-spec) The same binary layout is used for objects and arrays, hence it must be @@ -7971,67 +7470,58 @@ class binary_reader array (@a is_array == true). @return whether a valid BSON-object/array was passed to the SAX parser */ - bool parse_bson_element_list(const bool is_array) - { - string_t key; + bool parse_bson_element_list(const bool is_array) { + string_t key; - while (auto element_type = get()) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) - { - return false; + while (auto element_type = get()) { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) { + return false; + } + + const std::size_t element_type_parse_position = chars_read; + if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) { + return false; + } + + if (!is_array && !sax->key(key)) { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) { + return false; + } + + // get_bson_cstr only appends + key.clear(); + } + + return true; } - const std::size_t element_type_parse_position = chars_read; - if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) - { - return false; - } - - if (!is_array && !sax->key(key)) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) - { - return false; - } - - // get_bson_cstr only appends - key.clear(); - } - - return true; - } - - /*! + /*! @brief Reads an array from the BSON input and passes it to the SAX-parser. @return whether a valid BSON-array was passed to the SAX parser */ - bool parse_bson_array() - { - std::int32_t document_size{}; - get_number(input_format_t::bson, document_size); + bool parse_bson_array() { + std::int32_t document_size{}; + get_number(input_format_t::bson, document_size); - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) { + return false; + } - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) - { - return false; - } + if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) { + return false; + } - return sax->end_array(); - } + return sax->end_array(); + } - ////////// - // CBOR // - ////////// + ////////// + // CBOR // + ////////// - /*! + /*! @param[in] get_char whether a new character should be retrieved from the input (true) or whether the last read character should be considered instead (false) @@ -8039,441 +7529,428 @@ class binary_reader @return whether a valid CBOR value was passed to the SAX parser */ - bool parse_cbor_internal(const bool get_char, - const cbor_tag_handler_t tag_handler) - { - switch (get_char ? get() : current) - { - // EOF - case std::char_traits::eof(): - return unexpect_eof(input_format_t::cbor, "value"); + bool parse_cbor_internal(const bool get_char, + const cbor_tag_handler_t tag_handler) { + switch (get_char ? get() : current) { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::cbor, "value"); - // Integer 0x00..0x17 (0..23) - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - return sax->number_unsigned(static_cast(current)); + // Integer 0x00..0x17 (0..23) + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + return sax->number_unsigned(static_cast(current)); - case 0x18: // Unsigned integer (one-byte uint8_t follows) - { - std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } + case 0x18: // Unsigned integer (one-byte uint8_t follows) + { + std::uint8_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } - case 0x19: // Unsigned integer (two-byte uint16_t follows) - { - std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } + case 0x19: // Unsigned integer (two-byte uint16_t follows) + { + std::uint16_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } - case 0x1A: // Unsigned integer (four-byte uint32_t follows) - { - std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } + case 0x1A: // Unsigned integer (four-byte uint32_t follows) + { + std::uint32_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } - case 0x1B: // Unsigned integer (eight-byte uint64_t follows) - { - std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } + case 0x1B: // Unsigned integer (eight-byte uint64_t follows) + { + std::uint64_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); + } - // Negative integer -1-0x00..-1-0x17 (-1..-24) - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - return sax->number_integer(static_cast(0x20 - 1 - current)); + // Negative integer -1-0x00..-1-0x17 (-1..-24) + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + return sax->number_integer(static_cast(0x20 - 1 - current)); - case 0x38: // Negative integer (one-byte uint8_t follows) - { - std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } + case 0x38: // Negative integer (one-byte uint8_t follows) + { + std::uint8_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } - case 0x39: // Negative integer -1-n (two-byte uint16_t follows) - { - std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } + case 0x39: // Negative integer -1-n (two-byte uint16_t follows) + { + std::uint16_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } - case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) - { - std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } + case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) + { + std::uint32_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); + } - case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) - { - std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - - static_cast(number)); - } + case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) + { + std::uint64_t number{}; + return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) + - static_cast(number)); + } - // Binary data (0x00..0x17 bytes follow) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: // Binary data (one-byte uint8_t for n follows) - case 0x59: // Binary data (two-byte uint16_t for n follow) - case 0x5A: // Binary data (four-byte uint32_t for n follow) - case 0x5B: // Binary data (eight-byte uint64_t for n follow) - case 0x5F: // Binary data (indefinite length) - { - binary_t b; - return get_cbor_binary(b) && sax->binary(b); - } + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: // Binary data (one-byte uint8_t for n follows) + case 0x59: // Binary data (two-byte uint16_t for n follow) + case 0x5A: // Binary data (four-byte uint32_t for n follow) + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + case 0x5F: // Binary data (indefinite length) + { + binary_t b; + return get_cbor_binary(b) && sax->binary(b); + } - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) - case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) - case 0x7F: // UTF-8 string (indefinite length) - { - string_t s; - return get_cbor_string(s) && sax->string(s); - } + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7F: // UTF-8 string (indefinite length) + { + string_t s; + return get_cbor_string(s) && sax->string(s); + } - // array (0x00..0x17 data items follow) - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); + // array (0x00..0x17 data items follow) + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); - case 0x98: // array (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } + case 0x98: // array (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } - case 0x99: // array (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } + case 0x99: // array (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } - case 0x9A: // array (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } + case 0x9A: // array (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } - case 0x9B: // array (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } + case 0x9B: // array (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + } - case 0x9F: // array (indefinite length) - return get_cbor_array(std::size_t(-1), tag_handler); + case 0x9F: // array (indefinite length) + return get_cbor_array(std::size_t(-1), tag_handler); - // map (0x00..0x17 pairs of data items follow) - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); + // map (0x00..0x17 pairs of data items follow) + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); - case 0xB8: // map (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } + case 0xB8: // map (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } - case 0xB9: // map (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } + case 0xB9: // map (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } - case 0xBA: // map (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } + case 0xBA: // map (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } - case 0xBB: // map (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } + case 0xBB: // map (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + } - case 0xBF: // map (indefinite length) - return get_cbor_object(std::size_t(-1), tag_handler); + case 0xBF: // map (indefinite length) + return get_cbor_object(std::size_t(-1), tag_handler); - case 0xC6: // tagged item - case 0xC7: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD8: // tagged item (1 bytes follow) - case 0xD9: // tagged item (2 bytes follow) - case 0xDA: // tagged item (4 bytes follow) - case 0xDB: // tagged item (8 bytes follow) - { - switch (tag_handler) - { - case cbor_tag_handler_t::error: + case 0xC6: // tagged item + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD8: // tagged item (1 bytes follow) + case 0xD9: // tagged item (2 bytes follow) + case 0xDA: // tagged item (4 bytes follow) + case 0xDB: // tagged item (8 bytes follow) + { + switch (tag_handler) { + case cbor_tag_handler_t::error: { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, + parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); + } + + case cbor_tag_handler_t::ignore: { + switch (current) { + case 0xD8: { + std::uint8_t len{}; + get_number(input_format_t::cbor, len); + break; + } + case 0xD9: { + std::uint16_t len{}; + get_number(input_format_t::cbor, len); + break; + } + case 0xDA: { + std::uint32_t len{}; + get_number(input_format_t::cbor, len); + break; + } + case 0xDB: { + std::uint64_t len{}; + get_number(input_format_t::cbor, len); + break; + } + default: + break; + } + return parse_cbor_internal(true, tag_handler); + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // LCOV_EXCL_LINE + } + } + + case 0xF4: // false + return sax->boolean(false); + + case 0xF5: // true + return sax->boolean(true); + + case 0xF6: // null + return sax->null(); + + case 0xF9: // Half-Precision Float (two-byte IEEE 754) + { + const auto byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) { + return false; + } + const auto byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte1 << 8u) + byte2); + const double val = [&half] { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + JSON_ASSERT(0 <= exp && exp <= 32); + JSON_ASSERT(mant <= 1024); + switch (exp) { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 + ? static_cast(-val) + : static_cast(val), ""); + } + + case 0xFA: // Single-Precision Float (four-byte IEEE 754) + { + float number{}; + return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + } + + case 0xFB: // Double-Precision Float (eight-byte IEEE 754) + { + double number{}; + return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); + } + + default: // anything else (0xFF is handled inside the other types) { auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); } - - case cbor_tag_handler_t::ignore: - { - switch (current) - { - case 0xD8: - { - std::uint8_t len{}; - get_number(input_format_t::cbor, len); - break; - } - case 0xD9: - { - std::uint16_t len{}; - get_number(input_format_t::cbor, len); - break; - } - case 0xDA: - { - std::uint32_t len{}; - get_number(input_format_t::cbor, len); - break; - } - case 0xDB: - { - std::uint64_t len{}; - get_number(input_format_t::cbor, len); - break; - } - default: - break; - } - return parse_cbor_internal(true, tag_handler); - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE } } - case 0xF4: // false - return sax->boolean(false); - - case 0xF5: // true - return sax->boolean(true); - - case 0xF6: // null - return sax->null(); - - case 0xF9: // Half-Precision Float (two-byte IEEE 754) - { - const auto byte1_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) - { - return false; - } - const auto byte2_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) - { - return false; - } - - const auto byte1 = static_cast(byte1_raw); - const auto byte2 = static_cast(byte2_raw); - - // code from RFC 7049, Appendix D, Figure 3: - // As half-precision floating-point numbers were only added - // to IEEE 754 in 2008, today's programming platforms often - // still only have limited support for them. It is very - // easy to include at least decoding support for them even - // without such support. An example of a small decoder for - // half-precision floating-point numbers in the C language - // is shown in Fig. 3. - const auto half = static_cast((byte1 << 8u) + byte2); - const double val = [&half] - { - const int exp = (half >> 10u) & 0x1Fu; - const unsigned int mant = half & 0x3FFu; - JSON_ASSERT(0 <= exp&& exp <= 32); - JSON_ASSERT(mant <= 1024); - switch (exp) - { - case 0: - return std::ldexp(mant, -24); - case 31: - return (mant == 0) - ? std::numeric_limits::infinity() - : std::numeric_limits::quiet_NaN(); - default: - return std::ldexp(mant + 1024, exp - 25); - } - }(); - return sax->number_float((half & 0x8000u) != 0 - ? static_cast(-val) - : static_cast(val), ""); - } - - case 0xFA: // Single-Precision Float (four-byte IEEE 754) - { - float number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); - } - - case 0xFB: // Double-Precision Float (eight-byte IEEE 754) - { - double number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); - } - - default: // anything else (0xFF is handled inside the other types) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); - } - } - } - - /*! + /*! @brief reads a CBOR string This function first reads starting bytes to determine the expected @@ -8484,91 +7961,86 @@ class binary_reader @return whether string creation completed */ - bool get_cbor_string(string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) - { - return false; - } - - switch (current) - { - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - { - return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); - } - - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7F: // UTF-8 string (indefinite length) - { - while (get() != 0xFF) - { - string_t chunk; - if (!get_cbor_string(chunk)) - { - return false; - } - result.append(chunk); + bool get_cbor_string(string_t &result) { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) { + return false; + } + + switch (current) { + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: { + return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); + } + + case 0x7F: // UTF-8 string (indefinite length) + { + while (get() != 0xFF) { + string_t chunk; + if (!get_cbor_string(chunk)) { + return false; + } + result.append(chunk); + } + return true; + } + + default: { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, + "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + + last_token, "string"))); + } } - return true; } - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"))); - } - } - } - - /*! + /*! @brief reads a CBOR byte array This function first reads starting bytes to determine the expected @@ -8579,562 +8051,535 @@ class binary_reader @return whether byte array creation completed */ - bool get_cbor_binary(binary_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) - { - return false; - } - - switch (current) - { - // Binary data (0x00..0x17 bytes follow) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - { - return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); - } - - case 0x58: // Binary data (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x59: // Binary data (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5A: // Binary data (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5B: // Binary data (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5F: // Binary data (indefinite length) - { - while (get() != 0xFF) - { - binary_t chunk; - if (!get_cbor_binary(chunk)) - { - return false; - } - result.insert(result.end(), chunk.begin(), chunk.end()); + bool get_cbor_binary(binary_t &result) { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) { + return false; + } + + switch (current) { + // Binary data (0x00..0x17 bytes follow) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: { + return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x58: // Binary data (one-byte uint8_t for n follows) + { + std::uint8_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x59: // Binary data (two-byte uint16_t for n follow) + { + std::uint16_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5A: // Binary data (four-byte uint32_t for n follow) + { + std::uint32_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5B: // Binary data (eight-byte uint64_t for n follow) + { + std::uint64_t len{}; + return get_number(input_format_t::cbor, len) && + get_binary(input_format_t::cbor, len, result); + } + + case 0x5F: // Binary data (indefinite length) + { + while (get() != 0xFF) { + binary_t chunk; + if (!get_cbor_binary(chunk)) { + return false; + } + result.insert(result.end(), chunk.begin(), chunk.end()); + } + return true; + } + + default: { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, + "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + + last_token, "binary"))); + } } - return true; } - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"))); - } - } - } - - /*! + /*! @param[in] len the length of the array or std::size_t(-1) for an array of indefinite size @param[in] tag_handler how CBOR tags should be treated @return whether array creation completed */ - bool get_cbor_array(const std::size_t len, - const cbor_tag_handler_t tag_handler) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) - { - return false; - } - - if (len != std::size_t(-1)) - { - for (std::size_t i = 0; i < len; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { + bool get_cbor_array(const std::size_t len, + const cbor_tag_handler_t tag_handler) { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) { return false; } - } - } - else - { - while (get() != 0xFF) - { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) - { - return false; + + if (len != std::size_t(-1)) { + for (std::size_t i = 0; i < len; ++i) { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { + return false; + } + } + } else { + while (get() != 0xFF) { + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) { + return false; + } + } } + + return sax->end_array(); } - } - return sax->end_array(); - } - - /*! + /*! @param[in] len the length of the object or std::size_t(-1) for an object of indefinite size @param[in] tag_handler how CBOR tags should be treated @return whether object creation completed */ - bool get_cbor_object(const std::size_t len, - const cbor_tag_handler_t tag_handler) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) - { - return false; - } - - string_t key; - if (len != std::size_t(-1)) - { - for (std::size_t i = 0; i < len; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) - { + bool get_cbor_object(const std::size_t len, + const cbor_tag_handler_t tag_handler) { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) { return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; + string_t key; + if (len != std::size_t(-1)) { + for (std::size_t i = 0; i < len; ++i) { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { + return false; + } + key.clear(); + } + } else { + while (get() != 0xFF) { + if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { + return false; + } + key.clear(); + } } - key.clear(); + + return sax->end_object(); } - } - else - { - while (get() != 0xFF) - { - if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; - } - key.clear(); - } - } + ///////////// + // MsgPack // + ///////////// - return sax->end_object(); - } - - ///////////// - // MsgPack // - ///////////// - - /*! + /*! @return whether a valid MessagePack value was passed to the SAX parser */ - bool parse_msgpack_internal() - { - switch (get()) - { - // EOF - case std::char_traits::eof(): - return unexpect_eof(input_format_t::msgpack, "value"); + bool parse_msgpack_internal() { + switch (get()) { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::msgpack, "value"); - // positive fixint - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1A: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5C: - case 0x5D: - case 0x5E: - case 0x5F: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x79: - case 0x7A: - case 0x7B: - case 0x7C: - case 0x7D: - case 0x7E: - case 0x7F: - return sax->number_unsigned(static_cast(current)); + // positive fixint + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + return sax->number_unsigned(static_cast(current)); - // fixmap - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); + // fixmap + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); - // fixarray - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9A: - case 0x9B: - case 0x9C: - case 0x9D: - case 0x9E: - case 0x9F: - return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); + // fixarray + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: + return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); - // fixstr - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - case 0xD9: // str 8 - case 0xDA: // str 16 - case 0xDB: // str 32 - { - string_t s; - return get_msgpack_string(s) && sax->string(s); + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + case 0xD9: // str 8 + case 0xDA: // str 16 + case 0xDB: // str 32 + { + string_t s; + return get_msgpack_string(s) && sax->string(s); + } + + case 0xC0: // nil + return sax->null(); + + case 0xC2: // false + return sax->boolean(false); + + case 0xC3: // true + return sax->boolean(true); + + case 0xC4: // bin 8 + case 0xC5: // bin 16 + case 0xC6: // bin 32 + case 0xC7: // ext 8 + case 0xC8: // ext 16 + case 0xC9: // ext 32 + case 0xD4: // fixext 1 + case 0xD5: // fixext 2 + case 0xD6: // fixext 4 + case 0xD7: // fixext 8 + case 0xD8: // fixext 16 + { + binary_t b; + return get_msgpack_binary(b) && sax->binary(b); + } + + case 0xCA: // float 32 + { + float number{}; + return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + } + + case 0xCB: // float 64 + { + double number{}; + return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); + } + + case 0xCC: // uint 8 + { + std::uint8_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCD: // uint 16 + { + std::uint16_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCE: // uint 32 + { + std::uint32_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xCF: // uint 64 + { + std::uint64_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); + } + + case 0xD0: // int 8 + { + std::int8_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD1: // int 16 + { + std::int16_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD2: // int 32 + { + std::int32_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xD3: // int 64 + { + std::int64_t number{}; + return get_number(input_format_t::msgpack, number) && sax->number_integer(number); + } + + case 0xDC: // array 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + } + + case 0xDD: // array 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + } + + case 0xDE: // map 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + } + + case 0xDF: // map 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + } + + // negative fixint + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + case 0xFF: + return sax->number_integer(static_cast(current)); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"))); + } + } } - case 0xC0: // nil - return sax->null(); - - case 0xC2: // false - return sax->boolean(false); - - case 0xC3: // true - return sax->boolean(true); - - case 0xC4: // bin 8 - case 0xC5: // bin 16 - case 0xC6: // bin 32 - case 0xC7: // ext 8 - case 0xC8: // ext 16 - case 0xC9: // ext 32 - case 0xD4: // fixext 1 - case 0xD5: // fixext 2 - case 0xD6: // fixext 4 - case 0xD7: // fixext 8 - case 0xD8: // fixext 16 - { - binary_t b; - return get_msgpack_binary(b) && sax->binary(b); - } - - case 0xCA: // float 32 - { - float number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); - } - - case 0xCB: // float 64 - { - double number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); - } - - case 0xCC: // uint 8 - { - std::uint8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCD: // uint 16 - { - std::uint16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCE: // uint 32 - { - std::uint32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCF: // uint 64 - { - std::uint64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xD0: // int 8 - { - std::int8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD1: // int 16 - { - std::int16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD2: // int 32 - { - std::int32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD3: // int 64 - { - std::int64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xDC: // array 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); - } - - case 0xDD: // array 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); - } - - case 0xDE: // map 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); - } - - case 0xDF: // map 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); - } - - // negative fixint - case 0xE0: - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xED: - case 0xEE: - case 0xEF: - case 0xF0: - case 0xF1: - case 0xF2: - case 0xF3: - case 0xF4: - case 0xF5: - case 0xF6: - case 0xF7: - case 0xF8: - case 0xF9: - case 0xFA: - case 0xFB: - case 0xFC: - case 0xFD: - case 0xFE: - case 0xFF: - return sax->number_integer(static_cast(current)); - - default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"))); - } - } - } - - /*! + /*! @brief reads a MessagePack string This function first reads starting bytes to determine the expected @@ -9144,79 +8589,76 @@ class binary_reader @return whether string creation completed */ - bool get_msgpack_string(string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) - { - return false; - } + bool get_msgpack_string(string_t &result) { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) { + return false; + } - switch (current) - { - // fixstr - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - { - return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); + switch (current) { + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: { + return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); + } + + case 0xD9: // str 8 + { + std::uint8_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + case 0xDA: // str 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + case 0xDB: // str 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); + } + + default: { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, + "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + + last_token, "string"))); + } + } } - case 0xD9: // str 8 - { - std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - case 0xDA: // str 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - case 0xDB: // str 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"))); - } - } - } - - /*! + /*! @brief reads a MessagePack byte array This function first reads starting bytes to determine the expected @@ -9226,182 +8668,169 @@ class binary_reader @return whether byte array creation completed */ - bool get_msgpack_binary(binary_t& result) - { - // helper function to set the subtype - auto assign_and_return_true = [&result](std::int8_t subtype) - { - result.set_subtype(static_cast(subtype)); - return true; - }; + bool get_msgpack_binary(binary_t &result) { + // helper function to set the subtype + auto assign_and_return_true = [&result](std::int8_t subtype) { + result.set_subtype(static_cast(subtype)); + return true; + }; - switch (current) - { - case 0xC4: // bin 8 - { - std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); + switch (current) { + case 0xC4: // bin 8 + { + std::uint8_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC5: // bin 16 + { + std::uint16_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC6: // bin 32 + { + std::uint32_t len{}; + return get_number(input_format_t::msgpack, len) && + get_binary(input_format_t::msgpack, len, result); + } + + case 0xC7: // ext 8 + { + std::uint8_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xC8: // ext 16 + { + std::uint16_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xC9: // ext 32 + { + std::uint32_t len{}; + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, len) && + get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, len, result) && + assign_and_return_true(subtype); + } + + case 0xD4: // fixext 1 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 1, result) && + assign_and_return_true(subtype); + } + + case 0xD5: // fixext 2 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 2, result) && + assign_and_return_true(subtype); + } + + case 0xD6: // fixext 4 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 4, result) && + assign_and_return_true(subtype); + } + + case 0xD7: // fixext 8 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 8, result) && + assign_and_return_true(subtype); + } + + case 0xD8: // fixext 16 + { + std::int8_t subtype{}; + return get_number(input_format_t::msgpack, subtype) && + get_binary(input_format_t::msgpack, 16, result) && + assign_and_return_true(subtype); + } + + default: // LCOV_EXCL_LINE + return false; // LCOV_EXCL_LINE + } } - case 0xC5: // bin 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC6: // bin 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC7: // ext 8 - { - std::uint8_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xC8: // ext 16 - { - std::uint16_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xC9: // ext 32 - { - std::uint32_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xD4: // fixext 1 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 1, result) && - assign_and_return_true(subtype); - } - - case 0xD5: // fixext 2 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 2, result) && - assign_and_return_true(subtype); - } - - case 0xD6: // fixext 4 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 4, result) && - assign_and_return_true(subtype); - } - - case 0xD7: // fixext 8 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 8, result) && - assign_and_return_true(subtype); - } - - case 0xD8: // fixext 16 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 16, result) && - assign_and_return_true(subtype); - } - - default: // LCOV_EXCL_LINE - return false; // LCOV_EXCL_LINE - } - } - - /*! + /*! @param[in] len the length of the array @return whether array creation completed */ - bool get_msgpack_array(const std::size_t len) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) - { - return false; - } + bool get_msgpack_array(const std::size_t len) { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) { + return false; + } - for (std::size_t i = 0; i < len; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) - { - return false; + for (std::size_t i = 0; i < len; ++i) { + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) { + return false; + } + } + + return sax->end_array(); } - } - return sax->end_array(); - } - - /*! + /*! @param[in] len the length of the object @return whether object creation completed */ - bool get_msgpack_object(const std::size_t len) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) - { - return false; - } + bool get_msgpack_object(const std::size_t len) { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) { + return false; + } - string_t key; - for (std::size_t i = 0; i < len; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) - { - return false; + string_t key; + for (std::size_t i = 0; i < len; ++i) { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) { + return false; + } + key.clear(); + } + + return sax->end_object(); } - if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) - { - return false; - } - key.clear(); - } + //////////// + // UBJSON // + //////////// - return sax->end_object(); - } - - //////////// - // UBJSON // - //////////// - - /*! + /*! @param[in] get_char whether a new character should be retrieved from the input (true, default) or whether the last read character should be considered instead @return whether a valid UBJSON value was passed to the SAX parser */ - bool parse_ubjson_internal(const bool get_char = true) - { - return get_ubjson_value(get_char ? get_ignore_noop() : current); - } + bool parse_ubjson_internal(const bool get_char = true) { + return get_ubjson_value(get_char ? get_ignore_noop() : current); + } - /*! + /*! @brief reads a UBJSON string This function is either called after reading the 'S' byte explicitly @@ -9415,128 +8844,110 @@ class binary_reader @return whether string creation completed */ - bool get_ubjson_string(string_t& result, const bool get_char = true) - { - if (get_char) - { - get(); // TODO(niels): may we ignore N here? - } + bool get_ubjson_string(string_t &result, const bool get_char = true) { + if (get_char) { + get(); // TODO(niels): may we ignore N here? + } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) - { - return false; - } + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) { + return false; + } - switch (current) - { - case 'U': - { - std::uint8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + switch (current) { + case 'U': { + std::uint8_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'i': { + std::int8_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'I': { + std::int16_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'l': { + std::int32_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + case 'L': { + std::int64_t len{}; + return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + } + + default: + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, + "expected length type specification (U, i, I, l, L); last byte: 0x" + + last_token, "string"))); + } } - case 'i': - { - std::int8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'I': - { - std::int16_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'l': - { - std::int32_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'L': - { - std::int64_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - default: - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"))); - } - } - - /*! + /*! @param[out] result determined size @return whether size determination completed */ - bool get_ubjson_size_value(std::size_t& result) - { - switch (get_ignore_noop()) - { - case 'U': - { - std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; + bool get_ubjson_size_value(std::size_t &result) { + switch (get_ignore_noop()) { + case 'U': { + std::uint8_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) { + return false; + } + result = static_cast(number); + return true; + } + + case 'i': { + std::int8_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) { + return false; + } + result = static_cast(number); + return true; + } + + case 'I': { + std::int16_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) { + return false; + } + result = static_cast(number); + return true; + } + + case 'l': { + std::int32_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) { + return false; + } + result = static_cast(number); + return true; + } + + case 'L': { + std::int64_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) { + return false; + } + result = static_cast(number); + return true; + } + + default: { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, + "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + + last_token, "size"))); + } } - result = static_cast(number); - return true; } - case 'i': - { - std::int8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'I': - { - std::int16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'l': - { - std::int32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'L': - { - std::int64_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"))); - } - } - } - - /*! + /*! @brief determine the type and size for a container In the optimized UBJSON format, a type and a size can be provided to allow @@ -9546,339 +8957,287 @@ class binary_reader @return whether pair creation completed */ - bool get_ubjson_size_type(std::pair& result) - { - result.first = string_t::npos; // size - result.second = 0; // type + bool get_ubjson_size_type(std::pair &result) { + result.first = string_t::npos; // size + result.second = 0; // type - get_ignore_noop(); + get_ignore_noop(); - if (current == '$') - { - result.second = get(); // must not ignore 'N', because 'N' maybe the type - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type"))) - { - return false; - } + if (current == '$') { + result.second = get(); // must not ignore 'N', because 'N' maybe the type + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type"))) { + return false; + } - get_ignore_noop(); - if (JSON_HEDLEY_UNLIKELY(current != '#')) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) - { - return false; + get_ignore_noop(); + if (JSON_HEDLEY_UNLIKELY(current != '#')) { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) { + return false; + } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, + "size"))); + } + + return get_ubjson_size_value(result.first); } - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"))); + + if (current == '#') { + return get_ubjson_size_value(result.first); + } + + return true; } - return get_ubjson_size_value(result.first); - } - - if (current == '#') - { - return get_ubjson_size_value(result.first); - } - - return true; - } - - /*! + /*! @param prefix the previously read or set type prefix @return whether value creation completed */ - bool get_ubjson_value(const char_int_type prefix) - { - switch (prefix) - { - case std::char_traits::eof(): // EOF - return unexpect_eof(input_format_t::ubjson, "value"); + bool get_ubjson_value(const char_int_type prefix) { + switch (prefix) { + case std::char_traits::eof(): // EOF + return unexpect_eof(input_format_t::ubjson, "value"); - case 'T': // true - return sax->boolean(true); - case 'F': // false - return sax->boolean(false); + case 'T': // true + return sax->boolean(true); + case 'F': // false + return sax->boolean(false); - case 'Z': // null - return sax->null(); + case 'Z': // null + return sax->null(); - case 'U': - { - std::uint8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number); - } + case 'U': { + std::uint8_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number); + } - case 'i': - { - std::int8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } + case 'i': { + std::int8_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } - case 'I': - { - std::int16_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } + case 'I': { + std::int16_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } - case 'l': - { - std::int32_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } + case 'l': { + std::int32_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } - case 'L': - { - std::int64_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } + case 'L': { + std::int64_t number{}; + return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + } - case 'd': - { - float number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); - } + case 'd': { + float number{}; + return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + } - case 'D': - { - double number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); - } + case 'D': { + double number{}; + return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + } - case 'H': - { - return get_ubjson_high_precision_number(); - } + case 'H': { + return get_ubjson_high_precision_number(); + } - case 'C': // char - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char"))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(current > 127)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"))); - } - string_t s(1, static_cast(current)); - return sax->string(s); - } - - case 'S': // string - { - string_t s; - return get_ubjson_string(s) && sax->string(s); - } - - case '[': // array - return get_ubjson_array(); - - case '{': // object - return get_ubjson_object(); - - default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"))); - } - } - } - - /*! - @return whether array creation completed - */ - bool get_ubjson_array() - { - std::pair size_and_type; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) - { - return false; - } - - if (size_and_type.first != string_t::npos) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) - { - return false; - } - - if (size_and_type.second != 0) - { - if (size_and_type.second != 'N') - { - for (std::size_t i = 0; i < size_and_type.first; ++i) + case 'C': // char { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char"))) { return false; } + if (JSON_HEDLEY_UNLIKELY(current > 127)) { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, + "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + + last_token, "char"))); + } + string_t s(1, static_cast(current)); + return sax->string(s); } - } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) + + case 'S': // string { - return false; + string_t s; + return get_ubjson_string(s) && sax->string(s); + } + + case '[': // array + return get_ubjson_array(); + + case '{': // object + return get_ubjson_object(); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"))); } } } - } - else - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } - while (current != ']') - { - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) - { + /*! + @return whether array creation completed + */ + bool get_ubjson_array() { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) { return false; } - get_ignore_noop(); + + if (size_and_type.first != string_t::npos) { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) { + return false; + } + + if (size_and_type.second != 0) { + if (size_and_type.second != 'N') { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) { + return false; + } + } + } + } else { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) { + return false; + } + } + } + } else { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) { + return false; + } + + while (current != ']') { + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) { + return false; + } + get_ignore_noop(); + } + } + + return sax->end_array(); } - } - return sax->end_array(); - } - - /*! + /*! @return whether object creation completed */ - bool get_ubjson_object() - { - std::pair size_and_type; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) - { - return false; - } - - string_t key; - if (size_and_type.first != string_t::npos) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) - { - return false; - } - - if (size_and_type.second != 0) - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { - return false; - } - key.clear(); - } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; - } - key.clear(); - } - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } - - while (current != '}') - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) - { + bool get_ubjson_object() { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) { return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; + + string_t key; + if (size_and_type.first != string_t::npos) { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) { + return false; + } + + if (size_and_type.second != 0) { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) { + return false; + } + key.clear(); + } + } else { + for (std::size_t i = 0; i < size_and_type.first; ++i) { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) { + return false; + } + key.clear(); + } + } + } else { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) { + return false; + } + + while (current != '}') { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) { + return false; + } + if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) { + return false; + } + get_ignore_noop(); + key.clear(); + } } - get_ignore_noop(); - key.clear(); + + return sax->end_object(); } - } - return sax->end_object(); - } + // Note, no reader for UBJSON binary types is implemented because they do + // not exist - // Note, no reader for UBJSON binary types is implemented because they do - // not exist + bool get_ubjson_high_precision_number() { + // get size of following number string + std::size_t size{}; + auto res = get_ubjson_size_value(size); + if (JSON_HEDLEY_UNLIKELY(!res)) { + return res; + } - bool get_ubjson_high_precision_number() - { - // get size of following number string - std::size_t size{}; - auto res = get_ubjson_size_value(size); - if (JSON_HEDLEY_UNLIKELY(!res)) - { - return res; - } + // get number string + std::vector number_vector; + for (std::size_t i = 0; i < size; ++i) { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number"))) { + return false; + } + number_vector.push_back(static_cast(current)); + } - // get number string - std::vector number_vector; - for (std::size_t i = 0; i < size; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number"))) - { - return false; + // parse number string + auto number_ia = detail::input_adapter(std::forward(number_vector)); + auto number_lexer = detail::lexer(std::move(number_ia), false); + const auto result_number = number_lexer.scan(); + const auto number_string = number_lexer.get_token_string(); + const auto result_remainder = number_lexer.scan(); + + using token_type = typename detail::lexer_base::token_type; + + if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) { + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, + exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), + "high-precision number"))); + } + + switch (result_number) { + case token_type::value_integer: + return sax->number_integer(number_lexer.get_number_integer()); + case token_type::value_unsigned: + return sax->number_unsigned(number_lexer.get_number_unsigned()); + case token_type::value_float: + return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); + default: + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, + exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), + "high-precision number"))); + } } - number_vector.push_back(static_cast(current)); - } - // parse number string - auto number_ia = detail::input_adapter(std::forward(number_vector)); - auto number_lexer = detail::lexer(std::move(number_ia), false); - const auto result_number = number_lexer.scan(); - const auto number_string = number_lexer.get_token_string(); - const auto result_remainder = number_lexer.scan(); + /////////////////////// + // Utility functions // + /////////////////////// - using token_type = typename detail::lexer_base::token_type; - - if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) - { - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"))); - } - - switch (result_number) - { - case token_type::value_integer: - return sax->number_integer(number_lexer.get_number_integer()); - case token_type::value_unsigned: - return sax->number_unsigned(number_lexer.get_number_unsigned()); - case token_type::value_float: - return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); - default: - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"))); - } - } - - /////////////////////// - // Utility functions // - /////////////////////// - - /*! + /*! @brief get next character from the input This function provides the interface to the used input adapter. It does @@ -9887,27 +9246,23 @@ class binary_reader @return character read from the input */ - char_int_type get() - { - ++chars_read; - return current = ia.get_character(); - } + char_int_type get() { + ++chars_read; + return current = ia.get_character(); + } - /*! + /*! @return character read from the input after ignoring all 'N' entries */ - char_int_type get_ignore_noop() - { - do - { - get(); - } - while (current == 'N'); + char_int_type get_ignore_noop() { + do { + get(); + } while (current == 'N'); - return current; - } + return current; + } - /* + /* @brief read a number from the input @tparam NumberType the type of the number @@ -9920,36 +9275,30 @@ class binary_reader bytes in CBOR, MessagePack, and UBJSON are stored in network order (big endian) and therefore need reordering on little endian systems. */ - template - bool get_number(const input_format_t format, NumberType& result) - { - // step 1: read input into array with system's byte order - std::array vec; - for (std::size_t i = 0; i < sizeof(NumberType); ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) - { - return false; + template + bool get_number(const input_format_t format, NumberType &result) { + // step 1: read input into array with system's byte order + std::array vec; + for (std::size_t i = 0; i < sizeof(NumberType); ++i) { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) { + return false; + } + + // reverse byte order prior to conversion if necessary + if (is_little_endian != InputIsLittleEndian) { + vec[sizeof(NumberType) - i - 1] = static_cast(current); + } else { + vec[i] = static_cast(current); // LCOV_EXCL_LINE + } + } + + // step 2: convert array into number of type T and return + std::memcpy(&result, vec.data(), sizeof(NumberType)); + return true; } - // reverse byte order prior to conversion if necessary - if (is_little_endian != InputIsLittleEndian) - { - vec[sizeof(NumberType) - i - 1] = static_cast(current); - } - else - { - vec[i] = static_cast(current); // LCOV_EXCL_LINE - } - } - - // step 2: convert array into number of type T and return - std::memcpy(&result, vec.data(), sizeof(NumberType)); - return true; - } - - /*! + /*! @brief create a string by reading characters from the input @tparam NumberType the type of the number @@ -9963,26 +9312,23 @@ class binary_reader may be too large. Usually, @ref unexpect_eof() detects the end of the input before we run out of string memory. */ - template - bool get_string(const input_format_t format, - const NumberType len, - string_t& result) - { - bool success = true; - for (NumberType i = 0; i < len; i++) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) - { - success = false; - break; + template + bool get_string(const input_format_t format, + const NumberType len, + string_t &result) { + bool success = true; + for (NumberType i = 0; i < len; i++) { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) { + success = false; + break; + } + result.push_back(static_cast(current)); + }; + return success; } - result.push_back(static_cast(current)); - }; - return success; - } - /*! + /*! @brief create a byte array by reading bytes from the input @tparam NumberType the type of the number @@ -9996,105 +9342,97 @@ class binary_reader may be too large. Usually, @ref unexpect_eof() detects the end of the input before we run out of memory. */ - template - bool get_binary(const input_format_t format, - const NumberType len, - binary_t& result) - { - bool success = true; - for (NumberType i = 0; i < len; i++) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) - { - success = false; - break; + template + bool get_binary(const input_format_t format, + const NumberType len, + binary_t &result) { + bool success = true; + for (NumberType i = 0; i < len; i++) { + get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) { + success = false; + break; + } + result.push_back(static_cast(current)); + } + return success; } - result.push_back(static_cast(current)); - } - return success; - } - /*! + /*! @param[in] format the current format (for diagnostics) @param[in] context further context information (for diagnostics) @return whether the last read character is not EOF */ - JSON_HEDLEY_NON_NULL(3) - bool unexpect_eof(const input_format_t format, const char* context) const - { - if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) - { - return sax->parse_error(chars_read, "", - parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context))); - } - return true; - } + JSON_HEDLEY_NON_NULL(3) + bool unexpect_eof(const input_format_t format, const char *context) const { + if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) { + return sax->parse_error(chars_read, "", + parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context))); + } + return true; + } - /*! + /*! @return a string representation of the last read byte */ - std::string get_token_string() const - { - std::array cr{{}}; - (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current)); - return std::string{cr.data()}; - } + std::string get_token_string() const { + std::array cr{{}}; + (std::snprintf) (cr.data(), cr.size(), "%.2hhX", static_cast(current)); + return std::string{cr.data()}; + } - /*! + /*! @param[in] format the current format @param[in] detail a detailed error message @param[in] context further context information @return a message string to use in the parse_error exceptions */ - std::string exception_message(const input_format_t format, - const std::string& detail, - const std::string& context) const - { - std::string error_msg = "syntax error while parsing "; + std::string exception_message(const input_format_t format, + const std::string &detail, + const std::string &context) const { + std::string error_msg = "syntax error while parsing "; - switch (format) - { - case input_format_t::cbor: - error_msg += "CBOR"; - break; + switch (format) { + case input_format_t::cbor: + error_msg += "CBOR"; + break; - case input_format_t::msgpack: - error_msg += "MessagePack"; - break; + case input_format_t::msgpack: + error_msg += "MessagePack"; + break; - case input_format_t::ubjson: - error_msg += "UBJSON"; - break; + case input_format_t::ubjson: + error_msg += "UBJSON"; + break; - case input_format_t::bson: - error_msg += "BSON"; - break; + case input_format_t::bson: + error_msg += "BSON"; + break; - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // LCOV_EXCL_LINE + } - return error_msg + " " + context + ": " + detail; - } + return error_msg + " " + context + ": " + detail; + } - private: - /// input adapter - InputAdapterType ia; + private: + /// input adapter + InputAdapterType ia; - /// the current character - char_int_type current = std::char_traits::eof(); + /// the current character + char_int_type current = std::char_traits::eof(); - /// the number of characters read - std::size_t chars_read = 0; + /// the number of characters read + std::size_t chars_read = 0; - /// whether we can assume little endianess - const bool is_little_endian = little_endianess(); + /// whether we can assume little endianess + const bool is_little_endian = little_endianess(); - /// the SAX parser - json_sax_t* sax = nullptr; -}; -} // namespace detail + /// the SAX parser + json_sax_t *sax = nullptr; + }; + } // namespace detail } // namespace nlohmann // #include @@ -10126,64 +9464,57 @@ class binary_reader // #include -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { //////////// // parser // //////////// -enum class parse_event_t : uint8_t -{ - /// the parser read `{` and started to process a JSON object - object_start, - /// the parser read `}` and finished processing a JSON object - object_end, - /// the parser read `[` and started to process a JSON array - array_start, - /// the parser read `]` and finished processing a JSON array - array_end, - /// the parser read a key of a value in an object - key, - /// the parser finished reading a JSON value - value -}; + enum class parse_event_t : uint8_t { + /// the parser read `{` and started to process a JSON object + object_start, + /// the parser read `}` and finished processing a JSON object + object_end, + /// the parser read `[` and started to process a JSON array + array_start, + /// the parser read `]` and finished processing a JSON array + array_end, + /// the parser read a key of a value in an object + key, + /// the parser finished reading a JSON value + value + }; -template -using parser_callback_t = - std::function; + template + using parser_callback_t = + std::function; /*! @brief syntax analysis This class implements a recursive descent parser. */ -template -class parser -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using lexer_t = lexer; - using token_type = typename lexer_t::token_type; + template + class parser { + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using lexer_t = lexer; + using token_type = typename lexer_t::token_type; - public: - /// a parser reading from an input adapter - explicit parser(InputAdapterType&& adapter, - const parser_callback_t cb = nullptr, - const bool allow_exceptions_ = true, - const bool skip_comments = false) - : callback(cb) - , m_lexer(std::move(adapter), skip_comments) - , allow_exceptions(allow_exceptions_) - { - // read first token - get_token(); - } + public: + /// a parser reading from an input adapter + explicit parser(InputAdapterType &&adapter, + const parser_callback_t cb = nullptr, + const bool allow_exceptions_ = true, + const bool skip_comments = false) + : callback(cb), m_lexer(std::move(adapter), skip_comments), allow_exceptions(allow_exceptions_) { + // read first token + get_token(); + } - /*! + /*! @brief public parser interface @param[in] strict whether to expect the last token to be EOF @@ -10193,422 +9524,359 @@ class parser @throw parse_error.102 if to_unicode fails or surrogate error @throw parse_error.103 if to_unicode fails */ - void parse(const bool strict, BasicJsonType& result) - { - if (callback) - { - json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); - sax_parse_internal(&sdp); - result.assert_invariant(); + void parse(const bool strict, BasicJsonType &result) { + if (callback) { + json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); + sax_parse_internal(&sdp); + result.assert_invariant(); - // in strict mode, input must be completely read - if (strict && (get_token() != token_type::end_of_input)) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"))); + // in strict mode, input must be completely read + if (strict && (get_token() != token_type::end_of_input)) { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) { + result = value_t::discarded; + return; + } + + // set top-level value to null if it was discarded by the callback + // function + if (result.is_discarded()) { + result = nullptr; + } + } else { + json_sax_dom_parser sdp(result, allow_exceptions); + sax_parse_internal(&sdp); + result.assert_invariant(); + + // in strict mode, input must be completely read + if (strict && (get_token() != token_type::end_of_input)) { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) { + result = value_t::discarded; + return; + } + } } - // in case of an error, return discarded value - if (sdp.is_errored()) - { - result = value_t::discarded; - return; - } - - // set top-level value to null if it was discarded by the callback - // function - if (result.is_discarded()) - { - result = nullptr; - } - } - else - { - json_sax_dom_parser sdp(result, allow_exceptions); - sax_parse_internal(&sdp); - result.assert_invariant(); - - // in strict mode, input must be completely read - if (strict && (get_token() != token_type::end_of_input)) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"))); - } - - // in case of an error, return discarded value - if (sdp.is_errored()) - { - result = value_t::discarded; - return; - } - } - } - - /*! + /*! @brief public accept interface @param[in] strict whether to expect the last token to be EOF @return whether the input is a proper JSON text */ - bool accept(const bool strict = true) - { - json_sax_acceptor sax_acceptor; - return sax_parse(&sax_acceptor, strict); - } + bool accept(const bool strict = true) { + json_sax_acceptor sax_acceptor; + return sax_parse(&sax_acceptor, strict); + } - template - JSON_HEDLEY_NON_NULL(2) - bool sax_parse(SAX* sax, const bool strict = true) - { - (void)detail::is_sax_static_asserts {}; - const bool result = sax_parse_internal(sax); + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse(SAX *sax, const bool strict = true) { + (void) detail::is_sax_static_asserts{}; + const bool result = sax_parse_internal(sax); - // strict mode: next byte must be EOF - if (result && strict && (get_token() != token_type::end_of_input)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"))); - } + // strict mode: next byte must be EOF + if (result && strict && (get_token() != token_type::end_of_input)) { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); + } - return result; - } + return result; + } - private: - template - JSON_HEDLEY_NON_NULL(2) - bool sax_parse_internal(SAX* sax) - { - // stack to remember the hierarchy of structured values we are parsing - // true = array; false = object - std::vector states; - // value to avoid a goto (see comment where set to true) - bool skip_to_state_evaluation = false; + private: + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse_internal(SAX *sax) { + // stack to remember the hierarchy of structured values we are parsing + // true = array; false = object + std::vector states; + // value to avoid a goto (see comment where set to true) + bool skip_to_state_evaluation = false; - while (true) - { - if (!skip_to_state_evaluation) - { - // invariant: get_token() was called before each iteration - switch (last_token) - { - case token_type::begin_object: + while (true) { + if (!skip_to_state_evaluation) { + // invariant: get_token() was called before each iteration + switch (last_token) { + case token_type::begin_object: { + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) { + return false; + } + + // closing } -> we are done + if (get_token() == token_type::end_object) { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) { + return false; + } + break; + } + + // parse key + if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"))); + } + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"))); + } + + // remember we are now inside an object + states.push_back(false); + + // parse values + get_token(); + continue; + } + + case token_type::begin_array: { + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) { + return false; + } + + // closing ] -> we are done + if (get_token() == token_type::end_array) { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) { + return false; + } + break; + } + + // remember we are now inside an array + states.push_back(true); + + // parse values (no need to call get_token) + continue; + } + + case token_type::value_float: { + const auto res = m_lexer.get_number_float(); + + if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'")); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) { + return false; + } + + break; + } + + case token_type::literal_false: { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) { + return false; + } + break; + } + + case token_type::literal_null: { + if (JSON_HEDLEY_UNLIKELY(!sax->null())) { + return false; + } + break; + } + + case token_type::literal_true: { + if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) { + return false; + } + break; + } + + case token_type::value_integer: { + if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) { + return false; + } + break; + } + + case token_type::value_string: { + if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) { + return false; + } + break; + } + + case token_type::value_unsigned: { + if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) { + return false; + } + break; + } + + case token_type::parse_error: { + // using "uninitialized" to avoid "expected" message + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::uninitialized, "value"))); + } + + default: // the last token was unexpected + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::literal_or_value, "value"))); + } + } + } else { + skip_to_state_evaluation = false; + } + + // we reached this line after we successfully parsed a value + if (states.empty()) { + // empty stack: we reached the end of the hierarchy: done + return true; + } + + if (states.back()) // array { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; + // comma -> next value + if (get_token() == token_type::value_separator) { + // parse a new value + get_token(); + continue; } - // closing } -> we are done - if (get_token() == token_type::end_object) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) - { + // closing ] + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) { + if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) { return false; } - break; + + // We are done with this array. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + JSON_ASSERT(!states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; } - // parse key - if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::value_string, "object key"))); - } - if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) - { - return false; - } - - // parse separator (:) - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::name_separator, "object separator"))); - } - - // remember we are now inside an object - states.push_back(false); - - // parse values - get_token(); - continue; - } - - case token_type::begin_array: + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_array, "array"))); + } else // object { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } + // comma -> next value + if (get_token() == token_type::value_separator) { + // parse key + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"))); + } - // closing ] -> we are done - if (get_token() == token_type::end_array) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) - { + if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { return false; } - break; + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"))); + } + + // parse values + get_token(); + continue; } - // remember we are now inside an array - states.push_back(true); + // closing } + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) { + if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) { + return false; + } - // parse values (no need to call get_token) - continue; - } - - case token_type::value_float: - { - const auto res = m_lexer.get_number_float(); - - if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'")); + // We are done with this object. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + JSON_ASSERT(!states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; } - if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) - { - return false; - } - - break; - } - - case token_type::literal_false: - { - if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) - { - return false; - } - break; - } - - case token_type::literal_null: - { - if (JSON_HEDLEY_UNLIKELY(!sax->null())) - { - return false; - } - break; - } - - case token_type::literal_true: - { - if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) - { - return false; - } - break; - } - - case token_type::value_integer: - { - if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) - { - return false; - } - break; - } - - case token_type::value_string: - { - if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) - { - return false; - } - break; - } - - case token_type::value_unsigned: - { - if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) - { - return false; - } - break; - } - - case token_type::parse_error: - { - // using "uninitialized" to avoid "expected" message return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::uninitialized, "value"))); - } - - default: // the last token was unexpected - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::literal_or_value, "value"))); + exception_message(token_type::end_object, "object"))); } } } - else - { - skip_to_state_evaluation = false; + + /// get next token from lexer + token_type get_token() { + return last_token = m_lexer.scan(); } - // we reached this line after we successfully parsed a value - if (states.empty()) - { - // empty stack: we reached the end of the hierarchy: done - return true; + std::string exception_message(const token_type expected, const std::string &context) { + std::string error_msg = "syntax error "; + + if (!context.empty()) { + error_msg += "while parsing " + context + " "; + } + + error_msg += "- "; + + if (last_token == token_type::parse_error) { + error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + + m_lexer.get_token_string() + "'"; + } else { + error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); + } + + if (expected != token_type::uninitialized) { + error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); + } + + return error_msg; } - if (states.back()) // array - { - // comma -> next value - if (get_token() == token_type::value_separator) - { - // parse a new value - get_token(); - continue; - } - - // closing ] - if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) - { - return false; - } - - // We are done with this array. Before we can parse a - // new value, we need to evaluate the new state first. - // By setting skip_to_state_evaluation to false, we - // are effectively jumping to the beginning of this if. - JSON_ASSERT(!states.empty()); - states.pop_back(); - skip_to_state_evaluation = true; - continue; - } - - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_array, "array"))); - } - else // object - { - // comma -> next value - if (get_token() == token_type::value_separator) - { - // parse key - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::value_string, "object key"))); - } - - if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) - { - return false; - } - - // parse separator (:) - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::name_separator, "object separator"))); - } - - // parse values - get_token(); - continue; - } - - // closing } - if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) - { - return false; - } - - // We are done with this object. Before we can parse a - // new value, we need to evaluate the new state first. - // By setting skip_to_state_evaluation to false, we - // are effectively jumping to the beginning of this if. - JSON_ASSERT(!states.empty()); - states.pop_back(); - skip_to_state_evaluation = true; - continue; - } - - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_object, "object"))); - } - } - } - - /// get next token from lexer - token_type get_token() - { - return last_token = m_lexer.scan(); - } - - std::string exception_message(const token_type expected, const std::string& context) - { - std::string error_msg = "syntax error "; - - if (!context.empty()) - { - error_msg += "while parsing " + context + " "; - } - - error_msg += "- "; - - if (last_token == token_type::parse_error) - { - error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + - m_lexer.get_token_string() + "'"; - } - else - { - error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); - } - - if (expected != token_type::uninitialized) - { - error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); - } - - return error_msg; - } - - private: - /// callback function - const parser_callback_t callback = nullptr; - /// the type of the last read token - token_type last_token = token_type::uninitialized; - /// the lexer - lexer_t m_lexer; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; -}; -} // namespace detail + private: + /// callback function + const parser_callback_t callback = nullptr; + /// the type of the last read token + token_type last_token = token_type::uninitialized; + /// the lexer + lexer_t m_lexer; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + }; + } // namespace detail } // namespace nlohmann // #include @@ -10620,10 +9888,8 @@ class parser #include // ptrdiff_t #include // numeric_limits -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /* @brief an iterator for primitive JSON types @@ -10633,130 +9899,112 @@ to "iterate" over primitive values. Internally, the iterator is modeled by a `difference_type` variable. Value begin_value (`0`) models the begin, end_value (`1`) models past the end. */ -class primitive_iterator_t -{ - private: - using difference_type = std::ptrdiff_t; - static constexpr difference_type begin_value = 0; - static constexpr difference_type end_value = begin_value + 1; + class primitive_iterator_t { + private: + using difference_type = std::ptrdiff_t; + static constexpr difference_type begin_value = 0; + static constexpr difference_type end_value = begin_value + 1; - /// iterator as signed integer type - difference_type m_it = (std::numeric_limits::min)(); + /// iterator as signed integer type + difference_type m_it = (std::numeric_limits::min)(); - public: - constexpr difference_type get_value() const noexcept - { - return m_it; - } + public: + constexpr difference_type get_value() const noexcept { + return m_it; + } - /// set iterator to a defined beginning - void set_begin() noexcept - { - m_it = begin_value; - } + /// set iterator to a defined beginning + void set_begin() noexcept { + m_it = begin_value; + } - /// set iterator to a defined past the end - void set_end() noexcept - { - m_it = end_value; - } + /// set iterator to a defined past the end + void set_end() noexcept { + m_it = end_value; + } - /// return whether the iterator can be dereferenced - constexpr bool is_begin() const noexcept - { - return m_it == begin_value; - } + /// return whether the iterator can be dereferenced + constexpr bool is_begin() const noexcept { + return m_it == begin_value; + } - /// return whether the iterator is at end - constexpr bool is_end() const noexcept - { - return m_it == end_value; - } + /// return whether the iterator is at end + constexpr bool is_end() const noexcept { + return m_it == end_value; + } - friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it == rhs.m_it; - } + friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { + return lhs.m_it == rhs.m_it; + } - friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it < rhs.m_it; - } + friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { + return lhs.m_it < rhs.m_it; + } - primitive_iterator_t operator+(difference_type n) noexcept - { - auto result = *this; - result += n; - return result; - } + primitive_iterator_t operator+(difference_type n) noexcept { + auto result = *this; + result += n; + return result; + } - friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it - rhs.m_it; - } + friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept { + return lhs.m_it - rhs.m_it; + } - primitive_iterator_t& operator++() noexcept - { - ++m_it; - return *this; - } + primitive_iterator_t &operator++() noexcept { + ++m_it; + return *this; + } - primitive_iterator_t const operator++(int) noexcept - { - auto result = *this; - ++m_it; - return result; - } + primitive_iterator_t const operator++(int) noexcept { + auto result = *this; + ++m_it; + return result; + } - primitive_iterator_t& operator--() noexcept - { - --m_it; - return *this; - } + primitive_iterator_t &operator--() noexcept { + --m_it; + return *this; + } - primitive_iterator_t const operator--(int) noexcept - { - auto result = *this; - --m_it; - return result; - } + primitive_iterator_t const operator--(int) noexcept { + auto result = *this; + --m_it; + return result; + } - primitive_iterator_t& operator+=(difference_type n) noexcept - { - m_it += n; - return *this; - } + primitive_iterator_t &operator+=(difference_type n) noexcept { + m_it += n; + return *this; + } - primitive_iterator_t& operator-=(difference_type n) noexcept - { - m_it -= n; - return *this; - } -}; -} // namespace detail + primitive_iterator_t &operator-=(difference_type n) noexcept { + m_it -= n; + return *this; + } + }; + } // namespace detail } // namespace nlohmann -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /*! @brief an iterator value @note This structure could easily be a union, but MSVC currently does not allow unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. */ -template struct internal_iterator -{ - /// iterator for JSON objects - typename BasicJsonType::object_t::iterator object_iterator {}; - /// iterator for JSON arrays - typename BasicJsonType::array_t::iterator array_iterator {}; - /// generic iterator for all other types - primitive_iterator_t primitive_iterator {}; -}; -} // namespace detail + template + struct internal_iterator { + /// iterator for JSON objects + typename BasicJsonType::object_t::iterator object_iterator{}; + /// iterator for JSON arrays + typename BasicJsonType::array_t::iterator array_iterator{}; + /// generic iterator for all other types + primitive_iterator_t primitive_iterator{}; + }; + } // namespace detail } // namespace nlohmann // #include @@ -10780,13 +10028,14 @@ template struct internal_iterator // #include -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { // forward declare, to be able to friend it later on -template class iteration_proxy; -template class iteration_proxy_value; + template + class iteration_proxy; + + template + class iteration_proxy_value; /*! @brief a template for a bidirectional iterator for the @ref basic_json class @@ -10804,80 +10053,74 @@ This class implements a both iterators (iterator and const_iterator) for the @since version 1.0.0, simplified in version 2.0.9, change to bidirectional iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) */ -template -class iter_impl -{ - /// allow basic_json to access private members - friend iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; - friend BasicJsonType; - friend iteration_proxy; - friend iteration_proxy_value; + template + class iter_impl { + /// allow basic_json to access private members + friend iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; + friend BasicJsonType; + friend iteration_proxy; + friend iteration_proxy_value; - using object_t = typename BasicJsonType::object_t; - using array_t = typename BasicJsonType::array_t; - // make sure BasicJsonType is basic_json or const basic_json - static_assert(is_basic_json::type>::value, - "iter_impl only accepts (const) basic_json"); + using object_t = typename BasicJsonType::object_t; + using array_t = typename BasicJsonType::array_t; + // make sure BasicJsonType is basic_json or const basic_json + static_assert(is_basic_json::type>::value, + "iter_impl only accepts (const) basic_json"); - public: + public: - /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. - /// The C++ Standard has never required user-defined iterators to derive from std::iterator. - /// A user-defined iterator should provide publicly accessible typedefs named - /// iterator_category, value_type, difference_type, pointer, and reference. - /// Note that value_type is required to be non-const, even for constant iterators. - using iterator_category = std::bidirectional_iterator_tag; + /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. + /// The C++ Standard has never required user-defined iterators to derive from std::iterator. + /// A user-defined iterator should provide publicly accessible typedefs named + /// iterator_category, value_type, difference_type, pointer, and reference. + /// Note that value_type is required to be non-const, even for constant iterators. + using iterator_category = std::bidirectional_iterator_tag; - /// the type of the values when the iterator is dereferenced - using value_type = typename BasicJsonType::value_type; - /// a type to represent differences between iterators - using difference_type = typename BasicJsonType::difference_type; - /// defines a pointer to the type iterated over (value_type) - using pointer = typename std::conditional::value, - typename BasicJsonType::const_pointer, - typename BasicJsonType::pointer>::type; - /// defines a reference to the type iterated over (value_type) - using reference = - typename std::conditional::value, - typename BasicJsonType::const_reference, - typename BasicJsonType::reference>::type; + /// the type of the values when the iterator is dereferenced + using value_type = typename BasicJsonType::value_type; + /// a type to represent differences between iterators + using difference_type = typename BasicJsonType::difference_type; + /// defines a pointer to the type iterated over (value_type) + using pointer = typename std::conditional::value, + typename BasicJsonType::const_pointer, + typename BasicJsonType::pointer>::type; + /// defines a reference to the type iterated over (value_type) + using reference = + typename std::conditional::value, + typename BasicJsonType::const_reference, + typename BasicJsonType::reference>::type; - /// default constructor - iter_impl() = default; + /// default constructor + iter_impl() = default; - /*! + /*! @brief constructor for a given JSON instance @param[in] object pointer to a JSON object for this iterator @pre object != nullptr @post The iterator is initialized; i.e. `m_object != nullptr`. */ - explicit iter_impl(pointer object) noexcept : m_object(object) - { - JSON_ASSERT(m_object != nullptr); + explicit iter_impl(pointer object) noexcept: m_object(object) { + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = typename object_t::iterator(); - break; + switch (m_object->m_type) { + case value_t::object: { + m_it.object_iterator = typename object_t::iterator(); + break; + } + + case value_t::array: { + m_it.array_iterator = typename array_t::iterator(); + break; + } + + default: { + m_it.primitive_iterator = primitive_iterator_t(); + break; + } + } } - case value_t::array: - { - m_it.array_iterator = typename array_t::iterator(); - break; - } - - default: - { - m_it.primitive_iterator = primitive_iterator_t(); - break; - } - } - } - - /*! + /*! @note The conventional copy constructor and copy assignment are implicitly defined. Combined with the following converting constructor and assignment, they support: (1) copy from iterator to iterator, (2) @@ -10886,523 +10129,457 @@ class iter_impl to iterator is not defined. */ - /*! + /*! @brief const copy constructor @param[in] other const iterator to copy from @note This copy constructor had to be defined explicitly to circumvent a bug occurring on msvc v19.0 compiler (VS 2015) debug build. For more information refer to: https://github.com/nlohmann/json/issues/1608 */ - iter_impl(const iter_impl& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} + iter_impl(const iter_impl &other) noexcept + : m_object(other.m_object), m_it(other.m_it) {} - /*! + /*! @brief converting assignment @param[in] other const iterator to copy from @return const/non-const iterator @note It is not checked whether @a other is initialized. */ - iter_impl& operator=(const iter_impl& other) noexcept - { - m_object = other.m_object; - m_it = other.m_it; - return *this; - } + iter_impl &operator=(const iter_impl &other) noexcept { + m_object = other.m_object; + m_it = other.m_it; + return *this; + } - /*! + /*! @brief converting constructor @param[in] other non-const iterator to copy from @note It is not checked whether @a other is initialized. */ - iter_impl(const iter_impl::type>& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} + iter_impl(const iter_impl::type> &other) noexcept + : m_object(other.m_object), m_it(other.m_it) {} - /*! + /*! @brief converting assignment @param[in] other non-const iterator to copy from @return const/non-const iterator @note It is not checked whether @a other is initialized. */ - iter_impl& operator=(const iter_impl::type>& other) noexcept - { - m_object = other.m_object; - m_it = other.m_it; - return *this; - } + iter_impl &operator=(const iter_impl::type> &other) noexcept { + m_object = other.m_object; + m_it = other.m_it; + return *this; + } - private: - /*! + private: + /*! @brief set the iterator to the first value @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - void set_begin() noexcept - { - JSON_ASSERT(m_object != nullptr); + void set_begin() noexcept { + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = m_object->m_value.object->begin(); - break; + switch (m_object->m_type) { + case value_t::object: { + m_it.object_iterator = m_object->m_value.object->begin(); + break; + } + + case value_t::array: { + m_it.array_iterator = m_object->m_value.array->begin(); + break; + } + + case value_t::null: { + // set to end so begin()==end() is true: null is empty + m_it.primitive_iterator.set_end(); + break; + } + + default: { + m_it.primitive_iterator.set_begin(); + break; + } + } } - case value_t::array: - { - m_it.array_iterator = m_object->m_value.array->begin(); - break; - } - - case value_t::null: - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } - - default: - { - m_it.primitive_iterator.set_begin(); - break; - } - } - } - - /*! + /*! @brief set the iterator past the last value @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - void set_end() noexcept - { - JSON_ASSERT(m_object != nullptr); + void set_end() noexcept { + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = m_object->m_value.object->end(); - break; + switch (m_object->m_type) { + case value_t::object: { + m_it.object_iterator = m_object->m_value.object->end(); + break; + } + + case value_t::array: { + m_it.array_iterator = m_object->m_value.array->end(); + break; + } + + default: { + m_it.primitive_iterator.set_end(); + break; + } + } } - case value_t::array: - { - m_it.array_iterator = m_object->m_value.array->end(); - break; - } - - default: - { - m_it.primitive_iterator.set_end(); - break; - } - } - } - - public: - /*! + public: + /*! @brief return a reference to the value pointed to by the iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - reference operator*() const - { - JSON_ASSERT(m_object != nullptr); + reference operator*() const { + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); - return m_it.object_iterator->second; - } + switch (m_object->m_type) { + case value_t::object: { + JSON_ASSERT(m_it.object_iterator != m_object->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()); - return *m_it.array_iterator; - } + case value_t::array: { + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + return *m_it.array_iterator; + } - case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value")); + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value")); - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) - { - return *m_object; + default: { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); } - } - } - /*! + /*! @brief dereference the iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - pointer operator->() const - { - JSON_ASSERT(m_object != nullptr); + pointer operator->() const { + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); - return &(m_it.object_iterator->second); - } + switch (m_object->m_type) { + case value_t::object: { + JSON_ASSERT(m_it.object_iterator != m_object->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()); - return &*m_it.array_iterator; - } + case value_t::array: { + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); + return &*m_it.array_iterator; + } - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) - { - return m_object; + default: { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) { + return m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); } - } - } - /*! + /*! @brief post-increment (it++) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl const operator++(int) - { - auto result = *this; - ++(*this); - return result; - } + iter_impl const operator++(int) { + auto result = *this; + ++(*this); + return result; + } - /*! + /*! @brief pre-increment (++it) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl& operator++() - { - JSON_ASSERT(m_object != nullptr); + iter_impl &operator++() { + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - { - std::advance(m_it.object_iterator, 1); - break; + switch (m_object->m_type) { + case value_t::object: { + std::advance(m_it.object_iterator, 1); + break; + } + + case value_t::array: { + std::advance(m_it.array_iterator, 1); + break; + } + + default: { + ++m_it.primitive_iterator; + break; + } + } + + return *this; } - case value_t::array: - { - std::advance(m_it.array_iterator, 1); - break; - } - - default: - { - ++m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! + /*! @brief post-decrement (it--) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl const operator--(int) - { - auto result = *this; - --(*this); - return result; - } + iter_impl const operator--(int) { + auto result = *this; + --(*this); + return result; + } - /*! + /*! @brief pre-decrement (--it) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl& operator--() - { - JSON_ASSERT(m_object != nullptr); + iter_impl &operator--() { + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - { - std::advance(m_it.object_iterator, -1); - break; + switch (m_object->m_type) { + case value_t::object: { + std::advance(m_it.object_iterator, -1); + break; + } + + case value_t::array: { + std::advance(m_it.array_iterator, -1); + break; + } + + default: { + --m_it.primitive_iterator; + break; + } + } + + return *this; } - case value_t::array: - { - std::advance(m_it.array_iterator, -1); - break; - } - - default: - { - --m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! + /*! @brief comparison: equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator==(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); - } + bool operator==(const iter_impl &other) const { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); + } - JSON_ASSERT(m_object != nullptr); + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - return (m_it.object_iterator == other.m_it.object_iterator); + switch (m_object->m_type) { + case value_t::object: + return (m_it.object_iterator == other.m_it.object_iterator); - case value_t::array: - return (m_it.array_iterator == other.m_it.array_iterator); + case value_t::array: + return (m_it.array_iterator == other.m_it.array_iterator); - default: - return (m_it.primitive_iterator == other.m_it.primitive_iterator); - } - } + default: + return (m_it.primitive_iterator == other.m_it.primitive_iterator); + } + } - /*! + /*! @brief comparison: not equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator!=(const iter_impl& other) const - { - return !operator==(other); - } + bool operator!=(const iter_impl &other) const { + return !operator==(other); + } - /*! + /*! @brief comparison: smaller @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator<(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); - } + bool operator<(const iter_impl &other) const { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); + } - JSON_ASSERT(m_object != nullptr); + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); + switch (m_object->m_type) { + case value_t::object: + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); - case value_t::array: - return (m_it.array_iterator < other.m_it.array_iterator); + case value_t::array: + return (m_it.array_iterator < other.m_it.array_iterator); - default: - return (m_it.primitive_iterator < other.m_it.primitive_iterator); - } - } + default: + return (m_it.primitive_iterator < other.m_it.primitive_iterator); + } + } - /*! + /*! @brief comparison: less than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator<=(const iter_impl& other) const - { - return !other.operator < (*this); - } + bool operator<=(const iter_impl &other) const { + return !other.operator<(*this); + } - /*! + /*! @brief comparison: greater than @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator>(const iter_impl& other) const - { - return !operator<=(other); - } + bool operator>(const iter_impl &other) const { + return !operator<=(other); + } - /*! + /*! @brief comparison: greater than or equal @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - bool operator>=(const iter_impl& other) const - { - return !operator<(other); - } + bool operator>=(const iter_impl &other) const { + return !operator<(other); + } - /*! + /*! @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl& operator+=(difference_type i) - { - JSON_ASSERT(m_object != nullptr); + iter_impl &operator+=(difference_type i) { + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + switch (m_object->m_type) { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); - case value_t::array: - { - std::advance(m_it.array_iterator, i); - break; + case value_t::array: { + std::advance(m_it.array_iterator, i); + break; + } + + default: { + m_it.primitive_iterator += i; + break; + } + } + + return *this; } - default: - { - m_it.primitive_iterator += i; - break; - } - } - - return *this; - } - - /*! + /*! @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl& operator-=(difference_type i) - { - return operator+=(-i); - } + iter_impl &operator-=(difference_type i) { + return operator+=(-i); + } - /*! + /*! @brief add to iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl operator+(difference_type i) const - { - auto result = *this; - result += i; - return result; - } + iter_impl operator+(difference_type i) const { + auto result = *this; + result += i; + return result; + } - /*! + /*! @brief addition of distance and iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - friend iter_impl operator+(difference_type i, const iter_impl& it) - { - auto result = it; - result += i; - return result; - } + friend iter_impl operator+(difference_type i, const iter_impl &it) { + auto result = it; + result += i; + return result; + } - /*! + /*! @brief subtract from iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl operator-(difference_type i) const - { - auto result = *this; - result -= i; - return result; - } + iter_impl operator-(difference_type i) const { + auto result = *this; + result -= i; + return result; + } - /*! + /*! @brief return difference @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - difference_type operator-(const iter_impl& other) const - { - JSON_ASSERT(m_object != nullptr); + difference_type operator-(const iter_impl &other) const { + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + switch (m_object->m_type) { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); - case value_t::array: - return m_it.array_iterator - other.m_it.array_iterator; + case value_t::array: + return m_it.array_iterator - other.m_it.array_iterator; - default: - return m_it.primitive_iterator - other.m_it.primitive_iterator; - } - } + default: + return m_it.primitive_iterator - other.m_it.primitive_iterator; + } + } - /*! + /*! @brief access to successor @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - reference operator[](difference_type n) const - { - JSON_ASSERT(m_object != nullptr); + reference operator[](difference_type n) const { + JSON_ASSERT(m_object != nullptr); - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); + switch (m_object->m_type) { + case value_t::object: + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); - case value_t::array: - return *std::next(m_it.array_iterator, n); + case value_t::array: + return *std::next(m_it.array_iterator, n); - case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value")); + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value")); - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) - { - return *m_object; + default: { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); } - } - } - /*! + /*! @brief return the key of an object iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - const typename object_t::key_type& key() const - { - JSON_ASSERT(m_object != nullptr); + const typename object_t::key_type &key() const { + JSON_ASSERT(m_object != nullptr); - if (JSON_HEDLEY_LIKELY(m_object->is_object())) - { - return m_it.object_iterator->first; - } + if (JSON_HEDLEY_LIKELY(m_object->is_object())) { + return m_it.object_iterator->first; + } - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); - } + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); + } - /*! + /*! @brief return the value of an iterator @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - reference value() const - { - return operator*(); - } + reference value() const { + return operator*(); + } - private: - /// associated JSON instance - pointer m_object = nullptr; - /// the actual iterator of the associated instance - internal_iterator::type> m_it {}; -}; -} // namespace detail + private: + /// associated JSON instance + pointer m_object = nullptr; + /// the actual iterator of the associated instance + internal_iterator::type> m_it{}; + }; + } // namespace detail } // namespace nlohmann // #include @@ -11414,10 +10591,8 @@ class iter_impl #include // reverse_iterator #include // declval -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { ////////////////////// // reverse_iterator // ////////////////////// @@ -11440,92 +10615,80 @@ create @ref const_reverse_iterator). @since version 1.0.0 */ -template -class json_reverse_iterator : public std::reverse_iterator -{ - public: - using difference_type = std::ptrdiff_t; - /// shortcut to the reverse iterator adapter - using base_iterator = std::reverse_iterator; - /// the reference type for the pointed-to element - using reference = typename Base::reference; + template + class json_reverse_iterator : public std::reverse_iterator { + public: + using difference_type = std::ptrdiff_t; + /// shortcut to the reverse iterator adapter + using base_iterator = std::reverse_iterator; + /// the reference type for the pointed-to element + using reference = typename Base::reference; - /// create reverse iterator from iterator - explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept - : base_iterator(it) {} + /// create reverse iterator from iterator + explicit json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept + : base_iterator(it) {} - /// create reverse iterator from base class - explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} + /// create reverse iterator from base class + explicit json_reverse_iterator(const base_iterator &it) noexcept: base_iterator(it) {} - /// post-increment (it++) - json_reverse_iterator const operator++(int) - { - return static_cast(base_iterator::operator++(1)); - } + /// post-increment (it++) + json_reverse_iterator const operator++(int) { + return static_cast(base_iterator::operator++(1)); + } - /// pre-increment (++it) - json_reverse_iterator& operator++() - { - return static_cast(base_iterator::operator++()); - } + /// pre-increment (++it) + json_reverse_iterator &operator++() { + return static_cast(base_iterator::operator++()); + } - /// post-decrement (it--) - json_reverse_iterator const operator--(int) - { - return static_cast(base_iterator::operator--(1)); - } + /// post-decrement (it--) + json_reverse_iterator const operator--(int) { + return static_cast(base_iterator::operator--(1)); + } - /// pre-decrement (--it) - json_reverse_iterator& operator--() - { - return static_cast(base_iterator::operator--()); - } + /// pre-decrement (--it) + json_reverse_iterator &operator--() { + return static_cast(base_iterator::operator--()); + } - /// add to iterator - json_reverse_iterator& operator+=(difference_type i) - { - return static_cast(base_iterator::operator+=(i)); - } + /// add to iterator + json_reverse_iterator &operator+=(difference_type i) { + return static_cast(base_iterator::operator+=(i)); + } - /// add to iterator - json_reverse_iterator operator+(difference_type i) const - { - return static_cast(base_iterator::operator+(i)); - } + /// add to iterator + json_reverse_iterator operator+(difference_type i) const { + return static_cast(base_iterator::operator+(i)); + } - /// subtract from iterator - json_reverse_iterator operator-(difference_type i) const - { - return static_cast(base_iterator::operator-(i)); - } + /// subtract from iterator + json_reverse_iterator operator-(difference_type i) const { + return static_cast(base_iterator::operator-(i)); + } - /// return difference - difference_type operator-(const json_reverse_iterator& other) const - { - return base_iterator(*this) - base_iterator(other); - } + /// return difference + difference_type operator-(const json_reverse_iterator &other) const { + return base_iterator(*this) - base_iterator(other); + } - /// access to successor - reference operator[](difference_type n) const - { - return *(this->operator+(n)); - } + /// access to successor + reference operator[](difference_type n) const { + return *(this->operator+(n)); + } - /// return the key of an object iterator - auto key() const -> decltype(std::declval().key()) - { - auto it = --this->base(); - return it.key(); - } + /// return the key of an object iterator + auto key() const -> decltype(std::declval().key()) { + auto it = --this->base(); + return it.key(); + } - /// return the value of an iterator - reference value() const - { - auto it = --this->base(); - return it.operator * (); - } -}; -} // namespace detail + /// return the value of an iterator + reference value() const { + auto it = --this->base(); + return it.operator*(); + } + }; + } // namespace detail } // namespace nlohmann // #include @@ -11548,17 +10711,16 @@ class json_reverse_iterator : public std::reverse_iterator // #include -namespace nlohmann -{ -template -class json_pointer -{ - // allow basic_json to access private members - NLOHMANN_BASIC_JSON_TPL_DECLARATION - friend class basic_json; +namespace nlohmann { + template + class json_pointer { + // allow basic_json to access private members + NLOHMANN_BASIC_JSON_TPL_DECLARATION + friend + class basic_json; - public: - /*! + public: + /*! @brief create JSON pointer Create a JSON pointer according to the syntax described in @@ -11579,11 +10741,10 @@ class json_pointer @since version 2.0.0 */ - explicit json_pointer(const std::string& s = "") - : reference_tokens(split(s)) - {} + explicit json_pointer(const std::string &s = "") + : reference_tokens(split(s)) {} - /*! + /*! @brief return a string representation of the JSON pointer @invariant For each JSON pointer `ptr`, it holds: @@ -11597,23 +10758,20 @@ class json_pointer @since version 2.0.0 */ - std::string to_string() const - { - return std::accumulate(reference_tokens.begin(), reference_tokens.end(), - std::string{}, - [](const std::string & a, const std::string & b) - { - return a + "/" + escape(b); - }); - } + std::string to_string() const { + return std::accumulate(reference_tokens.begin(), reference_tokens.end(), + std::string{}, + [](const std::string &a, const std::string &b) { + return a + "/" + escape(b); + }); + } - /// @copydoc to_string() - operator std::string() const - { - return to_string(); - } + /// @copydoc to_string() + operator std::string() const { + return to_string(); + } - /*! + /*! @brief append another JSON pointer at the end of this JSON pointer @param[in] ptr JSON pointer to append @@ -11629,15 +10787,14 @@ class json_pointer @since version 3.6.0 */ - json_pointer& operator/=(const json_pointer& ptr) - { - reference_tokens.insert(reference_tokens.end(), - ptr.reference_tokens.begin(), - ptr.reference_tokens.end()); - return *this; - } + json_pointer &operator/=(const json_pointer &ptr) { + reference_tokens.insert(reference_tokens.end(), + ptr.reference_tokens.begin(), + ptr.reference_tokens.end()); + return *this; + } - /*! + /*! @brief append an unescaped reference token at the end of this JSON pointer @param[in] token reference token to append @@ -11653,13 +10810,12 @@ class json_pointer @since version 3.6.0 */ - json_pointer& operator/=(std::string token) - { - push_back(std::move(token)); - return *this; - } + json_pointer &operator/=(std::string token) { + push_back(std::move(token)); + return *this; + } - /*! + /*! @brief append an array index at the end of this JSON pointer @param[in] array_idx array index to append @@ -11675,12 +10831,11 @@ class json_pointer @since version 3.6.0 */ - json_pointer& operator/=(std::size_t array_idx) - { - return *this /= std::to_string(array_idx); - } + json_pointer &operator/=(std::size_t array_idx) { + return *this /= std::to_string(array_idx); + } - /*! + /*! @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer @param[in] lhs JSON pointer @@ -11695,13 +10850,12 @@ class json_pointer @since version 3.6.0 */ - friend json_pointer operator/(const json_pointer& lhs, - const json_pointer& rhs) - { - return json_pointer(lhs) /= rhs; - } + friend json_pointer operator/(const json_pointer &lhs, + const json_pointer &rhs) { + return json_pointer(lhs) /= rhs; + } - /*! + /*! @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer @param[in] ptr JSON pointer @@ -11716,12 +10870,11 @@ class json_pointer @since version 3.6.0 */ - friend json_pointer operator/(const json_pointer& ptr, std::string token) - { - return json_pointer(ptr) /= std::move(token); - } + friend json_pointer operator/(const json_pointer &ptr, std::string token) { + return json_pointer(ptr) /= std::move(token); + } - /*! + /*! @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer @param[in] ptr JSON pointer @@ -11736,12 +10889,11 @@ class json_pointer @since version 3.6.0 */ - friend json_pointer operator/(const json_pointer& ptr, std::size_t array_idx) - { - return json_pointer(ptr) /= array_idx; - } + friend json_pointer operator/(const json_pointer &ptr, std::size_t array_idx) { + return json_pointer(ptr) /= array_idx; + } - /*! + /*! @brief returns the parent of this JSON pointer @return parent of this JSON pointer; in case this JSON pointer is the root, @@ -11754,19 +10906,17 @@ class json_pointer @since version 3.6.0 */ - json_pointer parent_pointer() const - { - if (empty()) - { - return *this; + json_pointer parent_pointer() const { + if (empty()) { + return *this; + } + + json_pointer res = *this; + res.pop_back(); + return res; } - json_pointer res = *this; - res.pop_back(); - return res; - } - - /*! + /*! @brief remove last reference token @pre not `empty()` @@ -11779,17 +10929,15 @@ class json_pointer @since version 3.6.0 */ - void pop_back() - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + void pop_back() { + if (JSON_HEDLEY_UNLIKELY(empty())) { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + reference_tokens.pop_back(); } - reference_tokens.pop_back(); - } - - /*! + /*! @brief return last reference token @pre not `empty()` @@ -11803,17 +10951,15 @@ class json_pointer @since version 3.6.0 */ - const std::string& back() const - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + const std::string &back() const { + if (JSON_HEDLEY_UNLIKELY(empty())) { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + return reference_tokens.back(); } - return reference_tokens.back(); - } - - /*! + /*! @brief append an unescaped token at the end of the reference pointer @param[in] token token to add @@ -11825,18 +10971,16 @@ class json_pointer @since version 3.6.0 */ - void push_back(const std::string& token) - { - reference_tokens.push_back(token); - } + void push_back(const std::string &token) { + reference_tokens.push_back(token); + } - /// @copydoc push_back(const std::string&) - void push_back(std::string&& token) - { - reference_tokens.push_back(std::move(token)); - } + /// @copydoc push_back(const std::string&) + void push_back(std::string &&token) { + reference_tokens.push_back(std::move(token)); + } - /*! + /*! @brief return whether pointer points to the root document @return true iff the JSON pointer points to the root document @@ -11850,13 +10994,12 @@ class json_pointer @since version 3.6.0 */ - bool empty() const noexcept - { - return reference_tokens.empty(); - } + bool empty() const noexcept { + return reference_tokens.empty(); + } - private: - /*! + private: + /*! @param[in] s reference token to be converted into an array index @return integer representation of @a s @@ -11866,64 +11009,55 @@ class json_pointer @throw out_of_range.404 if string @a s could not be converted to an integer @throw out_of_range.410 if an array index exceeds size_type */ - static typename BasicJsonType::size_type array_index(const std::string& s) - { - using size_type = typename BasicJsonType::size_type; + static typename BasicJsonType::size_type array_index(const std::string &s) { + using size_type = typename BasicJsonType::size_type; - // error condition (cf. RFC 6901, Sect. 4) - if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) - { - JSON_THROW(detail::parse_error::create(106, 0, - "array index '" + s + - "' must not begin with '0'")); + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + s + + "' must not begin with '0'")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number")); + } + + std::size_t processed_chars = 0; + unsigned long long res = 0; + JSON_TRY { + res = std::stoull(s, &processed_chars); + } + JSON_CATCH(std::out_of_range &) { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); + } + + // check if the string was completely read + if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); + } + + // only triggered on special platforms (like 32bit), see also + // https://github.com/nlohmann/json/pull/2203 + if (res >= static_cast((std::numeric_limits::max)())) { + JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE + } + + return static_cast(res); } - // error condition (cf. RFC 6901, Sect. 4) - if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) - { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number")); + json_pointer top() const { + if (JSON_HEDLEY_UNLIKELY(empty())) { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + json_pointer result = *this; + result.reference_tokens = {reference_tokens[0]}; + return result; } - std::size_t processed_chars = 0; - unsigned long long res = 0; - JSON_TRY - { - res = std::stoull(s, &processed_chars); - } - JSON_CATCH(std::out_of_range&) - { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); - } - - // check if the string was completely read - if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) - { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); - } - - // only triggered on special platforms (like 32bit), see also - // https://github.com/nlohmann/json/pull/2203 - if (res >= static_cast((std::numeric_limits::max)())) - { - JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE - } - - return static_cast(res); - } - - json_pointer top() const - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); - } - - json_pointer result = *this; - result.reference_tokens = {reference_tokens[0]}; - return result; - } - - /*! + /*! @brief create and return a reference to the pointed to value @complexity Linear in the number of reference tokens. @@ -11931,60 +11065,51 @@ class json_pointer @throw parse_error.109 if array index is not a number @throw type_error.313 if value cannot be unflattened */ - BasicJsonType& get_and_create(BasicJsonType& j) const - { - auto result = &j; + BasicJsonType &get_and_create(BasicJsonType &j) const { + auto result = &j; - // in case no reference tokens exist, return a reference to the JSON value - // j which will be overwritten by a primitive value - for (const auto& reference_token : reference_tokens) - { - switch (result->type()) - { - case detail::value_t::null: - { - if (reference_token == "0") - { - // start a new array if reference token is 0 - result = &result->operator[](0); + // in case no reference tokens exist, return a reference to the JSON value + // j which will be overwritten by a primitive value + for (const auto &reference_token: reference_tokens) { + switch (result->type()) { + case detail::value_t::null: { + if (reference_token == "0") { + // start a new array if reference token is 0 + result = &result->operator[](0); + } else { + // start a new object otherwise + result = &result->operator[](reference_token); + } + break; } - else - { - // start a new object otherwise + + case detail::value_t::object: { + // create an entry in the object result = &result->operator[](reference_token); + break; } - break; - } - case detail::value_t::object: - { - // create an entry in the object - result = &result->operator[](reference_token); - break; - } + case detail::value_t::array: { + // create an entry in the array + result = &result->operator[](array_index(reference_token)); + break; + } - case detail::value_t::array: - { - // create an entry in the array - result = &result->operator[](array_index(reference_token)); - break; - } - - /* + /* The following code is only reached if there exists a reference token _and_ the current value is primitive. In this case, we have an error situation, because primitive values may only occur as single value; that is, with an empty list of reference tokens. */ - default: - JSON_THROW(detail::type_error::create(313, "invalid value to unflatten")); + default: + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten")); + } } + + return *result; } - return *result; - } - - /*! + /*! @brief return a reference to the pointed to value @note This version does not throw if a value is not present, but tries to @@ -12003,102 +11128,86 @@ class json_pointer @throw parse_error.109 if an array index was not a number @throw out_of_range.404 if the JSON pointer can not be resolved */ - BasicJsonType& get_unchecked(BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - // convert null values to arrays or objects before continuing - if (ptr->is_null()) - { - // check if reference token is a number - const bool nums = - std::all_of(reference_token.begin(), reference_token.end(), - [](const unsigned char x) - { - return std::isdigit(x); - }); + BasicJsonType &get_unchecked(BasicJsonType *ptr) const { + for (const auto &reference_token: reference_tokens) { + // convert null values to arrays or objects before continuing + if (ptr->is_null()) { + // check if reference token is a number + const bool nums = + std::all_of(reference_token.begin(), reference_token.end(), + [](const unsigned char x) { + return std::isdigit(x); + }); - // change value to array for numbers or "-" or to object otherwise - *ptr = (nums || reference_token == "-") - ? detail::value_t::array - : detail::value_t::object; - } - - switch (ptr->type()) - { - case detail::value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; + // change value to array for numbers or "-" or to object otherwise + *ptr = (nums || reference_token == "-") + ? detail::value_t::array + : detail::value_t::object; } - case detail::value_t::array: - { - if (reference_token == "-") - { - // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_value.array->size()); + switch (ptr->type()) { + case detail::value_t::object: { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; } - else - { - // convert array index to number; unchecked access - ptr = &ptr->operator[](array_index(reference_token)); - } - break; - } - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + case detail::value_t::array: { + if (reference_token == "-") { + // explicitly treat "-" as index beyond the end + ptr = &ptr->operator[](ptr->m_value.array->size()); + } else { + // convert array index to number; unchecked access + ptr = &ptr->operator[](array_index(reference_token)); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } } + + return *ptr; } - return *ptr; - } - - /*! + /*! @throw parse_error.106 if an array index begins with '0' @throw parse_error.109 if an array index was not a number @throw out_of_range.402 if the array index '-' is used @throw out_of_range.404 if the JSON pointer can not be resolved */ - BasicJsonType& get_checked(BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); + BasicJsonType &get_checked(BasicJsonType *ptr) const { + for (const auto &reference_token: reference_tokens) { + switch (ptr->type()) { + case detail::value_t::object: { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; } - // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); - break; - } + case detail::value_t::array: { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } } + + return *ptr; } - return *ptr; - } - - /*! + /*! @brief return a const reference to the pointed to value @param[in] ptr a JSON value @@ -12111,160 +11220,134 @@ class json_pointer @throw out_of_range.402 if the array index '-' is used @throw out_of_range.404 if the JSON pointer can not be resolved */ - const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" cannot be used for const access - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); + const BasicJsonType &get_unchecked(const BasicJsonType *ptr) const { + for (const auto &reference_token: reference_tokens) { + switch (ptr->type()) { + case detail::value_t::object: { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; } - // use unchecked array access - ptr = &ptr->operator[](array_index(reference_token)); - break; - } + case detail::value_t::array: { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { + // "-" cannot be used for const access + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + // use unchecked array access + ptr = &ptr->operator[](array_index(reference_token)); + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } } + + return *ptr; } - return *ptr; - } - - /*! + /*! @throw parse_error.106 if an array index begins with '0' @throw parse_error.109 if an array index was not a number @throw out_of_range.402 if the array index '-' is used @throw out_of_range.404 if the JSON pointer can not be resolved */ - const BasicJsonType& get_checked(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); + const BasicJsonType &get_checked(const BasicJsonType *ptr) const { + for (const auto &reference_token: reference_tokens) { + switch (ptr->type()) { + case detail::value_t::object: { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; } - // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); - break; - } + case detail::value_t::array: { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + // note: at performs range check + ptr = &ptr->at(array_index(reference_token)); + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } } + + return *ptr; } - return *ptr; - } - - /*! + /*! @throw parse_error.106 if an array index begins with '0' @throw parse_error.109 if an array index was not a number */ - bool contains(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - if (!ptr->contains(reference_token)) - { - // we did not find the key in the object - return false; - } - - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - return false; - } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) - { - // invalid char - return false; - } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) - { - if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) - { - // first char should be between '1' and '9' + bool contains(const BasicJsonType *ptr) const { + for (const auto &reference_token: reference_tokens) { + switch (ptr->type()) { + case detail::value_t::object: { + if (!ptr->contains(reference_token)) { + // we did not find the key in the object return false; } - for (std::size_t i = 1; i < reference_token.size(); i++) - { - if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) - { - // other char should be between '0' and '9' + + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { + // "-" always fails the range check + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) { + // invalid char + return false; + } + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) { + if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) { + // first char should be between '1' and '9' return false; } + for (std::size_t i = 1; i < reference_token.size(); i++) { + if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) { + // other char should be between '0' and '9' + return false; + } + } } + + const auto idx = array_index(reference_token); + if (idx >= ptr->size()) { + // index out of range + return false; + } + + ptr = &ptr->operator[](idx); + break; } - const auto idx = array_index(reference_token); - if (idx >= ptr->size()) - { - // index out of range + default: { + // we do not expect primitive values if there is still a + // reference token to process return false; } - - ptr = &ptr->operator[](idx); - break; - } - - default: - { - // we do not expect primitive values if there is still a - // reference token to process - return false; } } + + // no reference token left means we found a primitive value + return true; } - // no reference token left means we found a primitive value - return true; - } - - /*! + /*! @brief split the string input to reference tokens @note This function is only called by the json_pointer constructor. @@ -12273,69 +11356,63 @@ class json_pointer @throw parse_error.107 if the pointer is not empty or begins with '/' @throw parse_error.108 if character '~' is not followed by '0' or '1' */ - static std::vector split(const std::string& reference_string) - { - std::vector result; + static std::vector split(const std::string &reference_string) { + std::vector result; + + // special case: empty reference string -> no reference tokens + if (reference_string.empty()) { + return result; + } + + // check if nonempty reference string begins with slash + if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) { + JSON_THROW(detail::parse_error::create(107, 1, + "JSON pointer must be empty or begin with '/' - was: '" + + reference_string + "'")); + } + + // extract the reference tokens: + // - slash: position of the last read slash (or end of string) + // - start: position after the previous slash + for ( + // search for the first slash after the first character + std::size_t slash = reference_string.find_first_of('/', 1), + // set the beginning of the first reference token + start = 1; + // we can stop if start == 0 (if slash == std::string::npos) + start != 0; + // set the beginning of the next reference token + // (will eventually be 0 if slash == std::string::npos) + start = (slash == std::string::npos) ? 0 : slash + 1, + // find next slash + slash = reference_string.find_first_of('/', start)) { + // use the text between the beginning of the reference token + // (start) and the last slash (slash). + auto reference_token = reference_string.substr(start, slash - start); + + // check reference tokens are properly escaped + for (std::size_t pos = reference_token.find_first_of('~'); + pos != std::string::npos; + pos = reference_token.find_first_of('~', pos + 1)) { + JSON_ASSERT(reference_token[pos] == '~'); + + // ~ must be followed by 0 or 1 + if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || + (reference_token[pos + 1] != '0' && + reference_token[pos + 1] != '1'))) { + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); + } + } + + // finally, store the reference token + unescape(reference_token); + result.push_back(reference_token); + } - // special case: empty reference string -> no reference tokens - if (reference_string.empty()) - { return result; } - // check if nonempty reference string begins with slash - if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) - { - JSON_THROW(detail::parse_error::create(107, 1, - "JSON pointer must be empty or begin with '/' - was: '" + - reference_string + "'")); - } - - // extract the reference tokens: - // - slash: position of the last read slash (or end of string) - // - start: position after the previous slash - for ( - // search for the first slash after the first character - std::size_t slash = reference_string.find_first_of('/', 1), - // set the beginning of the first reference token - start = 1; - // we can stop if start == 0 (if slash == std::string::npos) - start != 0; - // set the beginning of the next reference token - // (will eventually be 0 if slash == std::string::npos) - start = (slash == std::string::npos) ? 0 : slash + 1, - // find next slash - slash = reference_string.find_first_of('/', start)) - { - // use the text between the beginning of the reference token - // (start) and the last slash (slash). - auto reference_token = reference_string.substr(start, slash - start); - - // check reference tokens are properly escaped - for (std::size_t pos = reference_token.find_first_of('~'); - pos != std::string::npos; - pos = reference_token.find_first_of('~', pos + 1)) - { - JSON_ASSERT(reference_token[pos] == '~'); - - // ~ must be followed by 0 or 1 - if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || - (reference_token[pos + 1] != '0' && - reference_token[pos + 1] != '1'))) - { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); - } - } - - // finally, store the reference token - unescape(reference_token); - result.push_back(reference_token); - } - - return result; - } - - /*! + /*! @brief replace all occurrences of a substring by another string @param[in,out] s the string to manipulate; changed so that all @@ -12348,92 +11425,76 @@ class json_pointer @since version 2.0.0 */ - static void replace_substring(std::string& s, const std::string& f, - const std::string& t) - { - JSON_ASSERT(!f.empty()); - for (auto pos = s.find(f); // find first occurrence of f - pos != std::string::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find next occurrence of f - {} - } + static void replace_substring(std::string &s, const std::string &f, + const std::string &t) { + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != std::string::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} + } - /// escape "~" to "~0" and "/" to "~1" - static std::string escape(std::string s) - { - replace_substring(s, "~", "~0"); - replace_substring(s, "/", "~1"); - return s; - } + /// escape "~" to "~0" and "/" to "~1" + static std::string escape(std::string s) { + replace_substring(s, "~", "~0"); + replace_substring(s, "/", "~1"); + return s; + } - /// unescape "~1" to tilde and "~0" to slash (order is important!) - static void unescape(std::string& s) - { - replace_substring(s, "~1", "/"); - replace_substring(s, "~0", "~"); - } + /// unescape "~1" to tilde and "~0" to slash (order is important!) + static void unescape(std::string &s) { + replace_substring(s, "~1", "/"); + replace_substring(s, "~0", "~"); + } - /*! + /*! @param[in] reference_string the reference string to the current value @param[in] value the value to consider @param[in,out] result the result object to insert values to @note Empty objects or arrays are flattened to `null`. */ - static void flatten(const std::string& reference_string, - const BasicJsonType& value, - BasicJsonType& result) - { - switch (value.type()) - { - case detail::value_t::array: - { - if (value.m_value.array->empty()) - { - // flatten empty array as null - result[reference_string] = nullptr; - } - else - { - // iterate array and use index as reference string - for (std::size_t i = 0; i < value.m_value.array->size(); ++i) - { - flatten(reference_string + "/" + std::to_string(i), - value.m_value.array->operator[](i), result); + static void flatten(const std::string &reference_string, + const BasicJsonType &value, + BasicJsonType &result) { + switch (value.type()) { + case detail::value_t::array: { + if (value.m_value.array->empty()) { + // flatten empty array as null + result[reference_string] = nullptr; + } else { + // iterate array and use index as reference string + for (std::size_t i = 0; i < value.m_value.array->size(); ++i) { + flatten(reference_string + "/" + std::to_string(i), + value.m_value.array->operator[](i), result); + } } + break; } - break; - } - case detail::value_t::object: - { - if (value.m_value.object->empty()) - { - // flatten empty object as null - result[reference_string] = nullptr; - } - else - { - // iterate object and use keys as reference string - for (const auto& element : *value.m_value.object) - { - flatten(reference_string + "/" + escape(element.first), element.second, result); + case detail::value_t::object: { + if (value.m_value.object->empty()) { + // flatten empty object as null + result[reference_string] = nullptr; + } else { + // iterate object and use keys as reference string + for (const auto &element: *value.m_value.object) { + flatten(reference_string + "/" + escape(element.first), element.second, result); + } } + break; } - break; - } - default: - { - // add primitive value with its reference string - result[reference_string] = value; - break; + default: { + // add primitive value with its reference string + result[reference_string] = value; + break; + } } } - } - /*! + /*! @param[in] value flattened JSON @return unflattened JSON @@ -12443,35 +11504,31 @@ class json_pointer @throw type_error.315 if object values are not primitive @throw type_error.313 if value cannot be unflattened */ - static BasicJsonType - unflatten(const BasicJsonType& value) - { - if (JSON_HEDLEY_UNLIKELY(!value.is_object())) - { - JSON_THROW(detail::type_error::create(314, "only objects can be unflattened")); - } - - BasicJsonType result; - - // iterate the JSON object values - for (const auto& element : *value.m_value.object) - { - if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) - { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive")); + static BasicJsonType + unflatten(const BasicJsonType &value) { + if (JSON_HEDLEY_UNLIKELY(!value.is_object())) { + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened")); } - // assign value to reference pointed to by JSON pointer; Note that if - // the JSON pointer is "" (i.e., points to the whole value), function - // get_and_create returns a reference to result itself. An assignment - // will then create a primitive value. - json_pointer(element.first).get_and_create(result) = element.second; + BasicJsonType result; + + // iterate the JSON object values + for (const auto &element: *value.m_value.object) { + if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { + JSON_THROW(detail::type_error::create(315, "values in object must be primitive")); + } + + // assign value to reference pointed to by JSON pointer; Note that if + // the JSON pointer is "" (i.e., points to the whole value), function + // get_and_create returns a reference to result itself. An assignment + // will then create a primitive value. + json_pointer(element.first).get_and_create(result) = element.second; + } + + return result; } - return result; - } - - /*! + /*! @brief compares two JSON pointers for equality @param[in] lhs JSON pointer to compare @@ -12482,13 +11539,12 @@ class json_pointer @exceptionsafety No-throw guarantee: this function never throws exceptions. */ - friend bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return lhs.reference_tokens == rhs.reference_tokens; - } + friend bool operator==(json_pointer const &lhs, + json_pointer const &rhs) noexcept { + return lhs.reference_tokens == rhs.reference_tokens; + } - /*! + /*! @brief compares two JSON pointers for inequality @param[in] lhs JSON pointer to compare @@ -12499,15 +11555,14 @@ class json_pointer @exceptionsafety No-throw guarantee: this function never throws exceptions. */ - friend bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return !(lhs == rhs); - } + friend bool operator!=(json_pointer const &lhs, + json_pointer const &rhs) noexcept { + return !(lhs == rhs); + } - /// the reference tokens - std::vector reference_tokens; -}; + /// the reference tokens + std::vector reference_tokens; + }; } // namespace nlohmann // #include @@ -12519,74 +11574,60 @@ class json_pointer // #include -namespace nlohmann -{ -namespace detail -{ -template -class json_ref -{ - public: - using value_type = BasicJsonType; +namespace nlohmann { + namespace detail { + template + class json_ref { + public: + using value_type = BasicJsonType; - json_ref(value_type&& value) - : owned_value(std::move(value)) - , value_ref(&owned_value) - , is_rvalue(true) - {} + json_ref(value_type &&value) + : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true) {} - json_ref(const value_type& value) - : value_ref(const_cast(&value)) - , is_rvalue(false) - {} + json_ref(const value_type &value) + : value_ref(const_cast(&value)), is_rvalue(false) {} - json_ref(std::initializer_list init) - : owned_value(init) - , value_ref(&owned_value) - , is_rvalue(true) - {} + json_ref(std::initializer_list init) + : owned_value(init), value_ref(&owned_value), is_rvalue(true) {} - template < - class... Args, - enable_if_t::value, int> = 0 > - json_ref(Args && ... args) - : owned_value(std::forward(args)...) - , value_ref(&owned_value) - , is_rvalue(true) - {} + template< + class... Args, + enable_if_t::value, int> = 0> + json_ref(Args &&... args) + : owned_value(std::forward(args)...), value_ref(&owned_value), is_rvalue(true) {} - // class should be movable only - json_ref(json_ref&&) = default; - json_ref(const json_ref&) = delete; - json_ref& operator=(const json_ref&) = delete; - json_ref& operator=(json_ref&&) = delete; - ~json_ref() = default; + // class should be movable only + json_ref(json_ref &&) = default; - value_type moved_or_copied() const - { - if (is_rvalue) - { - return std::move(*value_ref); - } - return *value_ref; - } + json_ref(const json_ref &) = delete; - value_type const& operator*() const - { - return *static_cast(value_ref); - } + json_ref &operator=(const json_ref &) = delete; - value_type const* operator->() const - { - return static_cast(value_ref); - } + json_ref &operator=(json_ref &&) = delete; - private: - mutable value_type owned_value = nullptr; - value_type* value_ref = nullptr; - const bool is_rvalue = true; -}; -} // namespace detail + ~json_ref() = default; + + value_type moved_or_copied() const { + if (is_rvalue) { + return std::move(*value_ref); + } + return *value_ref; + } + + value_type const &operator*() const { + return *static_cast(value_ref); + } + + value_type const *operator->() const { + return static_cast(value_ref); + } + + private: + mutable value_type owned_value = nullptr; + value_type *value_ref = nullptr; + const bool is_rvalue = true; + }; + } // namespace detail } // namespace nlohmann // #include @@ -12624,123 +11665,107 @@ class json_ref // #include -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /// abstract output adapter interface -template struct output_adapter_protocol -{ - virtual void write_character(CharType c) = 0; - virtual void write_characters(const CharType* s, std::size_t length) = 0; - virtual ~output_adapter_protocol() = default; -}; + template + struct output_adapter_protocol { + virtual void write_character(CharType c) = 0; + + virtual void write_characters(const CharType *s, std::size_t length) = 0; + + virtual ~output_adapter_protocol() = default; + }; /// a type to simplify interfaces -template -using output_adapter_t = std::shared_ptr>; + template + using output_adapter_t = std::shared_ptr>; /// output adapter for byte vectors -template -class output_vector_adapter : public output_adapter_protocol -{ - public: - explicit output_vector_adapter(std::vector& vec) noexcept - : v(vec) - {} + template + class output_vector_adapter : public output_adapter_protocol { + public: + explicit output_vector_adapter(std::vector &vec) noexcept + : v(vec) {} - void write_character(CharType c) override - { - v.push_back(c); - } + void write_character(CharType c) override { + v.push_back(c); + } - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - std::copy(s, s + length, std::back_inserter(v)); - } + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType *s, std::size_t length) override { + std::copy(s, s + length, std::back_inserter(v)); + } - private: - std::vector& v; -}; + private: + std::vector &v; + }; /// output adapter for output streams -template -class output_stream_adapter : public output_adapter_protocol -{ - public: - explicit output_stream_adapter(std::basic_ostream& s) noexcept - : stream(s) - {} + template + class output_stream_adapter : public output_adapter_protocol { + public: + explicit output_stream_adapter(std::basic_ostream &s) noexcept + : stream(s) {} - void write_character(CharType c) override - { - stream.put(c); - } + void write_character(CharType c) override { + stream.put(c); + } - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - stream.write(s, static_cast(length)); - } + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType *s, std::size_t length) override { + stream.write(s, static_cast(length)); + } - private: - std::basic_ostream& stream; -}; + private: + std::basic_ostream &stream; + }; /// output adapter for basic_string -template> -class output_string_adapter : public output_adapter_protocol -{ - public: - explicit output_string_adapter(StringType& s) noexcept - : str(s) - {} + template> + class output_string_adapter : public output_adapter_protocol { + public: + explicit output_string_adapter(StringType &s) noexcept + : str(s) {} - void write_character(CharType c) override - { - str.push_back(c); - } + void write_character(CharType c) override { + str.push_back(c); + } - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - str.append(s, length); - } + JSON_HEDLEY_NON_NULL(2) + void write_characters(const CharType *s, std::size_t length) override { + str.append(s, length); + } - private: - StringType& str; -}; + private: + StringType &str; + }; -template> -class output_adapter -{ - public: - output_adapter(std::vector& vec) - : oa(std::make_shared>(vec)) {} + template> + class output_adapter { + public: + output_adapter(std::vector &vec) + : oa(std::make_shared>(vec)) {} - output_adapter(std::basic_ostream& s) - : oa(std::make_shared>(s)) {} + output_adapter(std::basic_ostream &s) + : oa(std::make_shared>(s)) {} - output_adapter(StringType& s) - : oa(std::make_shared>(s)) {} + output_adapter(StringType &s) + : oa(std::make_shared>(s)) {} - operator output_adapter_t() - { - return oa; - } + operator output_adapter_t() { + return oa; + } - private: - output_adapter_t oa = nullptr; -}; -} // namespace detail + private: + output_adapter_t oa = nullptr; + }; + } // namespace detail } // namespace nlohmann -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /////////////////// // binary writer // /////////////////// @@ -12748,1479 +11773,1194 @@ namespace detail /*! @brief serialization to CBOR and MessagePack values */ -template -class binary_writer -{ - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using number_float_t = typename BasicJsonType::number_float_t; + template + class binary_writer { + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using number_float_t = typename BasicJsonType::number_float_t; - public: - /*! + public: + /*! @brief create a binary writer @param[in] adapter output adapter to write to */ - explicit binary_writer(output_adapter_t adapter) : oa(adapter) - { - JSON_ASSERT(oa); - } + explicit binary_writer(output_adapter_t adapter) : oa(adapter) { + JSON_ASSERT(oa); + } - /*! + /*! @param[in] j JSON value to serialize @pre j.type() == value_t::object */ - void write_bson(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::object: - { - write_bson_object(*j.m_value.object); - break; + void write_bson(const BasicJsonType &j) { + switch (j.type()) { + case value_t::object: { + write_bson_object(*j.m_value.object); + break; + } + + default: { + JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()))); + } + } } - default: - { - JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()))); - } - } - } - - /*! + /*! @param[in] j JSON value to serialize */ - void write_cbor(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::null: - { - oa->write_character(to_char_type(0xF6)); - break; - } - - case value_t::boolean: - { - oa->write_character(j.m_value.boolean - ? to_char_type(0xF5) - : to_char_type(0xF4)); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // CBOR does not differentiate between positive signed - // integers and unsigned integers. Therefore, we used the - // code from the value_t::number_unsigned case here. - if (j.m_value.number_integer <= 0x17) - { - write_number(static_cast(j.m_value.number_integer)); + void write_cbor(const BasicJsonType &j) { + switch (j.type()) { + case value_t::null: { + oa->write_character(to_char_type(0xF6)); + break; } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_integer)); + + case value_t::boolean: { + oa->write_character(j.m_value.boolean + ? to_char_type(0xF5) + : to_char_type(0xF4)); + break; } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_integer)); + + case value_t::number_integer: { + if (j.m_value.number_integer >= 0) { + // CBOR does not differentiate between positive signed + // integers and unsigned integers. Therefore, we used the + // code from the value_t::number_unsigned case here. + if (j.m_value.number_integer <= 0x17) { + write_number(static_cast(j.m_value.number_integer)); + } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x18)); + write_number(static_cast(j.m_value.number_integer)); + } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x19)); + write_number(static_cast(j.m_value.number_integer)); + } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x1A)); + write_number(static_cast(j.m_value.number_integer)); + } else { + oa->write_character(to_char_type(0x1B)); + write_number(static_cast(j.m_value.number_integer)); + } + } else { + // The conversions below encode the sign in the first + // byte, and the value is converted to a positive number. + const auto positive_number = -1 - j.m_value.number_integer; + if (j.m_value.number_integer >= -24) { + write_number(static_cast(0x20 + positive_number)); + } else if (positive_number <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x38)); + write_number(static_cast(positive_number)); + } else if (positive_number <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x39)); + write_number(static_cast(positive_number)); + } else if (positive_number <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x3A)); + write_number(static_cast(positive_number)); + } else { + oa->write_character(to_char_type(0x3B)); + write_number(static_cast(positive_number)); + } + } + break; } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_integer)); + + case value_t::number_unsigned: { + if (j.m_value.number_unsigned <= 0x17) { + write_number(static_cast(j.m_value.number_unsigned)); + } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x18)); + write_number(static_cast(j.m_value.number_unsigned)); + } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x19)); + write_number(static_cast(j.m_value.number_unsigned)); + } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x1A)); + write_number(static_cast(j.m_value.number_unsigned)); + } else { + oa->write_character(to_char_type(0x1B)); + write_number(static_cast(j.m_value.number_unsigned)); + } + break; } - else - { - oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_integer)); + + case value_t::number_float: { + if (std::isnan(j.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)) { + // 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(to_char_type(0x00)); + } else { + write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); + } + break; } - } - 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) - { - write_number(static_cast(0x20 + positive_number)); + + case value_t::string: { + // step 1: write control byte and the string length + const auto N = j.m_value.string->size(); + if (N <= 0x17) { + write_number(static_cast(0x60 + N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x78)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x79)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x7A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x7B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write the string + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x38)); - write_number(static_cast(positive_number)); + + case value_t::array: { + // step 1: write control byte and the array size + const auto N = j.m_value.array->size(); + if (N <= 0x17) { + write_number(static_cast(0x80 + N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x98)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x99)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x9A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x9B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + for (const auto &el: *j.m_value.array) { + write_cbor(el); + } + break; } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x39)); - write_number(static_cast(positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x3A)); - write_number(static_cast(positive_number)); - } - else - { - oa->write_character(to_char_type(0x3B)); - write_number(static_cast(positive_number)); - } - } - break; - } - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned <= 0x17) - { - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else - { - oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_unsigned)); - } - break; - } - - case value_t::number_float: - { - if (std::isnan(j.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)) - { - // 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(to_char_type(0x00)); - } - else - { - write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); - } - break; - } - - case value_t::string: - { - // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); - if (N <= 0x17) - { - write_number(static_cast(0x60 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x78)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x79)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x7A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x7B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write the string - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.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(); - if (N <= 0x17) - { - write_number(static_cast(0x80 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x98)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x99)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x9A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x9B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - for (const auto& el : *j.m_value.array) - { - write_cbor(el); - } - break; - } - - case value_t::binary: - { - if (j.m_value.binary->has_subtype()) - { - write_number(static_cast(0xd8)); - write_number(j.m_value.binary->subtype()); - } - - // step 1: write control byte and the binary array size - const auto N = j.m_value.binary->size(); - if (N <= 0x17) - { - write_number(static_cast(0x40 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x58)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x59)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x5A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x5B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - N); - - break; - } - - case value_t::object: - { - // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); - if (N <= 0x17) - { - write_number(static_cast(0xA0 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xB8)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xB9)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xBA)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xBB)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - for (const auto& el : *j.m_value.object) - { - write_cbor(el.first); - write_cbor(el.second); - } - break; - } - - default: - break; - } - } - - /*! - @param[in] j JSON value to serialize - */ - void write_msgpack(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::null: // nil - { - oa->write_character(to_char_type(0xC0)); - break; - } - - case value_t::boolean: // true and false - { - oa->write_character(j.m_value.boolean - ? to_char_type(0xC3) - : to_char_type(0xC2)); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we used - // the code from the value_t::number_unsigned case here. - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.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)); - } - else if (j.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)); - } - else if (j.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)); - } - else if (j.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)); - } - } - else - { - if (j.m_value.number_integer >= -32) - { - // negative fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.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)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.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)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.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)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.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)); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.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)); - } - else if (j.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)); - } - else if (j.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)); - } - else if (j.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)); - } - break; - } - - case value_t::number_float: - { - write_compact_float(j.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(); - if (N <= 31) - { - // fixstr - write_number(static_cast(0xA0 | N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 8 - oa->write_character(to_char_type(0xD9)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 16 - oa->write_character(to_char_type(0xDA)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 32 - oa->write_character(to_char_type(0xDB)); - write_number(static_cast(N)); - } - - // step 2: write the string - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.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(); - if (N <= 15) - { - // fixarray - write_number(static_cast(0x90 | N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // array 16 - oa->write_character(to_char_type(0xDC)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // array 32 - oa->write_character(to_char_type(0xDD)); - write_number(static_cast(N)); - } - - // step 2: write each element - for (const auto& el : *j.m_value.array) - { - write_msgpack(el); - } - break; - } - - case value_t::binary: - { - // 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(); - - // step 1: write control byte and the byte string length - const auto N = j.m_value.binary->size(); - if (N <= (std::numeric_limits::max)()) - { - std::uint8_t output_type{}; - bool fixed = true; - if (use_ext) - { - switch (N) - { - case 1: - output_type = 0xD4; // fixext 1 - break; - case 2: - output_type = 0xD5; // fixext 2 - break; - case 4: - output_type = 0xD6; // fixext 4 - break; - case 8: - output_type = 0xD7; // fixext 8 - break; - case 16: - output_type = 0xD8; // fixext 16 - break; - default: - output_type = 0xC7; // ext 8 - fixed = false; - break; + case value_t::binary: { + if (j.m_value.binary->has_subtype()) { + write_number(static_cast(0xd8)); + write_number(j.m_value.binary->subtype()); } - } - else - { - output_type = 0xC4; // bin 8 - fixed = false; + // step 1: write control byte and the binary array size + const auto N = j.m_value.binary->size(); + if (N <= 0x17) { + write_number(static_cast(0x40 + N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x58)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x59)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x5A)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0x5B)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + N); + + break; } - oa->write_character(to_char_type(output_type)); - if (!fixed) - { - write_number(static_cast(N)); + case value_t::object: { + // step 1: write control byte and the object size + const auto N = j.m_value.object->size(); + if (N <= 0x17) { + write_number(static_cast(0xA0 + N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0xB8)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0xB9)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0xBA)); + write_number(static_cast(N)); + } + // LCOV_EXCL_START + else if (N <= (std::numeric_limits::max)()) { + oa->write_character(to_char_type(0xBB)); + write_number(static_cast(N)); + } + // LCOV_EXCL_STOP + + // step 2: write each element + for (const auto &el: *j.m_value.object) { + write_cbor(el.first); + write_cbor(el.second); + } + break; } + + default: + break; } - else if (N <= (std::numeric_limits::max)()) - { - 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 - - oa->write_character(to_char_type(output_type)); - write_number(static_cast(N)); - } - - // step 1.5: if this is an ext type, write the subtype - if (use_ext) - { - write_number(static_cast(j.m_value.binary->subtype())); - } - - // step 2: write the byte string - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - N); - - break; } - case value_t::object: - { - // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); - if (N <= 15) - { - // fixmap - write_number(static_cast(0x80 | (N & 0xF))); - } - else if (N <= (std::numeric_limits::max)()) - { - // map 16 - oa->write_character(to_char_type(0xDE)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // map 32 - oa->write_character(to_char_type(0xDF)); - write_number(static_cast(N)); - } + /*! + @param[in] j JSON value to serialize + */ + void write_msgpack(const BasicJsonType &j) { + switch (j.type()) { + case value_t::null: // nil + { + oa->write_character(to_char_type(0xC0)); + break; + } - // step 2: write each element - for (const auto& el : *j.m_value.object) - { - write_msgpack(el.first); - write_msgpack(el.second); + case value_t::boolean: // true and false + { + oa->write_character(j.m_value.boolean + ? to_char_type(0xC3) + : to_char_type(0xC2)); + break; + } + + case value_t::number_integer: { + if (j.m_value.number_integer >= 0) { + // MessagePack does not differentiate between positive + // signed integers and unsigned integers. Therefore, we used + // the code from the value_t::number_unsigned case here. + if (j.m_value.number_unsigned < 128) { + // positive fixnum + write_number(static_cast(j.m_value.number_integer)); + } else if (j.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)); + } else if (j.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)); + } else if (j.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)); + } else if (j.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)); + } + } else { + if (j.m_value.number_integer >= -32) { + // negative fixnum + write_number(static_cast(j.m_value.number_integer)); + } else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.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)); + } else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.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)); + } else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.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)); + } else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.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)); + } + } + break; + } + + case value_t::number_unsigned: { + if (j.m_value.number_unsigned < 128) { + // positive fixnum + write_number(static_cast(j.m_value.number_integer)); + } else if (j.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)); + } else if (j.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)); + } else if (j.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)); + } else if (j.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)); + } + break; + } + + case value_t::number_float: { + write_compact_float(j.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(); + if (N <= 31) { + // fixstr + write_number(static_cast(0xA0 | N)); + } else if (N <= (std::numeric_limits::max)()) { + // str 8 + oa->write_character(to_char_type(0xD9)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + // str 16 + oa->write_character(to_char_type(0xDA)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + // str 32 + oa->write_character(to_char_type(0xDB)); + write_number(static_cast(N)); + } + + // step 2: write the string + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.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(); + if (N <= 15) { + // fixarray + write_number(static_cast(0x90 | N)); + } else if (N <= (std::numeric_limits::max)()) { + // array 16 + oa->write_character(to_char_type(0xDC)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + // array 32 + oa->write_character(to_char_type(0xDD)); + write_number(static_cast(N)); + } + + // step 2: write each element + for (const auto &el: *j.m_value.array) { + write_msgpack(el); + } + break; + } + + case value_t::binary: { + // 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(); + + // step 1: write control byte and the byte string length + const auto N = j.m_value.binary->size(); + if (N <= (std::numeric_limits::max)()) { + std::uint8_t output_type{}; + bool fixed = true; + if (use_ext) { + switch (N) { + case 1: + output_type = 0xD4; // fixext 1 + break; + case 2: + output_type = 0xD5; // fixext 2 + break; + case 4: + output_type = 0xD6; // fixext 4 + break; + case 8: + output_type = 0xD7; // fixext 8 + break; + case 16: + output_type = 0xD8; // fixext 16 + break; + default: + output_type = 0xC7; // ext 8 + fixed = false; + break; + } + + } else { + output_type = 0xC4; // bin 8 + fixed = false; + } + + oa->write_character(to_char_type(output_type)); + if (!fixed) { + write_number(static_cast(N)); + } + } else if (N <= (std::numeric_limits::max)()) { + 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 + + oa->write_character(to_char_type(output_type)); + write_number(static_cast(N)); + } + + // step 1.5: if this is an ext type, write the subtype + if (use_ext) { + write_number(static_cast(j.m_value.binary->subtype())); + } + + // step 2: write the byte string + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + N); + + break; + } + + case value_t::object: { + // step 1: write control byte and the object size + const auto N = j.m_value.object->size(); + if (N <= 15) { + // fixmap + write_number(static_cast(0x80 | (N & 0xF))); + } else if (N <= (std::numeric_limits::max)()) { + // map 16 + oa->write_character(to_char_type(0xDE)); + write_number(static_cast(N)); + } else if (N <= (std::numeric_limits::max)()) { + // map 32 + oa->write_character(to_char_type(0xDF)); + write_number(static_cast(N)); + } + + // step 2: write each element + for (const auto &el: *j.m_value.object) { + write_msgpack(el.first); + write_msgpack(el.second); + } + break; + } + + default: + break; } - break; } - default: - break; - } - } - - /*! + /*! @param[in] j JSON value to serialize @param[in] use_count whether to use '#' prefixes (optimized format) @param[in] use_type whether to use '$' prefixes (optimized format) @param[in] add_prefix whether prefixes need to be used for this value */ - void write_ubjson(const BasicJsonType& j, const bool use_count, - const bool use_type, const bool add_prefix = true) - { - switch (j.type()) - { - case value_t::null: - { - if (add_prefix) - { - oa->write_character(to_char_type('Z')); - } - break; - } - - case value_t::boolean: - { - if (add_prefix) - { - oa->write_character(j.m_value.boolean - ? to_char_type('T') - : to_char_type('F')); - } - break; - } - - case value_t::number_integer: - { - write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); - break; - } - - case value_t::number_unsigned: - { - write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); - break; - } - - case value_t::number_float: - { - write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); - break; - } - - case value_t::string: - { - if (add_prefix) - { - oa->write_character(to_char_type('S')); - } - write_number_with_ubjson_prefix(j.m_value.string->size(), true); - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); - break; - } - - case value_t::array: - { - if (add_prefix) - { - oa->write_character(to_char_type('[')); - } - - bool prefix_required = true; - if (use_type && !j.m_value.array->empty()) - { - JSON_ASSERT(use_count); - const CharType first_prefix = ubjson_prefix(j.front()); - const bool same_prefix = std::all_of(j.begin() + 1, j.end(), - [this, first_prefix](const BasicJsonType & v) - { - return ubjson_prefix(v) == first_prefix; - }); - - if (same_prefix) - { - prefix_required = false; - oa->write_character(to_char_type('$')); - oa->write_character(first_prefix); + void write_ubjson(const BasicJsonType &j, const bool use_count, + const bool use_type, const bool add_prefix = true) { + switch (j.type()) { + case value_t::null: { + if (add_prefix) { + oa->write_character(to_char_type('Z')); + } + break; } - } - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.array->size(), true); - } - - for (const auto& el : *j.m_value.array) - { - write_ubjson(el, use_count, use_type, prefix_required); - } - - if (!use_count) - { - oa->write_character(to_char_type(']')); - } - - break; - } - - case value_t::binary: - { - if (add_prefix) - { - oa->write_character(to_char_type('[')); - } - - if (use_type && !j.m_value.binary->empty()) - { - JSON_ASSERT(use_count); - oa->write_character(to_char_type('$')); - oa->write_character('U'); - } - - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.binary->size(), true); - } - - if (use_type) - { - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - j.m_value.binary->size()); - } - else - { - for (size_t i = 0; i < j.m_value.binary->size(); ++i) - { - oa->write_character(to_char_type('U')); - oa->write_character(j.m_value.binary->data()[i]); + case value_t::boolean: { + if (add_prefix) { + oa->write_character(j.m_value.boolean + ? to_char_type('T') + : to_char_type('F')); + } + break; } - } - if (!use_count) - { - oa->write_character(to_char_type(']')); - } - - break; - } - - case value_t::object: - { - if (add_prefix) - { - oa->write_character(to_char_type('{')); - } - - bool prefix_required = true; - if (use_type && !j.m_value.object->empty()) - { - JSON_ASSERT(use_count); - const CharType first_prefix = ubjson_prefix(j.front()); - const bool same_prefix = std::all_of(j.begin(), j.end(), - [this, first_prefix](const BasicJsonType & v) - { - return ubjson_prefix(v) == first_prefix; - }); - - if (same_prefix) - { - prefix_required = false; - oa->write_character(to_char_type('$')); - oa->write_character(first_prefix); + case value_t::number_integer: { + write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); + break; } - } - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.object->size(), true); - } + case value_t::number_unsigned: { + write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); + break; + } - for (const auto& el : *j.m_value.object) - { - write_number_with_ubjson_prefix(el.first.size(), true); - oa->write_characters( - reinterpret_cast(el.first.c_str()), - el.first.size()); - write_ubjson(el.second, use_count, use_type, prefix_required); - } + case value_t::number_float: { + write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); + break; + } - if (!use_count) - { - oa->write_character(to_char_type('}')); - } + case value_t::string: { + if (add_prefix) { + oa->write_character(to_char_type('S')); + } + write_number_with_ubjson_prefix(j.m_value.string->size(), true); + oa->write_characters( + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); + break; + } - break; + case value_t::array: { + if (add_prefix) { + oa->write_character(to_char_type('[')); + } + + bool prefix_required = true; + if (use_type && !j.m_value.array->empty()) { + JSON_ASSERT(use_count); + const CharType first_prefix = ubjson_prefix(j.front()); + const bool same_prefix = std::all_of(j.begin() + 1, j.end(), + [this, first_prefix](const BasicJsonType &v) { + return ubjson_prefix(v) == first_prefix; + }); + + if (same_prefix) { + prefix_required = false; + oa->write_character(to_char_type('$')); + oa->write_character(first_prefix); + } + } + + if (use_count) { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.array->size(), true); + } + + for (const auto &el: *j.m_value.array) { + write_ubjson(el, use_count, use_type, prefix_required); + } + + if (!use_count) { + oa->write_character(to_char_type(']')); + } + + break; + } + + case value_t::binary: { + if (add_prefix) { + oa->write_character(to_char_type('[')); + } + + if (use_type && !j.m_value.binary->empty()) { + JSON_ASSERT(use_count); + oa->write_character(to_char_type('$')); + oa->write_character('U'); + } + + if (use_count) { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.binary->size(), true); + } + + if (use_type) { + oa->write_characters( + reinterpret_cast(j.m_value.binary->data()), + j.m_value.binary->size()); + } else { + for (size_t i = 0; i < j.m_value.binary->size(); ++i) { + oa->write_character(to_char_type('U')); + oa->write_character(j.m_value.binary->data()[i]); + } + } + + if (!use_count) { + oa->write_character(to_char_type(']')); + } + + break; + } + + case value_t::object: { + if (add_prefix) { + oa->write_character(to_char_type('{')); + } + + bool prefix_required = true; + if (use_type && !j.m_value.object->empty()) { + JSON_ASSERT(use_count); + const CharType first_prefix = ubjson_prefix(j.front()); + const bool same_prefix = std::all_of(j.begin(), j.end(), + [this, first_prefix](const BasicJsonType &v) { + return ubjson_prefix(v) == first_prefix; + }); + + if (same_prefix) { + prefix_required = false; + oa->write_character(to_char_type('$')); + oa->write_character(first_prefix); + } + } + + if (use_count) { + oa->write_character(to_char_type('#')); + write_number_with_ubjson_prefix(j.m_value.object->size(), true); + } + + for (const auto &el: *j.m_value.object) { + write_number_with_ubjson_prefix(el.first.size(), true); + oa->write_characters( + reinterpret_cast(el.first.c_str()), + el.first.size()); + write_ubjson(el.second, use_count, use_type, prefix_required); + } + + if (!use_count) { + oa->write_character(to_char_type('}')); + } + + break; + } + + default: + break; + } } - default: - break; - } - } + private: + ////////// + // BSON // + ////////// - private: - ////////// - // BSON // - ////////// - - /*! + /*! @return The size of a BSON document entry header, including the id marker and the entry name size (and its null-terminator). */ - static std::size_t calc_bson_entry_header_size(const string_t& name) - { - const auto it = name.find(static_cast(0)); - if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) - { - JSON_THROW(out_of_range::create(409, - "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")")); - } + static std::size_t calc_bson_entry_header_size(const string_t &name) { + const auto it = name.find(static_cast(0)); + if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) { + JSON_THROW(out_of_range::create(409, + "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")")); + } - return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; - } + return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; + } - /*! + /*! @brief Writes the given @a element_type and @a name to the output adapter */ - void write_bson_entry_header(const string_t& name, - const std::uint8_t element_type) - { - oa->write_character(to_char_type(element_type)); // boolean - oa->write_characters( - reinterpret_cast(name.c_str()), - name.size() + 1u); - } + void write_bson_entry_header(const string_t &name, + const std::uint8_t element_type) { + oa->write_character(to_char_type(element_type)); // boolean + oa->write_characters( + reinterpret_cast(name.c_str()), + name.size() + 1u); + } - /*! + /*! @brief Writes a BSON element with key @a name and boolean value @a value */ - void write_bson_boolean(const string_t& name, - const bool value) - { - write_bson_entry_header(name, 0x08); - oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); - } + void write_bson_boolean(const string_t &name, + const bool value) { + write_bson_entry_header(name, 0x08); + oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); + } - /*! + /*! @brief Writes a BSON element with key @a name and double value @a value */ - void write_bson_double(const string_t& name, - const double value) - { - write_bson_entry_header(name, 0x01); - write_number(value); - } + void write_bson_double(const string_t &name, + const double value) { + write_bson_entry_header(name, 0x01); + write_number(value); + } - /*! + /*! @return The size of the BSON-encoded string in @a value */ - static std::size_t calc_bson_string_size(const string_t& value) - { - return sizeof(std::int32_t) + value.size() + 1ul; - } + static std::size_t calc_bson_string_size(const string_t &value) { + return sizeof(std::int32_t) + value.size() + 1ul; + } - /*! + /*! @brief Writes a BSON element with key @a name and string value @a value */ - void write_bson_string(const string_t& name, - const string_t& value) - { - write_bson_entry_header(name, 0x02); + void write_bson_string(const string_t &name, + const string_t &value) { + write_bson_entry_header(name, 0x02); - write_number(static_cast(value.size() + 1ul)); - oa->write_characters( - reinterpret_cast(value.c_str()), - value.size() + 1); - } + write_number(static_cast(value.size() + 1ul)); + oa->write_characters( + reinterpret_cast(value.c_str()), + value.size() + 1); + } - /*! + /*! @brief Writes a BSON element with key @a name and null value */ - void write_bson_null(const string_t& name) - { - write_bson_entry_header(name, 0x0A); - } + void write_bson_null(const string_t &name) { + write_bson_entry_header(name, 0x0A); + } - /*! + /*! @return The size of the BSON-encoded integer @a value */ - static std::size_t calc_bson_integer_size(const std::int64_t value) - { - return (std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)() - ? sizeof(std::int32_t) - : sizeof(std::int64_t); - } + static std::size_t calc_bson_integer_size(const std::int64_t value) { + return (std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)() + ? sizeof(std::int32_t) + : sizeof(std::int64_t); + } - /*! + /*! @brief Writes a BSON element with key @a name and integer @a value */ - void write_bson_integer(const string_t& name, - const std::int64_t value) - { - if ((std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)()) - { - write_bson_entry_header(name, 0x10); // int32 - write_number(static_cast(value)); - } - else - { - write_bson_entry_header(name, 0x12); // int64 - write_number(static_cast(value)); - } - } + void write_bson_integer(const string_t &name, + const std::int64_t value) { + if ((std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)()) { + write_bson_entry_header(name, 0x10); // int32 + write_number(static_cast(value)); + } else { + write_bson_entry_header(name, 0x12); // int64 + write_number(static_cast(value)); + } + } - /*! + /*! @return The size of the BSON-encoded unsigned integer in @a j */ - static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept - { - return (value <= static_cast((std::numeric_limits::max)())) - ? sizeof(std::int32_t) - : sizeof(std::int64_t); - } + static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept { + return (value <= static_cast((std::numeric_limits::max)())) + ? sizeof(std::int32_t) + : sizeof(std::int64_t); + } - /*! + /*! @brief Writes a BSON element with key @a name and unsigned @a value */ - void write_bson_unsigned(const string_t& name, - const std::uint64_t value) - { - if (value <= static_cast((std::numeric_limits::max)())) - { - write_bson_entry_header(name, 0x10 /* int32 */); - write_number(static_cast(value)); - } - else if (value <= static_cast((std::numeric_limits::max)())) - { - write_bson_entry_header(name, 0x12 /* int64 */); - write_number(static_cast(value)); - } - else - { - JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64")); - } - } + void write_bson_unsigned(const string_t &name, + const std::uint64_t value) { + if (value <= static_cast((std::numeric_limits::max)())) { + write_bson_entry_header(name, 0x10 /* int32 */); + write_number(static_cast(value)); + } else if (value <= static_cast((std::numeric_limits::max)())) { + write_bson_entry_header(name, 0x12 /* int64 */); + write_number(static_cast(value)); + } else { + JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64")); + } + } - /*! + /*! @brief Writes a BSON element with key @a name and object @a value */ - void write_bson_object_entry(const string_t& name, - const typename BasicJsonType::object_t& value) - { - write_bson_entry_header(name, 0x03); // object - write_bson_object(value); - } + void write_bson_object_entry(const string_t &name, + const typename BasicJsonType::object_t &value) { + write_bson_entry_header(name, 0x03); // object + write_bson_object(value); + } - /*! + /*! @return The size of the BSON-encoded array @a value */ - static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) - { - std::size_t array_index = 0ul; + static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t &value) { + std::size_t array_index = 0ul; - const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) - { - return result + calc_bson_element_size(std::to_string(array_index++), el); - }); + const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), + [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type &el) { + return result + calc_bson_element_size(std::to_string(array_index++), el); + }); - return sizeof(std::int32_t) + embedded_document_size + 1ul; - } + return sizeof(std::int32_t) + embedded_document_size + 1ul; + } - /*! + /*! @return The size of the BSON-encoded binary array @a value */ - static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) - { - return sizeof(std::int32_t) + value.size() + 1ul; - } + static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t &value) { + return sizeof(std::int32_t) + value.size() + 1ul; + } - /*! + /*! @brief Writes a BSON element with key @a name and array @a value */ - void write_bson_array(const string_t& name, - const typename BasicJsonType::array_t& value) - { - write_bson_entry_header(name, 0x04); // array - write_number(static_cast(calc_bson_array_size(value))); + void write_bson_array(const string_t &name, + const typename BasicJsonType::array_t &value) { + write_bson_entry_header(name, 0x04); // array + write_number(static_cast(calc_bson_array_size(value))); - std::size_t array_index = 0ul; + std::size_t array_index = 0ul; - for (const auto& el : value) - { - write_bson_element(std::to_string(array_index++), el); - } + for (const auto &el: value) { + write_bson_element(std::to_string(array_index++), el); + } - oa->write_character(to_char_type(0x00)); - } + oa->write_character(to_char_type(0x00)); + } - /*! + /*! @brief Writes a BSON element with key @a name and binary value @a value */ - void write_bson_binary(const string_t& name, - const binary_t& value) - { - write_bson_entry_header(name, 0x05); + void write_bson_binary(const string_t &name, + const binary_t &value) { + write_bson_entry_header(name, 0x05); - write_number(static_cast(value.size())); - write_number(value.has_subtype() ? value.subtype() : std::uint8_t(0x00)); + write_number(static_cast(value.size())); + write_number(value.has_subtype() ? value.subtype() : std::uint8_t(0x00)); - oa->write_characters(reinterpret_cast(value.data()), value.size()); - } + oa->write_characters(reinterpret_cast(value.data()), value.size()); + } - /*! + /*! @brief Calculates the size necessary to serialize the JSON value @a j with its @a name @return The calculated size for the BSON document entry for @a j with the given @a name. */ - static std::size_t calc_bson_element_size(const string_t& name, - const BasicJsonType& j) - { - const auto header_size = calc_bson_entry_header_size(name); - switch (j.type()) - { - case value_t::object: - return header_size + calc_bson_object_size(*j.m_value.object); + static std::size_t calc_bson_element_size(const string_t &name, + const BasicJsonType &j) { + const auto header_size = calc_bson_entry_header_size(name); + switch (j.type()) { + case value_t::object: + return header_size + calc_bson_object_size(*j.m_value.object); - case value_t::array: - return header_size + calc_bson_array_size(*j.m_value.array); + case value_t::array: + return header_size + calc_bson_array_size(*j.m_value.array); - case value_t::binary: - return header_size + calc_bson_binary_size(*j.m_value.binary); + case value_t::binary: + return header_size + calc_bson_binary_size(*j.m_value.binary); - case value_t::boolean: - return header_size + 1ul; + case value_t::boolean: + return header_size + 1ul; - case value_t::number_float: - return header_size + 8ul; + case value_t::number_float: + return header_size + 8ul; - case value_t::number_integer: - return header_size + calc_bson_integer_size(j.m_value.number_integer); + case value_t::number_integer: + return header_size + calc_bson_integer_size(j.m_value.number_integer); - case value_t::number_unsigned: - return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); + case value_t::number_unsigned: + return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); - case value_t::string: - return header_size + calc_bson_string_size(*j.m_value.string); + case value_t::string: + return header_size + calc_bson_string_size(*j.m_value.string); - case value_t::null: - return header_size + 0ul; + case value_t::null: + return header_size + 0ul; - // LCOV_EXCL_START - default: - JSON_ASSERT(false); - return 0ul; - // LCOV_EXCL_STOP - } - } + // LCOV_EXCL_START + default: + JSON_ASSERT(false); + return 0ul; + // LCOV_EXCL_STOP + } + } - /*! + /*! @brief Serializes the JSON value @a j to BSON and associates it with the key @a name. @param name The name to associate with the JSON entity @a j within the current BSON document @return The size of the BSON entry */ - void write_bson_element(const string_t& name, - const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::object: - return write_bson_object_entry(name, *j.m_value.object); + void write_bson_element(const string_t &name, + const BasicJsonType &j) { + switch (j.type()) { + case value_t::object: + return write_bson_object_entry(name, *j.m_value.object); - case value_t::array: - return write_bson_array(name, *j.m_value.array); + case value_t::array: + return write_bson_array(name, *j.m_value.array); - case value_t::binary: - return write_bson_binary(name, *j.m_value.binary); + case value_t::binary: + return write_bson_binary(name, *j.m_value.binary); - case value_t::boolean: - return write_bson_boolean(name, j.m_value.boolean); + case value_t::boolean: + return write_bson_boolean(name, j.m_value.boolean); - case value_t::number_float: - return write_bson_double(name, j.m_value.number_float); + case value_t::number_float: + return write_bson_double(name, j.m_value.number_float); - case value_t::number_integer: - return write_bson_integer(name, j.m_value.number_integer); + case value_t::number_integer: + return write_bson_integer(name, j.m_value.number_integer); - case value_t::number_unsigned: - return write_bson_unsigned(name, j.m_value.number_unsigned); + case value_t::number_unsigned: + return write_bson_unsigned(name, j.m_value.number_unsigned); - case value_t::string: - return write_bson_string(name, *j.m_value.string); + case value_t::string: + return write_bson_string(name, *j.m_value.string); - case value_t::null: - return write_bson_null(name); + case value_t::null: + return write_bson_null(name); - // LCOV_EXCL_START - default: - JSON_ASSERT(false); - return; - // LCOV_EXCL_STOP - } - } + // LCOV_EXCL_START + default: + JSON_ASSERT(false); + return; + // LCOV_EXCL_STOP + } + } - /*! + /*! @brief Calculates the size of the BSON serialization of the given JSON-object @a j. @param[in] j JSON value to serialize @pre j.type() == value_t::object */ - 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(), std::size_t(0), - [](size_t result, const typename BasicJsonType::object_t::value_type & el) - { - return result += calc_bson_element_size(el.first, el.second); - }); + 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(), std::size_t(0), + [](size_t result, const typename BasicJsonType::object_t::value_type &el) { + return result += calc_bson_element_size(el.first, el.second); + }); - return sizeof(std::int32_t) + document_size + 1ul; - } + return sizeof(std::int32_t) + document_size + 1ul; + } - /*! + /*! @param[in] j JSON value to serialize @pre j.type() == value_t::object */ - void write_bson_object(const typename BasicJsonType::object_t& value) - { - write_number(static_cast(calc_bson_object_size(value))); + void write_bson_object(const typename BasicJsonType::object_t &value) { + write_number(static_cast(calc_bson_object_size(value))); - for (const auto& el : value) - { - write_bson_element(el.first, el.second); - } + for (const auto &el: value) { + write_bson_element(el.first, el.second); + } - oa->write_character(to_char_type(0x00)); - } - - ////////// - // CBOR // - ////////// - - static constexpr CharType get_cbor_float_prefix(float /*unused*/) - { - return to_char_type(0xFA); // Single-Precision Float - } - - static constexpr CharType get_cbor_float_prefix(double /*unused*/) - { - return to_char_type(0xFB); // Double-Precision Float - } - - ///////////// - // MsgPack // - ///////////// - - static constexpr CharType get_msgpack_float_prefix(float /*unused*/) - { - return to_char_type(0xCA); // float 32 - } - - static constexpr CharType get_msgpack_float_prefix(double /*unused*/) - { - return to_char_type(0xCB); // float 64 - } - - //////////// - // UBJSON // - //////////// - - // UBJSON: write number (floating point) - template::value, int>::type = 0> - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if (add_prefix) - { - oa->write_character(get_ubjson_float_prefix(n)); - } - write_number(n); - } - - // UBJSON: write number (unsigned integer) - template::value, int>::type = 0> - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('i')); // int8 - } - write_number(static_cast(n)); - } - else if (n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('U')); // uint8 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('I')); // int16 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('l')); // int32 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('L')); // int64 - } - write_number(static_cast(n)); - } - else - { - if (add_prefix) - { - oa->write_character(to_char_type('H')); // high-precision number + oa->write_character(to_char_type(0x00)); } - const auto number = BasicJsonType(n).dump(); - write_number_with_ubjson_prefix(number.size(), true); - for (std::size_t i = 0; i < number.size(); ++i) - { - oa->write_character(to_char_type(static_cast(number[i]))); - } - } - } + ////////// + // CBOR // + ////////// - // UBJSON: write number (signed integer) - template < typename NumberType, typename std::enable_if < - std::is_signed::value&& - !std::is_floating_point::value, int >::type = 0 > - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('i')); // int8 - } - write_number(static_cast(n)); - } - else if (static_cast((std::numeric_limits::min)()) <= n && n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('U')); // uint8 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('I')); // int16 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('l')); // int32 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('L')); // int64 - } - write_number(static_cast(n)); - } - // LCOV_EXCL_START - else - { - if (add_prefix) - { - oa->write_character(to_char_type('H')); // high-precision number + static constexpr CharType get_cbor_float_prefix(float /*unused*/) { + return to_char_type(0xFA); // Single-Precision Float } - const auto number = BasicJsonType(n).dump(); - write_number_with_ubjson_prefix(number.size(), true); - for (std::size_t i = 0; i < number.size(); ++i) - { - oa->write_character(to_char_type(static_cast(number[i]))); + static constexpr CharType get_cbor_float_prefix(double /*unused*/) { + return to_char_type(0xFB); // Double-Precision Float } - } - // LCOV_EXCL_STOP - } - /*! + ///////////// + // MsgPack // + ///////////// + + static constexpr CharType get_msgpack_float_prefix(float /*unused*/) { + return to_char_type(0xCA); // float 32 + } + + static constexpr CharType get_msgpack_float_prefix(double /*unused*/) { + return to_char_type(0xCB); // float 64 + } + + //////////// + // UBJSON // + //////////// + + // UBJSON: write number (floating point) + template::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) { + if (add_prefix) { + oa->write_character(get_ubjson_float_prefix(n)); + } + write_number(n); + } + + // UBJSON: write number (unsigned integer) + template::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) { + if (n <= static_cast((std::numeric_limits::max)())) { + if (add_prefix) { + oa->write_character(to_char_type('i')); // int8 + } + write_number(static_cast(n)); + } else if (n <= (std::numeric_limits::max)()) { + if (add_prefix) { + oa->write_character(to_char_type('U')); // uint8 + } + write_number(static_cast(n)); + } else if (n <= static_cast((std::numeric_limits::max)())) { + if (add_prefix) { + oa->write_character(to_char_type('I')); // int16 + } + write_number(static_cast(n)); + } else if (n <= static_cast((std::numeric_limits::max)())) { + if (add_prefix) { + oa->write_character(to_char_type('l')); // int32 + } + write_number(static_cast(n)); + } else if (n <= static_cast((std::numeric_limits::max)())) { + if (add_prefix) { + oa->write_character(to_char_type('L')); // int64 + } + write_number(static_cast(n)); + } else { + if (add_prefix) { + oa->write_character(to_char_type('H')); // high-precision number + } + + const auto number = BasicJsonType(n).dump(); + write_number_with_ubjson_prefix(number.size(), true); + for (std::size_t i = 0; i < number.size(); ++i) { + oa->write_character(to_char_type(static_cast(number[i]))); + } + } + } + + // UBJSON: write number (signed integer) + template::value && + !std::is_floating_point::value, int>::type = 0> + void write_number_with_ubjson_prefix(const NumberType n, + const bool add_prefix) { + if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) { + if (add_prefix) { + oa->write_character(to_char_type('i')); // int8 + } + write_number(static_cast(n)); + } else if (static_cast((std::numeric_limits::min)()) <= n && n <= static_cast((std::numeric_limits::max)())) { + if (add_prefix) { + oa->write_character(to_char_type('U')); // uint8 + } + write_number(static_cast(n)); + } else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) { + if (add_prefix) { + oa->write_character(to_char_type('I')); // int16 + } + write_number(static_cast(n)); + } else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) { + if (add_prefix) { + oa->write_character(to_char_type('l')); // int32 + } + write_number(static_cast(n)); + } else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) { + if (add_prefix) { + oa->write_character(to_char_type('L')); // int64 + } + write_number(static_cast(n)); + } + // LCOV_EXCL_START + else { + if (add_prefix) { + oa->write_character(to_char_type('H')); // high-precision number + } + + const auto number = BasicJsonType(n).dump(); + write_number_with_ubjson_prefix(number.size(), true); + for (std::size_t i = 0; i < number.size(); ++i) { + oa->write_character(to_char_type(static_cast(number[i]))); + } + } + // LCOV_EXCL_STOP + } + + /*! @brief determine the type prefix of container values */ - CharType ubjson_prefix(const BasicJsonType& j) const noexcept - { - switch (j.type()) - { - case value_t::null: - return 'Z'; + CharType ubjson_prefix(const BasicJsonType &j) const noexcept { + switch (j.type()) { + case value_t::null: + return 'Z'; - case value_t::boolean: - return j.m_value.boolean ? 'T' : 'F'; + case value_t::boolean: + return j.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)()) - { - return 'i'; + case value_t::number_integer: { + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.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)()) { + return 'U'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.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)()) { + return 'l'; + } + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { + return 'L'; + } + // anything else is treated as high-precision number + return 'H'; // LCOV_EXCL_LINE + } + + case value_t::number_unsigned: { + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { + return 'i'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { + return 'U'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { + return 'I'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { + return 'l'; + } + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { + return 'L'; + } + // anything else is treated as high-precision number + return 'H'; // LCOV_EXCL_LINE + } + + case value_t::number_float: + return get_ubjson_float_prefix(j.m_value.number_float); + + case value_t::string: + return 'S'; + + case value_t::array: // fallthrough + case value_t::binary: + return '['; + + case value_t::object: + return '{'; + + default: // discarded values + return 'N'; } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.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)()) - { - return 'I'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'l'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'L'; - } - // anything else is treated as high-precision number - return 'H'; // LCOV_EXCL_LINE } - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'i'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'U'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'I'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'l'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'L'; - } - // anything else is treated as high-precision number - return 'H'; // LCOV_EXCL_LINE + static constexpr CharType get_ubjson_float_prefix(float /*unused*/) { + return 'd'; // float 32 } - case value_t::number_float: - return get_ubjson_float_prefix(j.m_value.number_float); + static constexpr CharType get_ubjson_float_prefix(double /*unused*/) { + return 'D'; // float 64 + } - case value_t::string: - return 'S'; + /////////////////////// + // Utility functions // + /////////////////////// - case value_t::array: // fallthrough - case value_t::binary: - return '['; - - case value_t::object: - return '{'; - - default: // discarded values - return 'N'; - } - } - - static constexpr CharType get_ubjson_float_prefix(float /*unused*/) - { - return 'd'; // float 32 - } - - static constexpr CharType get_ubjson_float_prefix(double /*unused*/) - { - return 'D'; // float 64 - } - - /////////////////////// - // Utility functions // - /////////////////////// - - /* + /* @brief write a number to output input @param[in] n number of type @a NumberType @tparam NumberType the type of the number @@ -14231,92 +12971,82 @@ class binary_writer in CBOR, MessagePack, and UBJSON are stored in network order (big endian) and therefore need reordering on little endian systems. */ - template - void write_number(const NumberType n) - { - // step 1: write number to array of length NumberType - std::array vec; - std::memcpy(vec.data(), &n, sizeof(NumberType)); + template + void write_number(const NumberType n) { + // step 1: write number to array of length NumberType + std::array vec; + std::memcpy(vec.data(), &n, sizeof(NumberType)); - // step 2: write array to output (with possible reordering) - if (is_little_endian != OutputIsLittleEndian) - { - // reverse byte order prior to conversion if necessary - std::reverse(vec.begin(), vec.end()); - } + // step 2: write array to output (with possible reordering) + if (is_little_endian != OutputIsLittleEndian) { + // reverse byte order prior to conversion if necessary + std::reverse(vec.begin(), vec.end()); + } - oa->write_characters(vec.data(), sizeof(NumberType)); - } + oa->write_characters(vec.data(), sizeof(NumberType)); + } - void write_compact_float(const number_float_t n, detail::input_format_t format) - { - if (static_cast(n) >= static_cast(std::numeric_limits::lowest()) && - static_cast(n) <= static_cast((std::numeric_limits::max)()) && - static_cast(static_cast(n)) == static_cast(n)) - { - oa->write_character(format == detail::input_format_t::cbor - ? get_cbor_float_prefix(static_cast(n)) - : get_msgpack_float_prefix(static_cast(n))); - write_number(static_cast(n)); - } - else - { - oa->write_character(format == detail::input_format_t::cbor - ? get_cbor_float_prefix(n) - : get_msgpack_float_prefix(n)); - write_number(n); - } - } + void write_compact_float(const number_float_t n, detail::input_format_t format) { + if (static_cast(n) >= static_cast(std::numeric_limits::lowest()) && + static_cast(n) <= static_cast((std::numeric_limits::max)()) && + static_cast(static_cast(n)) == static_cast(n)) { + oa->write_character(format == detail::input_format_t::cbor + ? get_cbor_float_prefix(static_cast(n)) + : get_msgpack_float_prefix(static_cast(n))); + write_number(static_cast(n)); + } else { + oa->write_character(format == detail::input_format_t::cbor + ? get_cbor_float_prefix(n) + : get_msgpack_float_prefix(n)); + write_number(n); + } + } - public: - // The following to_char_type functions are implement the conversion - // between uint8_t and CharType. In case CharType is not unsigned, - // such a conversion is required to allow values greater than 128. - // See for a discussion. - template < typename C = CharType, - enable_if_t < std::is_signed::value && std::is_signed::value > * = nullptr > - static constexpr CharType to_char_type(std::uint8_t x) noexcept - { - return *reinterpret_cast(&x); - } + public: + // The following to_char_type functions are implement the conversion + // between uint8_t and CharType. In case CharType is not unsigned, + // such a conversion is required to allow values greater than 128. + // See for a discussion. + template::value && std::is_signed::value> * = nullptr> + static constexpr CharType to_char_type(std::uint8_t x) noexcept { + return *reinterpret_cast(&x); + } - template < typename C = CharType, - enable_if_t < std::is_signed::value && std::is_unsigned::value > * = nullptr > - static CharType to_char_type(std::uint8_t x) noexcept - { - static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); - static_assert(std::is_trivial::value, "CharType must be trivial"); - CharType result; - std::memcpy(&result, &x, sizeof(x)); - return result; - } + template::value && std::is_unsigned::value> * = nullptr> + static CharType to_char_type(std::uint8_t x) noexcept { + static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); + static_assert(std::is_trivial::value, "CharType must be trivial"); + CharType result; + std::memcpy(&result, &x, sizeof(x)); + return result; + } - template::value>* = nullptr> - static constexpr CharType to_char_type(std::uint8_t x) noexcept - { - return x; - } + template::value> * = nullptr> + static constexpr CharType to_char_type(std::uint8_t x) noexcept { + return x; + } - template < typename InputCharType, typename C = CharType, - enable_if_t < - std::is_signed::value && - std::is_signed::value && - std::is_same::type>::value - > * = nullptr > - static constexpr CharType to_char_type(InputCharType x) noexcept - { - return x; - } + template::value && + std::is_signed::value && + std::is_same::type>::value + > * = nullptr> + static constexpr CharType to_char_type(InputCharType x) noexcept { + return x; + } - private: - /// whether we can assume little endianess - const bool is_little_endian = little_endianess(); + private: + /// whether we can assume little endianess + const bool is_little_endian = little_endianess(); - /// the output - output_adapter_t oa = nullptr; -}; -} // namespace detail + /// the output + output_adapter_t oa = nullptr; + }; + } // namespace detail } // namespace nlohmann // #include @@ -14349,10 +13079,8 @@ class binary_writer // #include -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /*! @brief implements the Grisu2 algorithm for binary to decimal floating-point @@ -14373,143 +13101,135 @@ For a detailed description of the algorithm see: Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language Design and Implementation, PLDI 1996 */ -namespace dtoa_impl -{ + namespace dtoa_impl { -template -Target reinterpret_bits(const Source source) -{ - static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); + template + Target reinterpret_bits(const Source source) { + static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); - Target target; - std::memcpy(&target, &source, sizeof(Source)); - return target; -} + Target target; + std::memcpy(&target, &source, sizeof(Source)); + return target; + } -struct diyfp // f * 2^e -{ - static constexpr int kPrecision = 64; // = q + struct diyfp // f * 2^e + { + static constexpr int kPrecision = 64; // = q - std::uint64_t f = 0; - int e = 0; + std::uint64_t f = 0; + int e = 0; - constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} + constexpr diyfp(std::uint64_t f_, int e_) noexcept: f(f_), e(e_) {} - /*! + /*! @brief returns x - y @pre x.e == y.e and x.f >= y.f */ - static diyfp sub(const diyfp& x, const diyfp& y) noexcept - { - JSON_ASSERT(x.e == y.e); - JSON_ASSERT(x.f >= y.f); + static diyfp sub(const diyfp &x, const diyfp &y) noexcept { + JSON_ASSERT(x.e == y.e); + JSON_ASSERT(x.f >= y.f); - return {x.f - y.f, x.e}; - } + return {x.f - y.f, x.e}; + } - /*! + /*! @brief returns x * y @note The result is rounded. (Only the upper q bits are returned.) */ - static diyfp mul(const diyfp& x, const diyfp& y) noexcept - { - static_assert(kPrecision == 64, "internal error"); + static diyfp mul(const diyfp &x, const diyfp &y) noexcept { + static_assert(kPrecision == 64, "internal error"); - // Computes: - // f = round((x.f * y.f) / 2^q) - // e = x.e + y.e + q + // Computes: + // f = round((x.f * y.f) / 2^q) + // e = x.e + y.e + q - // Emulate the 64-bit * 64-bit multiplication: - // - // p = u * v - // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) - // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) - // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) - // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) - // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) - // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) - // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) - // - // (Since Q might be larger than 2^32 - 1) - // - // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) - // - // (Q_hi + H does not overflow a 64-bit int) - // - // = p_lo + 2^64 p_hi + // Emulate the 64-bit * 64-bit multiplication: + // + // p = u * v + // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) + // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) + // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) + // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) + // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) + // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) + // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) + // + // (Since Q might be larger than 2^32 - 1) + // + // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) + // + // (Q_hi + H does not overflow a 64-bit int) + // + // = p_lo + 2^64 p_hi - const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; - const std::uint64_t u_hi = x.f >> 32u; - const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; - const std::uint64_t v_hi = y.f >> 32u; + const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; + const std::uint64_t u_hi = x.f >> 32u; + const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; + const std::uint64_t v_hi = y.f >> 32u; - const std::uint64_t p0 = u_lo * v_lo; - const std::uint64_t p1 = u_lo * v_hi; - const std::uint64_t p2 = u_hi * v_lo; - const std::uint64_t p3 = u_hi * v_hi; + const std::uint64_t p0 = u_lo * v_lo; + const std::uint64_t p1 = u_lo * v_hi; + const std::uint64_t p2 = u_hi * v_lo; + const std::uint64_t p3 = u_hi * v_hi; - const std::uint64_t p0_hi = p0 >> 32u; - const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; - const std::uint64_t p1_hi = p1 >> 32u; - const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; - const std::uint64_t p2_hi = p2 >> 32u; + const std::uint64_t p0_hi = p0 >> 32u; + const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; + const std::uint64_t p1_hi = p1 >> 32u; + const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; + const std::uint64_t p2_hi = p2 >> 32u; - std::uint64_t Q = p0_hi + p1_lo + p2_lo; + std::uint64_t Q = p0_hi + p1_lo + p2_lo; - // The full product might now be computed as - // - // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) - // p_lo = p0_lo + (Q << 32) - // - // But in this particular case here, the full p_lo is not required. - // Effectively we only need to add the highest bit in p_lo to p_hi (and - // Q_hi + 1 does not overflow). + // The full product might now be computed as + // + // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) + // p_lo = p0_lo + (Q << 32) + // + // But in this particular case here, the full p_lo is not required. + // Effectively we only need to add the highest bit in p_lo to p_hi (and + // Q_hi + 1 does not overflow). - Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up + Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up - const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); + const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); - return {h, x.e + y.e + 64}; - } + return {h, x.e + y.e + 64}; + } - /*! + /*! @brief normalize x such that the significand is >= 2^(q-1) @pre x.f != 0 */ - static diyfp normalize(diyfp x) noexcept - { - JSON_ASSERT(x.f != 0); + static diyfp normalize(diyfp x) noexcept { + JSON_ASSERT(x.f != 0); - while ((x.f >> 63u) == 0) - { - x.f <<= 1u; - x.e--; - } + while ((x.f >> 63u) == 0) { + x.f <<= 1u; + x.e--; + } - return x; - } + return x; + } - /*! + /*! @brief normalize x such that the result has the exponent E @pre e >= x.e and the upper e - x.e bits of x.f must be zero. */ - static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept - { - const int delta = x.e - target_exponent; + static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept { + const int delta = x.e - target_exponent; - JSON_ASSERT(delta >= 0); - JSON_ASSERT(((x.f << delta) >> delta) == x.f); + JSON_ASSERT(delta >= 0); + JSON_ASSERT(((x.f << delta) >> delta) == x.f); - return {x.f << delta, target_exponent}; - } -}; + return {x.f << delta, target_exponent}; + } + }; -struct boundaries -{ - diyfp w; - diyfp minus; - diyfp plus; -}; + struct boundaries { + diyfp w; + diyfp minus; + diyfp plus; + }; /*! Compute the (normalized) diyfp representing the input number 'value' and its @@ -14517,73 +13237,72 @@ boundaries. @pre value must be finite and positive */ -template -boundaries compute_boundaries(FloatType value) -{ - JSON_ASSERT(std::isfinite(value)); - JSON_ASSERT(value > 0); + template + boundaries compute_boundaries(FloatType value) { + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); - // Convert the IEEE representation into a diyfp. - // - // If v is denormal: - // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) - // If v is normalized: - // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) + // Convert the IEEE representation into a diyfp. + // + // If v is denormal: + // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) + // If v is normalized: + // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) - static_assert(std::numeric_limits::is_iec559, - "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); + static_assert(std::numeric_limits::is_iec559, + "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); - constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) - constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); - constexpr int kMinExp = 1 - kBias; - constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) + constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) + constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); + constexpr int kMinExp = 1 - kBias; + constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) - using bits_type = typename std::conditional::type; + using bits_type = typename std::conditional::type; - const std::uint64_t bits = reinterpret_bits(value); - const std::uint64_t E = bits >> (kPrecision - 1); - const std::uint64_t F = bits & (kHiddenBit - 1); + const std::uint64_t bits = reinterpret_bits(value); + const std::uint64_t E = bits >> (kPrecision - 1); + const std::uint64_t F = bits & (kHiddenBit - 1); - const bool is_denormal = E == 0; - const diyfp v = is_denormal - ? diyfp(F, kMinExp) - : diyfp(F + kHiddenBit, static_cast(E) - kBias); + const bool is_denormal = E == 0; + const diyfp v = is_denormal + ? diyfp(F, kMinExp) + : diyfp(F + kHiddenBit, static_cast(E) - kBias); - // Compute the boundaries m- and m+ of the floating-point value - // v = f * 2^e. - // - // Determine v- and v+, the floating-point predecessor and successor if v, - // respectively. - // - // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) - // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) - // - // v+ = v + 2^e - // - // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ - // between m- and m+ round to v, regardless of how the input rounding - // algorithm breaks ties. - // - // ---+-------------+-------------+-------------+-------------+--- (A) - // v- m- v m+ v+ - // - // -----------------+------+------+-------------+-------------+--- (B) - // v- m- v m+ v+ + // Compute the boundaries m- and m+ of the floating-point value + // v = f * 2^e. + // + // Determine v- and v+, the floating-point predecessor and successor if v, + // respectively. + // + // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) + // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) + // + // v+ = v + 2^e + // + // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ + // between m- and m+ round to v, regardless of how the input rounding + // algorithm breaks ties. + // + // ---+-------------+-------------+-------------+-------------+--- (A) + // v- m- v m+ v+ + // + // -----------------+------+------+-------------+-------------+--- (B) + // v- m- v m+ v+ - const bool lower_boundary_is_closer = F == 0 && E > 1; - const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); - const diyfp m_minus = lower_boundary_is_closer - ? diyfp(4 * v.f - 1, v.e - 2) // (B) - : diyfp(2 * v.f - 1, v.e - 1); // (A) + const bool lower_boundary_is_closer = F == 0 && E > 1; + const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_minus = lower_boundary_is_closer + ? diyfp(4 * v.f - 1, v.e - 2) // (B) + : diyfp(2 * v.f - 1, v.e - 1); // (A) - // Determine the normalized w+ = m+. - const diyfp w_plus = diyfp::normalize(m_plus); + // Determine the normalized w+ = m+. + const diyfp w_plus = diyfp::normalize(m_plus); - // Determine w- = m- such that e_(w-) = e_(w+). - const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); + // Determine w- = m- such that e_(w-) = e_(w+). + const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); - return {diyfp::normalize(v), w_minus, w_plus}; -} + return {diyfp::normalize(v), w_minus, w_plus}; + } // Given normalized diyfp w, Grisu needs to find a (normalized) cached // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies @@ -14640,15 +13359,15 @@ boundaries compute_boundaries(FloatType value) // // -e <= 60 or e >= -60 := alpha -constexpr int kAlpha = -60; -constexpr int kGamma = -32; + constexpr int kAlpha = -60; + constexpr int kGamma = -32; -struct cached_power // c = f * 2^e ~= 10^k -{ - std::uint64_t f; - int e; - int k; -}; + struct cached_power // c = f * 2^e ~= 10^k + { + std::uint64_t f; + int e; + int k; + }; /*! For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached @@ -14657,648 +13376,610 @@ satisfies (Definition 3.2 from [1]) alpha <= e_c + e + q <= gamma. */ -inline cached_power get_cached_power_for_binary_exponent(int e) -{ - // Now - // - // alpha <= e_c + e + q <= gamma (1) - // ==> f_c * 2^alpha <= c * 2^e * 2^q - // - // and since the c's are normalized, 2^(q-1) <= f_c, - // - // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) - // ==> 2^(alpha - e - 1) <= c - // - // If c were an exact power of ten, i.e. c = 10^k, one may determine k as - // - // k = ceil( log_10( 2^(alpha - e - 1) ) ) - // = ceil( (alpha - e - 1) * log_10(2) ) - // - // From the paper: - // "In theory the result of the procedure could be wrong since c is rounded, - // and the computation itself is approximated [...]. In practice, however, - // this simple function is sufficient." - // - // For IEEE double precision floating-point numbers converted into - // normalized diyfp's w = f * 2^e, with q = 64, - // - // e >= -1022 (min IEEE exponent) - // -52 (p - 1) - // -52 (p - 1, possibly normalize denormal IEEE numbers) - // -11 (normalize the diyfp) - // = -1137 - // - // and - // - // e <= +1023 (max IEEE exponent) - // -52 (p - 1) - // -11 (normalize the diyfp) - // = 960 - // - // This binary exponent range [-1137,960] results in a decimal exponent - // range [-307,324]. One does not need to store a cached power for each - // k in this range. For each such k it suffices to find a cached power - // such that the exponent of the product lies in [alpha,gamma]. - // This implies that the difference of the decimal exponents of adjacent - // table entries must be less than or equal to - // - // floor( (gamma - alpha) * log_10(2) ) = 8. - // - // (A smaller distance gamma-alpha would require a larger table.) + inline cached_power get_cached_power_for_binary_exponent(int e) { + // Now + // + // alpha <= e_c + e + q <= gamma (1) + // ==> f_c * 2^alpha <= c * 2^e * 2^q + // + // and since the c's are normalized, 2^(q-1) <= f_c, + // + // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) + // ==> 2^(alpha - e - 1) <= c + // + // If c were an exact power of ten, i.e. c = 10^k, one may determine k as + // + // k = ceil( log_10( 2^(alpha - e - 1) ) ) + // = ceil( (alpha - e - 1) * log_10(2) ) + // + // From the paper: + // "In theory the result of the procedure could be wrong since c is rounded, + // and the computation itself is approximated [...]. In practice, however, + // this simple function is sufficient." + // + // For IEEE double precision floating-point numbers converted into + // normalized diyfp's w = f * 2^e, with q = 64, + // + // e >= -1022 (min IEEE exponent) + // -52 (p - 1) + // -52 (p - 1, possibly normalize denormal IEEE numbers) + // -11 (normalize the diyfp) + // = -1137 + // + // and + // + // e <= +1023 (max IEEE exponent) + // -52 (p - 1) + // -11 (normalize the diyfp) + // = 960 + // + // This binary exponent range [-1137,960] results in a decimal exponent + // range [-307,324]. One does not need to store a cached power for each + // k in this range. For each such k it suffices to find a cached power + // such that the exponent of the product lies in [alpha,gamma]. + // This implies that the difference of the decimal exponents of adjacent + // table entries must be less than or equal to + // + // floor( (gamma - alpha) * log_10(2) ) = 8. + // + // (A smaller distance gamma-alpha would require a larger table.) - // NB: - // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. + // NB: + // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. - constexpr int kCachedPowersMinDecExp = -300; - constexpr int kCachedPowersDecStep = 8; + constexpr int kCachedPowersMinDecExp = -300; + constexpr int kCachedPowersDecStep = 8; - static constexpr std::array kCachedPowers = - { - { - { 0xAB70FE17C79AC6CA, -1060, -300 }, - { 0xFF77B1FCBEBCDC4F, -1034, -292 }, - { 0xBE5691EF416BD60C, -1007, -284 }, - { 0x8DD01FAD907FFC3C, -980, -276 }, - { 0xD3515C2831559A83, -954, -268 }, - { 0x9D71AC8FADA6C9B5, -927, -260 }, - { 0xEA9C227723EE8BCB, -901, -252 }, - { 0xAECC49914078536D, -874, -244 }, - { 0x823C12795DB6CE57, -847, -236 }, - { 0xC21094364DFB5637, -821, -228 }, - { 0x9096EA6F3848984F, -794, -220 }, - { 0xD77485CB25823AC7, -768, -212 }, - { 0xA086CFCD97BF97F4, -741, -204 }, - { 0xEF340A98172AACE5, -715, -196 }, - { 0xB23867FB2A35B28E, -688, -188 }, - { 0x84C8D4DFD2C63F3B, -661, -180 }, - { 0xC5DD44271AD3CDBA, -635, -172 }, - { 0x936B9FCEBB25C996, -608, -164 }, - { 0xDBAC6C247D62A584, -582, -156 }, - { 0xA3AB66580D5FDAF6, -555, -148 }, - { 0xF3E2F893DEC3F126, -529, -140 }, - { 0xB5B5ADA8AAFF80B8, -502, -132 }, - { 0x87625F056C7C4A8B, -475, -124 }, - { 0xC9BCFF6034C13053, -449, -116 }, - { 0x964E858C91BA2655, -422, -108 }, - { 0xDFF9772470297EBD, -396, -100 }, - { 0xA6DFBD9FB8E5B88F, -369, -92 }, - { 0xF8A95FCF88747D94, -343, -84 }, - { 0xB94470938FA89BCF, -316, -76 }, - { 0x8A08F0F8BF0F156B, -289, -68 }, - { 0xCDB02555653131B6, -263, -60 }, - { 0x993FE2C6D07B7FAC, -236, -52 }, - { 0xE45C10C42A2B3B06, -210, -44 }, - { 0xAA242499697392D3, -183, -36 }, - { 0xFD87B5F28300CA0E, -157, -28 }, - { 0xBCE5086492111AEB, -130, -20 }, - { 0x8CBCCC096F5088CC, -103, -12 }, - { 0xD1B71758E219652C, -77, -4 }, - { 0x9C40000000000000, -50, 4 }, - { 0xE8D4A51000000000, -24, 12 }, - { 0xAD78EBC5AC620000, 3, 20 }, - { 0x813F3978F8940984, 30, 28 }, - { 0xC097CE7BC90715B3, 56, 36 }, - { 0x8F7E32CE7BEA5C70, 83, 44 }, - { 0xD5D238A4ABE98068, 109, 52 }, - { 0x9F4F2726179A2245, 136, 60 }, - { 0xED63A231D4C4FB27, 162, 68 }, - { 0xB0DE65388CC8ADA8, 189, 76 }, - { 0x83C7088E1AAB65DB, 216, 84 }, - { 0xC45D1DF942711D9A, 242, 92 }, - { 0x924D692CA61BE758, 269, 100 }, - { 0xDA01EE641A708DEA, 295, 108 }, - { 0xA26DA3999AEF774A, 322, 116 }, - { 0xF209787BB47D6B85, 348, 124 }, - { 0xB454E4A179DD1877, 375, 132 }, - { 0x865B86925B9BC5C2, 402, 140 }, - { 0xC83553C5C8965D3D, 428, 148 }, - { 0x952AB45CFA97A0B3, 455, 156 }, - { 0xDE469FBD99A05FE3, 481, 164 }, - { 0xA59BC234DB398C25, 508, 172 }, - { 0xF6C69A72A3989F5C, 534, 180 }, - { 0xB7DCBF5354E9BECE, 561, 188 }, - { 0x88FCF317F22241E2, 588, 196 }, - { 0xCC20CE9BD35C78A5, 614, 204 }, - { 0x98165AF37B2153DF, 641, 212 }, - { 0xE2A0B5DC971F303A, 667, 220 }, - { 0xA8D9D1535CE3B396, 694, 228 }, - { 0xFB9B7CD9A4A7443C, 720, 236 }, - { 0xBB764C4CA7A44410, 747, 244 }, - { 0x8BAB8EEFB6409C1A, 774, 252 }, - { 0xD01FEF10A657842C, 800, 260 }, - { 0x9B10A4E5E9913129, 827, 268 }, - { 0xE7109BFBA19C0C9D, 853, 276 }, - { 0xAC2820D9623BF429, 880, 284 }, - { 0x80444B5E7AA7CF85, 907, 292 }, - { 0xBF21E44003ACDD2D, 933, 300 }, - { 0x8E679C2F5E44FF8F, 960, 308 }, - { 0xD433179D9C8CB841, 986, 316 }, - { 0x9E19DB92B4E31BA9, 1013, 324 }, - } - }; + static constexpr std::array kCachedPowers = + { + { + {0xAB70FE17C79AC6CA, -1060, -300}, + {0xFF77B1FCBEBCDC4F, -1034, -292}, + {0xBE5691EF416BD60C, -1007, -284}, + {0x8DD01FAD907FFC3C, -980, -276}, + {0xD3515C2831559A83, -954, -268}, + {0x9D71AC8FADA6C9B5, -927, -260}, + {0xEA9C227723EE8BCB, -901, -252}, + {0xAECC49914078536D, -874, -244}, + {0x823C12795DB6CE57, -847, -236}, + {0xC21094364DFB5637, -821, -228}, + {0x9096EA6F3848984F, -794, -220}, + {0xD77485CB25823AC7, -768, -212}, + {0xA086CFCD97BF97F4, -741, -204}, + {0xEF340A98172AACE5, -715, -196}, + {0xB23867FB2A35B28E, -688, -188}, + {0x84C8D4DFD2C63F3B, -661, -180}, + {0xC5DD44271AD3CDBA, -635, -172}, + {0x936B9FCEBB25C996, -608, -164}, + {0xDBAC6C247D62A584, -582, -156}, + {0xA3AB66580D5FDAF6, -555, -148}, + {0xF3E2F893DEC3F126, -529, -140}, + {0xB5B5ADA8AAFF80B8, -502, -132}, + {0x87625F056C7C4A8B, -475, -124}, + {0xC9BCFF6034C13053, -449, -116}, + {0x964E858C91BA2655, -422, -108}, + {0xDFF9772470297EBD, -396, -100}, + {0xA6DFBD9FB8E5B88F, -369, -92}, + {0xF8A95FCF88747D94, -343, -84}, + {0xB94470938FA89BCF, -316, -76}, + {0x8A08F0F8BF0F156B, -289, -68}, + {0xCDB02555653131B6, -263, -60}, + {0x993FE2C6D07B7FAC, -236, -52}, + {0xE45C10C42A2B3B06, -210, -44}, + {0xAA242499697392D3, -183, -36}, + {0xFD87B5F28300CA0E, -157, -28}, + {0xBCE5086492111AEB, -130, -20}, + {0x8CBCCC096F5088CC, -103, -12}, + {0xD1B71758E219652C, -77, -4}, + {0x9C40000000000000, -50, 4}, + {0xE8D4A51000000000, -24, 12}, + {0xAD78EBC5AC620000, 3, 20}, + {0x813F3978F8940984, 30, 28}, + {0xC097CE7BC90715B3, 56, 36}, + {0x8F7E32CE7BEA5C70, 83, 44}, + {0xD5D238A4ABE98068, 109, 52}, + {0x9F4F2726179A2245, 136, 60}, + {0xED63A231D4C4FB27, 162, 68}, + {0xB0DE65388CC8ADA8, 189, 76}, + {0x83C7088E1AAB65DB, 216, 84}, + {0xC45D1DF942711D9A, 242, 92}, + {0x924D692CA61BE758, 269, 100}, + {0xDA01EE641A708DEA, 295, 108}, + {0xA26DA3999AEF774A, 322, 116}, + {0xF209787BB47D6B85, 348, 124}, + {0xB454E4A179DD1877, 375, 132}, + {0x865B86925B9BC5C2, 402, 140}, + {0xC83553C5C8965D3D, 428, 148}, + {0x952AB45CFA97A0B3, 455, 156}, + {0xDE469FBD99A05FE3, 481, 164}, + {0xA59BC234DB398C25, 508, 172}, + {0xF6C69A72A3989F5C, 534, 180}, + {0xB7DCBF5354E9BECE, 561, 188}, + {0x88FCF317F22241E2, 588, 196}, + {0xCC20CE9BD35C78A5, 614, 204}, + {0x98165AF37B2153DF, 641, 212}, + {0xE2A0B5DC971F303A, 667, 220}, + {0xA8D9D1535CE3B396, 694, 228}, + {0xFB9B7CD9A4A7443C, 720, 236}, + {0xBB764C4CA7A44410, 747, 244}, + {0x8BAB8EEFB6409C1A, 774, 252}, + {0xD01FEF10A657842C, 800, 260}, + {0x9B10A4E5E9913129, 827, 268}, + {0xE7109BFBA19C0C9D, 853, 276}, + {0xAC2820D9623BF429, 880, 284}, + {0x80444B5E7AA7CF85, 907, 292}, + {0xBF21E44003ACDD2D, 933, 300}, + {0x8E679C2F5E44FF8F, 960, 308}, + {0xD433179D9C8CB841, 986, 316}, + {0x9E19DB92B4E31BA9, 1013, 324}, + } + }; - // This computation gives exactly the same results for k as - // k = ceil((kAlpha - e - 1) * 0.30102999566398114) - // for |e| <= 1500, but doesn't require floating-point operations. - // NB: log_10(2) ~= 78913 / 2^18 - JSON_ASSERT(e >= -1500); - JSON_ASSERT(e <= 1500); - const int f = kAlpha - e - 1; - const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + // This computation gives exactly the same results for k as + // k = ceil((kAlpha - e - 1) * 0.30102999566398114) + // for |e| <= 1500, but doesn't require floating-point operations. + // NB: log_10(2) ~= 78913 / 2^18 + JSON_ASSERT(e >= -1500); + JSON_ASSERT(e <= 1500); + const int f = kAlpha - e - 1; + const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); - const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; - JSON_ASSERT(index >= 0); - JSON_ASSERT(static_cast(index) < kCachedPowers.size()); + const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; + JSON_ASSERT(index >= 0); + JSON_ASSERT(static_cast(index) < kCachedPowers.size()); - const cached_power cached = kCachedPowers[static_cast(index)]; - JSON_ASSERT(kAlpha <= cached.e + e + 64); - JSON_ASSERT(kGamma >= cached.e + e + 64); + const cached_power cached = kCachedPowers[static_cast(index)]; + JSON_ASSERT(kAlpha <= cached.e + e + 64); + JSON_ASSERT(kGamma >= cached.e + e + 64); - return cached; -} + return cached; + } /*! For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. For n == 0, returns 1 and sets pow10 := 1. */ -inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) -{ - // LCOV_EXCL_START - if (n >= 1000000000) - { - pow10 = 1000000000; - return 10; - } - // LCOV_EXCL_STOP - else if (n >= 100000000) - { - pow10 = 100000000; - return 9; - } - else if (n >= 10000000) - { - pow10 = 10000000; - return 8; - } - else if (n >= 1000000) - { - pow10 = 1000000; - return 7; - } - else if (n >= 100000) - { - pow10 = 100000; - return 6; - } - else if (n >= 10000) - { - pow10 = 10000; - return 5; - } - else if (n >= 1000) - { - pow10 = 1000; - return 4; - } - else if (n >= 100) - { - pow10 = 100; - return 3; - } - else if (n >= 10) - { - pow10 = 10; - return 2; - } - else - { - pow10 = 1; - return 1; - } -} + inline int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10) { + // LCOV_EXCL_START + if (n >= 1000000000) { + pow10 = 1000000000; + return 10; + } + // LCOV_EXCL_STOP + else if (n >= 100000000) { + pow10 = 100000000; + return 9; + } else if (n >= 10000000) { + pow10 = 10000000; + return 8; + } else if (n >= 1000000) { + pow10 = 1000000; + return 7; + } else if (n >= 100000) { + pow10 = 100000; + return 6; + } else if (n >= 10000) { + pow10 = 10000; + return 5; + } else if (n >= 1000) { + pow10 = 1000; + return 4; + } else if (n >= 100) { + pow10 = 100; + return 3; + } else if (n >= 10) { + pow10 = 10; + return 2; + } else { + pow10 = 1; + return 1; + } + } -inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, - std::uint64_t rest, std::uint64_t ten_k) -{ - JSON_ASSERT(len >= 1); - JSON_ASSERT(dist <= delta); - JSON_ASSERT(rest <= delta); - JSON_ASSERT(ten_k > 0); + inline void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, + std::uint64_t rest, std::uint64_t ten_k) { + JSON_ASSERT(len >= 1); + JSON_ASSERT(dist <= delta); + JSON_ASSERT(rest <= delta); + JSON_ASSERT(ten_k > 0); - // <--------------------------- delta ----> - // <---- dist ---------> - // --------------[------------------+-------------------]-------------- - // M- w M+ - // - // ten_k - // <------> - // <---- rest ----> - // --------------[------------------+----+--------------]-------------- - // w V - // = buf * 10^k - // - // ten_k represents a unit-in-the-last-place in the decimal representation - // stored in buf. - // Decrement buf by ten_k while this takes buf closer to w. + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // ten_k + // <------> + // <---- rest ----> + // --------------[------------------+----+--------------]-------------- + // w V + // = buf * 10^k + // + // ten_k represents a unit-in-the-last-place in the decimal representation + // stored in buf. + // Decrement buf by ten_k while this takes buf closer to w. - // The tests are written in this order to avoid overflow in unsigned - // integer arithmetic. + // The tests are written in this order to avoid overflow in unsigned + // integer arithmetic. - while (rest < dist - && delta - rest >= ten_k - && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) - { - JSON_ASSERT(buf[len - 1] != '0'); - buf[len - 1]--; - rest += ten_k; - } -} + while (rest < dist + && delta - rest >= ten_k + && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) { + JSON_ASSERT(buf[len - 1] != '0'); + buf[len - 1]--; + rest += ten_k; + } + } /*! Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. M- and M+ must be normalized and share the same exponent -60 <= e <= -32. */ -inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, - diyfp M_minus, diyfp w, diyfp M_plus) -{ - static_assert(kAlpha >= -60, "internal error"); - static_assert(kGamma <= -32, "internal error"); + inline void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, + diyfp M_minus, diyfp w, diyfp M_plus) { + static_assert(kAlpha >= -60, "internal error"); + static_assert(kGamma <= -32, "internal error"); - // Generates the digits (and the exponent) of a decimal floating-point - // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's - // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. - // - // <--------------------------- delta ----> - // <---- dist ---------> - // --------------[------------------+-------------------]-------------- - // M- w M+ - // - // Grisu2 generates the digits of M+ from left to right and stops as soon as - // V is in [M-,M+]. + // Generates the digits (and the exponent) of a decimal floating-point + // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's + // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. + // + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // Grisu2 generates the digits of M+ from left to right and stops as soon as + // V is in [M-,M+]. - JSON_ASSERT(M_plus.e >= kAlpha); - JSON_ASSERT(M_plus.e <= kGamma); + JSON_ASSERT(M_plus.e >= kAlpha); + JSON_ASSERT(M_plus.e <= kGamma); - std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) - std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) + std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) + std::uint64_t dist = diyfp::sub(M_plus, w).f; // (significand of (M+ - w ), implicit exponent is e) - // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): - // - // M+ = f * 2^e - // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e - // = ((p1 ) * 2^-e + (p2 )) * 2^e - // = p1 + p2 * 2^e + // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): + // + // M+ = f * 2^e + // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e + // = ((p1 ) * 2^-e + (p2 )) * 2^e + // = p1 + p2 * 2^e - const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); + const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); - auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) - std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e + auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) + std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e - // 1) - // - // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] + // 1) + // + // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] - JSON_ASSERT(p1 > 0); + JSON_ASSERT(p1 > 0); - std::uint32_t pow10; - const int k = find_largest_pow10(p1, pow10); + std::uint32_t pow10; + const int k = find_largest_pow10(p1, pow10); - // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) - // - // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) - // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) - // - // M+ = p1 + p2 * 2^e - // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e - // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e - // = d[k-1] * 10^(k-1) + ( rest) * 2^e - // - // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) - // - // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] - // - // but stop as soon as - // - // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e + // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) + // + // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) + // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) + // + // M+ = p1 + p2 * 2^e + // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e + // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e + // = d[k-1] * 10^(k-1) + ( rest) * 2^e + // + // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) + // + // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] + // + // but stop as soon as + // + // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e - int n = k; - while (n > 0) - { - // Invariants: - // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) - // pow10 = 10^(n-1) <= p1 < 10^n - // - const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) - const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) - // - // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e - // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) - // - JSON_ASSERT(d <= 9); - buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d - // - // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) - // - p1 = r; - n--; - // - // M+ = buffer * 10^n + (p1 + p2 * 2^e) - // pow10 = 10^n - // + int n = k; + while (n > 0) { + // Invariants: + // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) + // pow10 = 10^(n-1) <= p1 < 10^n + // + const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) + const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) + // + // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e + // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) + // + p1 = r; + n--; + // + // M+ = buffer * 10^n + (p1 + p2 * 2^e) + // pow10 = 10^n + // - // Now check if enough digits have been generated. - // Compute - // - // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e - // - // Note: - // Since rest and delta share the same exponent e, it suffices to - // compare the significands. - const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; - if (rest <= delta) - { - // V = buffer * 10^n, with M- <= V <= M+. + // Now check if enough digits have been generated. + // Compute + // + // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e + // + // Note: + // Since rest and delta share the same exponent e, it suffices to + // compare the significands. + const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; + if (rest <= delta) { + // V = buffer * 10^n, with M- <= V <= M+. - decimal_exponent += n; + decimal_exponent += n; - // We may now just stop. But instead look if the buffer could be - // decremented to bring V closer to w. - // - // pow10 = 10^n is now 1 ulp in the decimal representation V. - // The rounding procedure works with diyfp's with an implicit - // exponent of e. - // - // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e - // - const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; - grisu2_round(buffer, length, dist, delta, rest, ten_n); + // We may now just stop. But instead look if the buffer could be + // decremented to bring V closer to w. + // + // pow10 = 10^n is now 1 ulp in the decimal representation V. + // The rounding procedure works with diyfp's with an implicit + // exponent of e. + // + // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e + // + const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; + grisu2_round(buffer, length, dist, delta, rest, ten_n); - return; - } + return; + } - pow10 /= 10; - // - // pow10 = 10^(n-1) <= p1 < 10^n - // Invariants restored. - } + pow10 /= 10; + // + // pow10 = 10^(n-1) <= p1 < 10^n + // Invariants restored. + } - // 2) - // - // The digits of the integral part have been generated: - // - // M+ = d[k-1]...d[1]d[0] + p2 * 2^e - // = buffer + p2 * 2^e - // - // Now generate the digits of the fractional part p2 * 2^e. - // - // Note: - // No decimal point is generated: the exponent is adjusted instead. - // - // p2 actually represents the fraction - // - // p2 * 2^e - // = p2 / 2^-e - // = d[-1] / 10^1 + d[-2] / 10^2 + ... - // - // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) - // - // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m - // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) - // - // using - // - // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) - // = ( d) * 2^-e + ( r) - // - // or - // 10^m * p2 * 2^e = d + r * 2^e - // - // i.e. - // - // M+ = buffer + p2 * 2^e - // = buffer + 10^-m * (d + r * 2^e) - // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e - // - // and stop as soon as 10^-m * r * 2^e <= delta * 2^e + // 2) + // + // The digits of the integral part have been generated: + // + // M+ = d[k-1]...d[1]d[0] + p2 * 2^e + // = buffer + p2 * 2^e + // + // Now generate the digits of the fractional part p2 * 2^e. + // + // Note: + // No decimal point is generated: the exponent is adjusted instead. + // + // p2 actually represents the fraction + // + // p2 * 2^e + // = p2 / 2^-e + // = d[-1] / 10^1 + d[-2] / 10^2 + ... + // + // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) + // + // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m + // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) + // + // using + // + // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) + // = ( d) * 2^-e + ( r) + // + // or + // 10^m * p2 * 2^e = d + r * 2^e + // + // i.e. + // + // M+ = buffer + p2 * 2^e + // = buffer + 10^-m * (d + r * 2^e) + // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e + // + // and stop as soon as 10^-m * r * 2^e <= delta * 2^e - JSON_ASSERT(p2 > delta); + JSON_ASSERT(p2 > delta); - int m = 0; - for (;;) - { - // Invariant: - // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e - // = buffer * 10^-m + 10^-m * (p2 ) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e - // - JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); - p2 *= 10; - const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e - const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e - // - // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) - // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e - // - JSON_ASSERT(d <= 9); - buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d - // - // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e - // - p2 = r; - m++; - // - // M+ = buffer * 10^-m + 10^-m * p2 * 2^e - // Invariant restored. + int m = 0; + for (;;) { + // Invariant: + // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e + // = buffer * 10^-m + 10^-m * (p2 ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e + // + JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); + p2 *= 10; + const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e + const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e + // + // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) + // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + JSON_ASSERT(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + p2 = r; + m++; + // + // M+ = buffer * 10^-m + 10^-m * p2 * 2^e + // Invariant restored. - // Check if enough digits have been generated. - // - // 10^-m * p2 * 2^e <= delta * 2^e - // p2 * 2^e <= 10^m * delta * 2^e - // p2 <= 10^m * delta - delta *= 10; - dist *= 10; - if (p2 <= delta) - { - break; - } - } + // Check if enough digits have been generated. + // + // 10^-m * p2 * 2^e <= delta * 2^e + // p2 * 2^e <= 10^m * delta * 2^e + // p2 <= 10^m * delta + delta *= 10; + dist *= 10; + if (p2 <= delta) { + break; + } + } - // V = buffer * 10^-m, with M- <= V <= M+. + // V = buffer * 10^-m, with M- <= V <= M+. - decimal_exponent -= m; + decimal_exponent -= m; - // 1 ulp in the decimal representation is now 10^-m. - // Since delta and dist are now scaled by 10^m, we need to do the - // same with ulp in order to keep the units in sync. - // - // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e - // - const std::uint64_t ten_m = one.f; - grisu2_round(buffer, length, dist, delta, p2, ten_m); + // 1 ulp in the decimal representation is now 10^-m. + // Since delta and dist are now scaled by 10^m, we need to do the + // same with ulp in order to keep the units in sync. + // + // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e + // + const std::uint64_t ten_m = one.f; + grisu2_round(buffer, length, dist, delta, p2, ten_m); - // By construction this algorithm generates the shortest possible decimal - // number (Loitsch, Theorem 6.2) which rounds back to w. - // For an input number of precision p, at least - // - // N = 1 + ceil(p * log_10(2)) - // - // decimal digits are sufficient to identify all binary floating-point - // numbers (Matula, "In-and-Out conversions"). - // This implies that the algorithm does not produce more than N decimal - // digits. - // - // N = 17 for p = 53 (IEEE double precision) - // N = 9 for p = 24 (IEEE single precision) -} + // By construction this algorithm generates the shortest possible decimal + // number (Loitsch, Theorem 6.2) which rounds back to w. + // For an input number of precision p, at least + // + // N = 1 + ceil(p * log_10(2)) + // + // decimal digits are sufficient to identify all binary floating-point + // numbers (Matula, "In-and-Out conversions"). + // This implies that the algorithm does not produce more than N decimal + // digits. + // + // N = 17 for p = 53 (IEEE double precision) + // N = 9 for p = 24 (IEEE single precision) + } /*! v = buf * 10^decimal_exponent len is the length of the buffer (number of decimal digits) The buffer must be large enough, i.e. >= max_digits10. */ -JSON_HEDLEY_NON_NULL(1) -inline void grisu2(char* buf, int& len, int& decimal_exponent, - diyfp m_minus, diyfp v, diyfp m_plus) -{ - JSON_ASSERT(m_plus.e == m_minus.e); - JSON_ASSERT(m_plus.e == v.e); + JSON_HEDLEY_NON_NULL(1) + inline void grisu2(char *buf, int &len, int &decimal_exponent, + diyfp m_minus, diyfp v, diyfp m_plus) { + JSON_ASSERT(m_plus.e == m_minus.e); + JSON_ASSERT(m_plus.e == v.e); - // --------(-----------------------+-----------------------)-------- (A) - // m- v m+ - // - // --------------------(-----------+-----------------------)-------- (B) - // m- v m+ - // - // First scale v (and m- and m+) such that the exponent is in the range - // [alpha, gamma]. + // --------(-----------------------+-----------------------)-------- (A) + // m- v m+ + // + // --------------------(-----------+-----------------------)-------- (B) + // m- v m+ + // + // First scale v (and m- and m+) such that the exponent is in the range + // [alpha, gamma]. - const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); + const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); - const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k + const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k - // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] - const diyfp w = diyfp::mul(v, c_minus_k); - const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); - const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); + // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] + const diyfp w = diyfp::mul(v, c_minus_k); + const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); + const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); - // ----(---+---)---------------(---+---)---------------(---+---)---- - // w- w w+ - // = c*m- = c*v = c*m+ - // - // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and - // w+ are now off by a small amount. - // In fact: - // - // w - v * 10^k < 1 ulp - // - // To account for this inaccuracy, add resp. subtract 1 ulp. - // - // --------+---[---------------(---+---)---------------]---+-------- - // w- M- w M+ w+ - // - // Now any number in [M-, M+] (bounds included) will round to w when input, - // regardless of how the input rounding algorithm breaks ties. - // - // And digit_gen generates the shortest possible such number in [M-, M+]. - // Note that this does not mean that Grisu2 always generates the shortest - // possible number in the interval (m-, m+). - const diyfp M_minus(w_minus.f + 1, w_minus.e); - const diyfp M_plus (w_plus.f - 1, w_plus.e ); + // ----(---+---)---------------(---+---)---------------(---+---)---- + // w- w w+ + // = c*m- = c*v = c*m+ + // + // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and + // w+ are now off by a small amount. + // In fact: + // + // w - v * 10^k < 1 ulp + // + // To account for this inaccuracy, add resp. subtract 1 ulp. + // + // --------+---[---------------(---+---)---------------]---+-------- + // w- M- w M+ w+ + // + // Now any number in [M-, M+] (bounds included) will round to w when input, + // regardless of how the input rounding algorithm breaks ties. + // + // And digit_gen generates the shortest possible such number in [M-, M+]. + // Note that this does not mean that Grisu2 always generates the shortest + // possible number in the interval (m-, m+). + const diyfp M_minus(w_minus.f + 1, w_minus.e); + const diyfp M_plus(w_plus.f - 1, w_plus.e); - decimal_exponent = -cached.k; // = -(-k) = k + decimal_exponent = -cached.k; // = -(-k) = k - grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); -} + grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); + } /*! v = buf * 10^decimal_exponent len is the length of the buffer (number of decimal digits) The buffer must be large enough, i.e. >= max_digits10. */ -template -JSON_HEDLEY_NON_NULL(1) -void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) -{ - static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, - "internal error: not enough precision"); + template + JSON_HEDLEY_NON_NULL(1) + void grisu2(char *buf, int &len, int &decimal_exponent, FloatType value) { + static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, + "internal error: not enough precision"); - JSON_ASSERT(std::isfinite(value)); - JSON_ASSERT(value > 0); + JSON_ASSERT(std::isfinite(value)); + JSON_ASSERT(value > 0); - // If the neighbors (and boundaries) of 'value' are always computed for double-precision - // numbers, all float's can be recovered using strtod (and strtof). However, the resulting - // decimal representations are not exactly "short". - // - // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) - // says "value is converted to a string as if by std::sprintf in the default ("C") locale" - // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars' - // does. - // On the other hand, the documentation for 'std::to_chars' requires that "parsing the - // representation using the corresponding std::from_chars function recovers value exactly". That - // indicates that single precision floating-point numbers should be recovered using - // 'std::strtof'. - // - // 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 the neighbors (and boundaries) of 'value' are always computed for double-precision + // numbers, all float's can be recovered using strtod (and strtof). However, the resulting + // decimal representations are not exactly "short". + // + // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) + // says "value is converted to a string as if by std::sprintf in the default ("C") locale" + // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars' + // does. + // On the other hand, the documentation for 'std::to_chars' requires that "parsing the + // representation using the corresponding std::from_chars function recovers value exactly". That + // indicates that single precision floating-point numbers should be recovered using + // 'std::strtof'. + // + // 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 - const boundaries w = compute_boundaries(static_cast(value)); + const boundaries w = compute_boundaries(static_cast(value)); #else - const boundaries w = compute_boundaries(value); + const boundaries w = compute_boundaries(value); #endif - grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); -} + grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); + } /*! @brief appends a decimal representation of e to buf @return a pointer to the element following the exponent. @pre -1000 < e < 1000 */ -JSON_HEDLEY_NON_NULL(1) -JSON_HEDLEY_RETURNS_NON_NULL -inline char* append_exponent(char* buf, int e) -{ - JSON_ASSERT(e > -1000); - JSON_ASSERT(e < 1000); + JSON_HEDLEY_NON_NULL(1) + JSON_HEDLEY_RETURNS_NON_NULL + inline char *append_exponent(char *buf, int e) { + JSON_ASSERT(e > -1000); + JSON_ASSERT(e < 1000); - if (e < 0) - { - e = -e; - *buf++ = '-'; - } - else - { - *buf++ = '+'; - } + if (e < 0) { + e = -e; + *buf++ = '-'; + } else { + *buf++ = '+'; + } - auto k = static_cast(e); - if (k < 10) - { - // Always print at least two digits in the exponent. - // This is for compatibility with printf("%g"). - *buf++ = '0'; - *buf++ = static_cast('0' + k); - } - else if (k < 100) - { - *buf++ = static_cast('0' + k / 10); - k %= 10; - *buf++ = static_cast('0' + k); - } - else - { - *buf++ = static_cast('0' + k / 100); - k %= 100; - *buf++ = static_cast('0' + k / 10); - k %= 10; - *buf++ = static_cast('0' + k); - } + auto k = static_cast(e); + if (k < 10) { + // Always print at least two digits in the exponent. + // This is for compatibility with printf("%g"). + *buf++ = '0'; + *buf++ = static_cast('0' + k); + } else if (k < 100) { + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } else { + *buf++ = static_cast('0' + k / 100); + k %= 100; + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } - return buf; -} + return buf; + } /*! @brief prettify v = buf * 10^decimal_exponent @@ -15309,79 +13990,72 @@ notation. Otherwise it will be printed in exponential notation. @pre min_exp < 0 @pre max_exp > 0 */ -JSON_HEDLEY_NON_NULL(1) -JSON_HEDLEY_RETURNS_NON_NULL -inline char* format_buffer(char* buf, int len, int decimal_exponent, - int min_exp, int max_exp) -{ - JSON_ASSERT(min_exp < 0); - JSON_ASSERT(max_exp > 0); + JSON_HEDLEY_NON_NULL(1) + JSON_HEDLEY_RETURNS_NON_NULL + inline char *format_buffer(char *buf, int len, int decimal_exponent, + int min_exp, int max_exp) { + JSON_ASSERT(min_exp < 0); + JSON_ASSERT(max_exp > 0); - const int k = len; - const int n = len + decimal_exponent; + const int k = len; + const int n = len + decimal_exponent; - // v = buf * 10^(n-k) - // k is the length of the buffer (number of decimal digits) - // n is the position of the decimal point relative to the start of the buffer. + // v = buf * 10^(n-k) + // k is the length of the buffer (number of decimal digits) + // n is the position of the decimal point relative to the start of the buffer. - if (k <= n && n <= max_exp) - { - // digits[000] - // len <= max_exp + 2 + if (k <= n && n <= max_exp) { + // digits[000] + // len <= max_exp + 2 - std::memset(buf + k, '0', static_cast(n) - static_cast(k)); - // Make it look like a floating-point number (#362, #378) - buf[n + 0] = '.'; - buf[n + 1] = '0'; - return buf + (static_cast(n) + 2); - } + std::memset(buf + k, '0', static_cast(n) - static_cast(k)); + // Make it look like a floating-point number (#362, #378) + buf[n + 0] = '.'; + buf[n + 1] = '0'; + return buf + (static_cast(n) + 2); + } - if (0 < n && n <= max_exp) - { - // dig.its - // len <= max_digits10 + 1 + if (0 < n && n <= max_exp) { + // dig.its + // len <= max_digits10 + 1 - JSON_ASSERT(k > n); + JSON_ASSERT(k > n); - std::memmove(buf + (static_cast(n) + 1), buf + n, static_cast(k) - static_cast(n)); - buf[n] = '.'; - return buf + (static_cast(k) + 1U); - } + std::memmove(buf + (static_cast(n) + 1), buf + n, static_cast(k) - static_cast(n)); + buf[n] = '.'; + return buf + (static_cast(k) + 1U); + } - if (min_exp < n && n <= 0) - { - // 0.[000]digits - // len <= 2 + (-min_exp - 1) + max_digits10 + if (min_exp < n && n <= 0) { + // 0.[000]digits + // len <= 2 + (-min_exp - 1) + max_digits10 - std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); - buf[0] = '0'; - buf[1] = '.'; - std::memset(buf + 2, '0', static_cast(-n)); - return buf + (2U + static_cast(-n) + static_cast(k)); - } + std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); + buf[0] = '0'; + buf[1] = '.'; + std::memset(buf + 2, '0', static_cast(-n)); + return buf + (2U + static_cast(-n) + static_cast(k)); + } - if (k == 1) - { - // dE+123 - // len <= 1 + 5 + if (k == 1) { + // dE+123 + // len <= 1 + 5 - buf += 1; - } - else - { - // d.igitsE+123 - // len <= max_digits10 + 1 + 5 + buf += 1; + } else { + // d.igitsE+123 + // len <= max_digits10 + 1 + 5 - std::memmove(buf + 2, buf + 1, static_cast(k) - 1); - buf[1] = '.'; - buf += 1 + static_cast(k); - } + std::memmove(buf + 2, buf + 1, static_cast(k) - 1); + buf[1] = '.'; + buf += 1 + static_cast(k); + } - *buf++ = 'e'; - return append_exponent(buf, n - 1); -} + *buf++ = 'e'; + 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). @@ -15393,55 +14067,53 @@ format. Returns an iterator pointing past-the-end of the decimal representation. @note The buffer must be large enough. @note The result is NOT null-terminated. */ -template -JSON_HEDLEY_NON_NULL(1, 2) -JSON_HEDLEY_RETURNS_NON_NULL -char* to_chars(char* first, const char* last, FloatType value) -{ - static_cast(last); // maybe unused - fix warning - JSON_ASSERT(std::isfinite(value)); + template + JSON_HEDLEY_NON_NULL(1, 2) + JSON_HEDLEY_RETURNS_NON_NULL + char *to_chars(char *first, const char *last, FloatType value) { + static_cast(last); // maybe unused - fix warning + JSON_ASSERT(std::isfinite(value)); - // Use signbit(value) instead of (value < 0) since signbit works for -0. - if (std::signbit(value)) - { - value = -value; - *first++ = '-'; - } + // Use signbit(value) instead of (value < 0) since signbit works for -0. + if (std::signbit(value)) { + value = -value; + *first++ = '-'; + } - if (value == 0) // +-0 - { - *first++ = '0'; - // Make it look like a floating-point number (#362, #378) - *first++ = '.'; - *first++ = '0'; - return first; - } + if (value == 0) // +-0 + { + *first++ = '0'; + // Make it look like a floating-point number (#362, #378) + *first++ = '.'; + *first++ = '0'; + return first; + } - JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); + JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); - // Compute v = buffer * 10^decimal_exponent. - // The decimal digits are stored in the buffer, which needs to be interpreted - // as an unsigned decimal integer. - // len is the length of the buffer, i.e. the number of decimal digits. - int len = 0; - int decimal_exponent = 0; - dtoa_impl::grisu2(first, len, decimal_exponent, value); + // Compute v = buffer * 10^decimal_exponent. + // The decimal digits are stored in the buffer, which needs to be interpreted + // as an unsigned decimal integer. + // len is the length of the buffer, i.e. the number of decimal digits. + int len = 0; + int decimal_exponent = 0; + dtoa_impl::grisu2(first, len, decimal_exponent, value); - JSON_ASSERT(len <= std::numeric_limits::max_digits10); + JSON_ASSERT(len <= std::numeric_limits::max_digits10); - // Format the buffer like printf("%.*g", prec, value) - constexpr int kMinExp = -4; - // Use digits10 here to increase compatibility with version 2. - constexpr int kMaxExp = std::numeric_limits::digits10; + // Format the buffer like printf("%.*g", prec, value) + constexpr int kMinExp = -4; + // Use digits10 here to increase compatibility with version 2. + constexpr int kMaxExp = std::numeric_limits::digits10; - JSON_ASSERT(last - first >= kMaxExp + 2); - JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); - JSON_ASSERT(last - first >= std::numeric_limits::max_digits10 + 6); + JSON_ASSERT(last - first >= kMaxExp + 2); + JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); + JSON_ASSERT(last - first >= std::numeric_limits::max_digits10 + 6); - return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); -} + return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); + } -} // namespace detail + } // namespace detail } // namespace nlohmann // #include @@ -15457,58 +14129,53 @@ char* to_chars(char* first, const char* last, FloatType value) // #include -namespace nlohmann -{ -namespace detail -{ +namespace nlohmann { + namespace detail { /////////////////// // serialization // /////////////////// /// how to treat decoding errors -enum class error_handler_t -{ - strict, ///< throw a type_error exception in case of invalid UTF-8 - replace, ///< replace invalid UTF-8 sequences with U+FFFD - ignore ///< ignore invalid UTF-8 sequences -}; + enum class error_handler_t { + strict, ///< throw a type_error exception in case of invalid UTF-8 + replace, ///< replace invalid UTF-8 sequences with U+FFFD + ignore ///< ignore invalid UTF-8 sequences + }; -template -class serializer -{ - using string_t = typename BasicJsonType::string_t; - using number_float_t = typename BasicJsonType::number_float_t; - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using binary_char_t = typename BasicJsonType::binary_t::value_type; - static constexpr std::uint8_t UTF8_ACCEPT = 0; - static constexpr std::uint8_t UTF8_REJECT = 1; + template + class serializer { + using string_t = typename BasicJsonType::string_t; + using number_float_t = typename BasicJsonType::number_float_t; + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using binary_char_t = typename BasicJsonType::binary_t::value_type; + static constexpr std::uint8_t UTF8_ACCEPT = 0; + static constexpr std::uint8_t UTF8_REJECT = 1; - public: - /*! + public: + /*! @param[in] s output stream to serialize to @param[in] ichar indentation character to use @param[in] error_handler_ how to react on decoding errors */ - serializer(output_adapter_t s, const char ichar, - error_handler_t error_handler_ = error_handler_t::strict) - : o(std::move(s)) - , loc(std::localeconv()) - , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->thousands_sep))) - , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->decimal_point))) - , indent_char(ichar) - , indent_string(512, indent_char) - , error_handler(error_handler_) - {} + serializer(output_adapter_t s, const char ichar, + error_handler_t error_handler_ = error_handler_t::strict) + : o(std::move(s)), loc(std::localeconv()), thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits::to_char_type(*(loc->thousands_sep))), + decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits::to_char_type(*(loc->decimal_point))), indent_char(ichar), indent_string(512, indent_char), + error_handler(error_handler_) {} - // delete because of pointer members - serializer(const serializer&) = delete; - serializer& operator=(const serializer&) = delete; - serializer(serializer&&) = delete; - serializer& operator=(serializer&&) = delete; - ~serializer() = default; + // delete because of pointer members + serializer(const serializer &) = delete; - /*! + serializer &operator=(const serializer &) = delete; + + serializer(serializer &&) = delete; + + serializer &operator=(serializer &&) = delete; + + ~serializer() = default; + + /*! @brief internal implementation of the serialization function This function is called by the public member function dump and organizes @@ -15530,277 +14197,234 @@ class serializer @param[in] indent_step the indent level @param[in] current_indent the current indent level (only used internally) */ - void dump(const BasicJsonType& val, - const bool pretty_print, - const bool ensure_ascii, - const unsigned int indent_step, - const unsigned int current_indent = 0) - { - switch (val.m_type) - { - case value_t::object: - { - if (val.m_value.object->empty()) - { - o->write_characters("{}", 2); - return; - } - - if (pretty_print) - { - o->write_characters("{\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - // 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) - { - o->write_characters(indent_string.c_str(), new_indent); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); - o->write_characters(",\n", 2); - } - - // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); - o->write_characters(indent_string.c_str(), new_indent); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); - - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character('}'); - } - else - { - 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) - { - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); - o->write_character(','); - } - - // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); - - o->write_character('}'); - } - - return; - } - - case value_t::array: - { - if (val.m_value.array->empty()) - { - o->write_characters("[]", 2); - return; - } - - if (pretty_print) - { - o->write_characters("[\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) - { - o->write_characters(indent_string.c_str(), new_indent); - dump(*i, true, ensure_ascii, indent_step, new_indent); - o->write_characters(",\n", 2); - } - - // last element - JSON_ASSERT(!val.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); - - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character(']'); - } - else - { - o->write_character('['); - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.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); - - o->write_character(']'); - } - - return; - } - - case value_t::string: - { - o->write_character('\"'); - dump_escaped(*val.m_value.string, ensure_ascii); - o->write_character('\"'); - return; - } - - case value_t::binary: - { - if (pretty_print) - { - o->write_characters("{\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - o->write_characters(indent_string.c_str(), new_indent); - - o->write_characters("\"bytes\": [", 10); - - if (!val.m_value.binary->empty()) - { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) - { - dump_integer(*i); - o->write_characters(", ", 2); + void dump(const BasicJsonType &val, + const bool pretty_print, + const bool ensure_ascii, + const unsigned int indent_step, + const unsigned int current_indent = 0) { + switch (val.m_type) { + case value_t::object: { + if (val.m_value.object->empty()) { + o->write_characters("{}", 2); + return; } - dump_integer(val.m_value.binary->back()); + + if (pretty_print) { + o->write_characters("{\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) { + indent_string.resize(indent_string.size() * 2, ' '); + } + + // 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) { + o->write_characters(indent_string.c_str(), new_indent); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\": ", 3); + dump(i->second, true, ensure_ascii, indent_step, new_indent); + o->write_characters(",\n", 2); + } + + // last element + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + o->write_characters(indent_string.c_str(), new_indent); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\": ", 3); + dump(i->second, true, ensure_ascii, indent_step, new_indent); + + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character('}'); + } else { + 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) { + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\":", 2); + dump(i->second, false, ensure_ascii, indent_step, current_indent); + o->write_character(','); + } + + // last element + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); + o->write_character('\"'); + dump_escaped(i->first, ensure_ascii); + o->write_characters("\":", 2); + dump(i->second, false, ensure_ascii, indent_step, current_indent); + + o->write_character('}'); + } + + return; } - o->write_characters("],\n", 3); - o->write_characters(indent_string.c_str(), new_indent); + case value_t::array: { + if (val.m_value.array->empty()) { + o->write_characters("[]", 2); + return; + } - o->write_characters("\"subtype\": ", 11); - if (val.m_value.binary->has_subtype()) - { - dump_integer(val.m_value.binary->subtype()); + if (pretty_print) { + o->write_characters("[\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) { + indent_string.resize(indent_string.size() * 2, ' '); + } + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) { + o->write_characters(indent_string.c_str(), new_indent); + dump(*i, true, ensure_ascii, indent_step, new_indent); + o->write_characters(",\n", 2); + } + + // last element + JSON_ASSERT(!val.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); + + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character(']'); + } else { + o->write_character('['); + + // first n-1 elements + for (auto i = val.m_value.array->cbegin(); + i != val.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); + + o->write_character(']'); + } + + return; } - else - { + + case value_t::string: { + o->write_character('\"'); + dump_escaped(*val.m_value.string, ensure_ascii); + o->write_character('\"'); + return; + } + + case value_t::binary: { + if (pretty_print) { + o->write_characters("{\n", 2); + + // variable to hold indentation for recursive calls + const auto new_indent = current_indent + indent_step; + if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) { + indent_string.resize(indent_string.size() * 2, ' '); + } + + o->write_characters(indent_string.c_str(), new_indent); + + o->write_characters("\"bytes\": [", 10); + + if (!val.m_value.binary->empty()) { + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) { + dump_integer(*i); + o->write_characters(", ", 2); + } + dump_integer(val.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()) { + dump_integer(val.m_value.binary->subtype()); + } else { + o->write_characters("null", 4); + } + o->write_character('\n'); + o->write_characters(indent_string.c_str(), current_indent); + o->write_character('}'); + } else { + o->write_characters("{\"bytes\":[", 10); + + if (!val.m_value.binary->empty()) { + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) { + dump_integer(*i); + o->write_character(','); + } + dump_integer(val.m_value.binary->back()); + } + + o->write_characters("],\"subtype\":", 12); + if (val.m_value.binary->has_subtype()) { + dump_integer(val.m_value.binary->subtype()); + o->write_character('}'); + } else { + o->write_characters("null}", 5); + } + } + return; + } + + case value_t::boolean: { + if (val.m_value.boolean) { + o->write_characters("true", 4); + } else { + o->write_characters("false", 5); + } + return; + } + + case value_t::number_integer: { + dump_integer(val.m_value.number_integer); + return; + } + + case value_t::number_unsigned: { + dump_integer(val.m_value.number_unsigned); + return; + } + + case value_t::number_float: { + dump_float(val.m_value.number_float); + return; + } + + case value_t::discarded: { + o->write_characters("", 11); + return; + } + + case value_t::null: { o->write_characters("null", 4); - } - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character('}'); - } - else - { - o->write_characters("{\"bytes\":[", 10); - - if (!val.m_value.binary->empty()) - { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) - { - dump_integer(*i); - o->write_character(','); - } - dump_integer(val.m_value.binary->back()); + return; } - o->write_characters("],\"subtype\":", 12); - if (val.m_value.binary->has_subtype()) - { - dump_integer(val.m_value.binary->subtype()); - o->write_character('}'); - } - else - { - o->write_characters("null}", 5); - } + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // LCOV_EXCL_LINE } - return; } - case value_t::boolean: - { - if (val.m_value.boolean) - { - o->write_characters("true", 4); - } - else - { - o->write_characters("false", 5); - } - return; - } - - case value_t::number_integer: - { - dump_integer(val.m_value.number_integer); - return; - } - - case value_t::number_unsigned: - { - dump_integer(val.m_value.number_unsigned); - return; - } - - case value_t::number_float: - { - dump_float(val.m_value.number_float); - return; - } - - case value_t::discarded: - { - o->write_characters("", 11); - return; - } - - case value_t::null: - { - o->write_characters("null", 4); - return; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - } - - private: - /*! + private: + /*! @brief dump escaped string Escape a string by replacing certain special characters by a sequence of an @@ -15814,255 +14438,222 @@ class serializer @complexity Linear in the length of string @a s. */ - void dump_escaped(const string_t& s, const bool ensure_ascii) - { - std::uint32_t codepoint; - std::uint8_t state = UTF8_ACCEPT; - std::size_t bytes = 0; // number of bytes written to string_buffer + void dump_escaped(const string_t &s, const bool ensure_ascii) { + std::uint32_t codepoint; + std::uint8_t state = UTF8_ACCEPT; + std::size_t bytes = 0; // number of bytes written to string_buffer - // number of bytes written at the point of the last valid byte - std::size_t bytes_after_last_accept = 0; - std::size_t undumped_chars = 0; + // number of bytes written at the point of the last valid byte + std::size_t bytes_after_last_accept = 0; + std::size_t undumped_chars = 0; - for (std::size_t i = 0; i < s.size(); ++i) - { - const auto byte = static_cast(s[i]); + for (std::size_t i = 0; i < s.size(); ++i) { + const auto byte = static_cast(s[i]); - switch (decode(state, codepoint, byte)) - { - case UTF8_ACCEPT: // decode found a new code point - { - switch (codepoint) - { - case 0x08: // backspace + switch (decode(state, codepoint, byte)) { + case UTF8_ACCEPT: // decode found a new code point { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'b'; - break; - } - - case 0x09: // horizontal tab - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 't'; - break; - } - - case 0x0A: // newline - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'n'; - break; - } - - case 0x0C: // formfeed - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'f'; - break; - } - - case 0x0D: // carriage return - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'r'; - break; - } - - case 0x22: // quotation mark - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = '\"'; - break; - } - - case 0x5C: // reverse solidus - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = '\\'; - break; - } - - default: - { - // escape control characters (0x00..0x1F) or, if - // ensure_ascii parameter is used, non-ASCII characters - if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) - { - if (codepoint <= 0xFFFF) - { - (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", - static_cast(codepoint)); - bytes += 6; - } - else - { - (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", - static_cast(0xD7C0u + (codepoint >> 10u)), - static_cast(0xDC00u + (codepoint & 0x3FFu))); - bytes += 12; - } - } - else - { - // copy byte to buffer (all previous bytes - // been copied have in default case above) - string_buffer[bytes++] = s[i]; - } - break; - } - } - - // write buffer and reset index; there must be 13 bytes - // left, as this is the maximal number of bytes to be - // written ("\uxxxx\uxxxx\0") for one code point - if (string_buffer.size() - bytes < 13) - { - o->write_characters(string_buffer.data(), bytes); - bytes = 0; - } - - // remember the byte position of this accept - bytes_after_last_accept = bytes; - undumped_chars = 0; - break; - } - - case UTF8_REJECT: // decode found invalid UTF-8 byte - { - switch (error_handler) - { - case error_handler_t::strict: - { - std::string sn(3, '\0'); - (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); - JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); - } - - case error_handler_t::ignore: - case error_handler_t::replace: - { - // in case we saw this character the first time, we - // would like to read it again, because the byte - // may be OK for itself, but just not OK for the - // previous sequence - if (undumped_chars > 0) - { - --i; - } - - // reset length buffer to the last accepted index; - // thus removing/ignoring the invalid characters - bytes = bytes_after_last_accept; - - if (error_handler == error_handler_t::replace) - { - // add a replacement character - if (ensure_ascii) + switch (codepoint) { + case 0x08: // backspace { string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'u'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'd'; - } - else - { - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xEF'); - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBF'); - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBD'); + string_buffer[bytes++] = 'b'; + break; } - // write buffer and reset index; there must be 13 bytes - // left, as this is the maximal number of bytes to be - // written ("\uxxxx\uxxxx\0") for one code point - if (string_buffer.size() - bytes < 13) + case 0x09: // horizontal tab { - o->write_characters(string_buffer.data(), bytes); - bytes = 0; + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 't'; + break; } - bytes_after_last_accept = bytes; + case 0x0A: // newline + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'n'; + break; + } + + case 0x0C: // formfeed + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'f'; + break; + } + + case 0x0D: // carriage return + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'r'; + break; + } + + case 0x22: // quotation mark + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = '\"'; + break; + } + + case 0x5C: // reverse solidus + { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = '\\'; + break; + } + + default: { + // escape control characters (0x00..0x1F) or, if + // ensure_ascii parameter is used, non-ASCII characters + if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) { + if (codepoint <= 0xFFFF) { + (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", + static_cast(codepoint)); + bytes += 6; + } else { + (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", + static_cast(0xD7C0u + (codepoint >> 10u)), + static_cast(0xDC00u + (codepoint & 0x3FFu))); + bytes += 12; + } + } else { + // copy byte to buffer (all previous bytes + // been copied have in default case above) + string_buffer[bytes++] = s[i]; + } + break; + } } - undumped_chars = 0; + // write buffer and reset index; there must be 13 bytes + // left, as this is the maximal number of bytes to be + // written ("\uxxxx\uxxxx\0") for one code point + if (string_buffer.size() - bytes < 13) { + o->write_characters(string_buffer.data(), bytes); + bytes = 0; + } - // continue processing the string - state = UTF8_ACCEPT; + // remember the byte position of this accept + bytes_after_last_accept = bytes; + undumped_chars = 0; + break; + } + + case UTF8_REJECT: // decode found invalid UTF-8 byte + { + switch (error_handler) { + case error_handler_t::strict: { + std::string sn(3, '\0'); + (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); + JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); + } + + case error_handler_t::ignore: + case error_handler_t::replace: { + // in case we saw this character the first time, we + // would like to read it again, because the byte + // may be OK for itself, but just not OK for the + // previous sequence + if (undumped_chars > 0) { + --i; + } + + // reset length buffer to the last accepted index; + // thus removing/ignoring the invalid characters + bytes = bytes_after_last_accept; + + if (error_handler == error_handler_t::replace) { + // add a replacement character + if (ensure_ascii) { + string_buffer[bytes++] = '\\'; + string_buffer[bytes++] = 'u'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'f'; + string_buffer[bytes++] = 'd'; + } else { + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xEF'); + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBF'); + string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBD'); + } + + // write buffer and reset index; there must be 13 bytes + // left, as this is the maximal number of bytes to be + // written ("\uxxxx\uxxxx\0") for one code point + if (string_buffer.size() - bytes < 13) { + o->write_characters(string_buffer.data(), bytes); + bytes = 0; + } + + bytes_after_last_accept = bytes; + } + + undumped_chars = 0; + + // continue processing the string + state = UTF8_ACCEPT; + break; + } + + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // LCOV_EXCL_LINE + } + break; + } + + default: // decode found yet incomplete multi-byte code point + { + if (!ensure_ascii) { + // code point will not be escaped - copy byte to buffer + string_buffer[bytes++] = s[i]; + } + ++undumped_chars; + break; + } + } + } + + // we finished processing the string + if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) { + // write buffer + if (bytes > 0) { + o->write_characters(string_buffer.data(), bytes); + } + } else { + // we finish reading, but do not accept: string was incomplete + switch (error_handler) { + case error_handler_t::strict: { + std::string sn(3, '\0'); + (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); + JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); + } + + case error_handler_t::ignore: { + // write all accepted bytes + o->write_characters(string_buffer.data(), bytes_after_last_accept); + break; + } + + case error_handler_t::replace: { + // write all accepted bytes + o->write_characters(string_buffer.data(), bytes_after_last_accept); + // add a replacement character + if (ensure_ascii) { + o->write_characters("\\ufffd", 6); + } else { + o->write_characters("\xEF\xBF\xBD", 3); + } break; } default: // LCOV_EXCL_LINE JSON_ASSERT(false); // LCOV_EXCL_LINE } - break; - } - - default: // decode found yet incomplete multi-byte code point - { - if (!ensure_ascii) - { - // code point will not be escaped - copy byte to buffer - string_buffer[bytes++] = s[i]; - } - ++undumped_chars; - break; } } - } - // we finished processing the string - if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) - { - // write buffer - if (bytes > 0) - { - o->write_characters(string_buffer.data(), bytes); - } - } - else - { - // we finish reading, but do not accept: string was incomplete - switch (error_handler) - { - case error_handler_t::strict: - { - std::string sn(3, '\0'); - (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); - JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); - } - - case error_handler_t::ignore: - { - // write all accepted bytes - o->write_characters(string_buffer.data(), bytes_after_last_accept); - break; - } - - case error_handler_t::replace: - { - // write all accepted bytes - o->write_characters(string_buffer.data(), bytes_after_last_accept); - // add a replacement character - if (ensure_ascii) - { - o->write_characters("\\ufffd", 6); - } - else - { - o->write_characters("\xEF\xBF\xBD", 3); - } - break; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - } - } - - /*! + /*! @brief count digits Count the number of decimal (base 10) digits for an input unsigned integer. @@ -16070,33 +14661,27 @@ class serializer @param[in] x unsigned integer number to count its digits @return number of decimal digits */ - inline unsigned int count_digits(number_unsigned_t x) noexcept - { - unsigned int n_digits = 1; - for (;;) - { - if (x < 10) - { - return n_digits; + inline unsigned int count_digits(number_unsigned_t x) noexcept { + unsigned int n_digits = 1; + for (;;) { + if (x < 10) { + return n_digits; + } + if (x < 100) { + return n_digits + 1; + } + if (x < 1000) { + return n_digits + 2; + } + if (x < 10000) { + return n_digits + 3; + } + x = x / 10000u; + n_digits += 4; + } } - if (x < 100) - { - return n_digits + 1; - } - if (x < 1000) - { - return n_digits + 2; - } - if (x < 10000) - { - return n_digits + 3; - } - x = x / 10000u; - n_digits += 4; - } - } - /*! + /*! @brief dump an integer Dump a given integer to output stream @a o. Works internally with @@ -16105,90 +14690,81 @@ class serializer @param[in] x integer number (signed or unsigned) to dump @tparam NumberType either @a number_integer_t or @a number_unsigned_t */ - template < typename NumberType, detail::enable_if_t < - std::is_same::value || - std::is_same::value || - std::is_same::value, - int > = 0 > - void dump_integer(NumberType x) - { - static constexpr std::array, 100> digits_to_99 - { - { - {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, - {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, - {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, - {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, - {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, - {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, - {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, - {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, - {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, - {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, + template::value || + std::is_same::value || + std::is_same::value, + int> = 0> + void dump_integer(NumberType x) { + static constexpr std::array, 100> digits_to_99 + { + { + {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, + {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, + {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, + {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, + {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, + {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, + {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, + {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, + {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, + {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, + } + }; + + // special case for "0" + if (x == 0) { + o->write_character('0'); + return; + } + + // use a pointer to fill the buffer + auto buffer_ptr = number_buffer.begin(); + + const bool is_negative = std::is_same::value && !(x >= 0); // see issue #755 + number_unsigned_t abs_value; + + unsigned int n_chars; + + if (is_negative) { + *buffer_ptr = '-'; + abs_value = remove_sign(static_cast(x)); + + // account one more byte for the minus sign + n_chars = 1 + count_digits(abs_value); + } else { + abs_value = static_cast(x); + n_chars = count_digits(abs_value); + } + + // spare 1 byte for '\0' + JSON_ASSERT(n_chars < number_buffer.size() - 1); + + // jump to the end to generate the string from backward + // so we later avoid reversing the result + buffer_ptr += n_chars; + + // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu + // See: https://www.youtube.com/watch?v=o4-CwDo2zpg + while (abs_value >= 100) { + const auto digits_index = static_cast((abs_value % 100)); + abs_value /= 100; + *(--buffer_ptr) = digits_to_99[digits_index][1]; + *(--buffer_ptr) = digits_to_99[digits_index][0]; + } + + if (abs_value >= 10) { + const auto digits_index = static_cast(abs_value); + *(--buffer_ptr) = digits_to_99[digits_index][1]; + *(--buffer_ptr) = digits_to_99[digits_index][0]; + } else { + *(--buffer_ptr) = static_cast('0' + abs_value); + } + + o->write_characters(number_buffer.data(), n_chars); } - }; - // special case for "0" - if (x == 0) - { - o->write_character('0'); - return; - } - - // use a pointer to fill the buffer - auto buffer_ptr = number_buffer.begin(); - - const bool is_negative = std::is_same::value && !(x >= 0); // see issue #755 - number_unsigned_t abs_value; - - unsigned int n_chars; - - if (is_negative) - { - *buffer_ptr = '-'; - abs_value = remove_sign(static_cast(x)); - - // account one more byte for the minus sign - n_chars = 1 + count_digits(abs_value); - } - else - { - abs_value = static_cast(x); - n_chars = count_digits(abs_value); - } - - // spare 1 byte for '\0' - JSON_ASSERT(n_chars < number_buffer.size() - 1); - - // jump to the end to generate the string from backward - // so we later avoid reversing the result - buffer_ptr += n_chars; - - // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu - // See: https://www.youtube.com/watch?v=o4-CwDo2zpg - while (abs_value >= 100) - { - const auto digits_index = static_cast((abs_value % 100)); - abs_value /= 100; - *(--buffer_ptr) = digits_to_99[digits_index][1]; - *(--buffer_ptr) = digits_to_99[digits_index][0]; - } - - if (abs_value >= 10) - { - const auto digits_index = static_cast(abs_value); - *(--buffer_ptr) = digits_to_99[digits_index][1]; - *(--buffer_ptr) = digits_to_99[digits_index][0]; - } - else - { - *(--buffer_ptr) = static_cast('0' + abs_value); - } - - o->write_characters(number_buffer.data(), n_chars); - } - - /*! + /*! @brief dump a floating-point number Dump a given floating-point number to output stream @a o. Works internally @@ -16196,85 +14772,76 @@ class serializer @param[in] x floating-point number to dump */ - void dump_float(number_float_t x) - { - // NaN / inf - if (!std::isfinite(x)) - { - o->write_characters("null", 4); - return; - } + void dump_float(number_float_t x) { + // NaN / inf + if (!std::isfinite(x)) { + o->write_characters("null", 4); + return; + } - // If number_float_t is an IEEE-754 single or double precision number, - // use the Grisu2 algorithm to produce short numbers which are - // guaranteed to round-trip, using strtof and strtod, resp. - // - // NB: The test below works if == . - static constexpr bool is_ieee_single_or_double - = (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 24 && std::numeric_limits::max_exponent == 128) || - (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 53 && std::numeric_limits::max_exponent == 1024); + // If number_float_t is an IEEE-754 single or double precision number, + // use the Grisu2 algorithm to produce short numbers which are + // guaranteed to round-trip, using strtof and strtod, resp. + // + // NB: The test below works if == . + static constexpr bool is_ieee_single_or_double + = (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 24 && std::numeric_limits::max_exponent == 128) || + (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 53 && std::numeric_limits::max_exponent == 1024); - dump_float(x, std::integral_constant()); - } - - void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) - { - char* begin = number_buffer.data(); - char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); - - o->write_characters(begin, static_cast(end - begin)); - } - - void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) - { - // get number of digits for a float -> text -> float round-trip - static constexpr auto d = std::numeric_limits::max_digits10; - - // the actual conversion - std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); - - // negative value indicates an error - JSON_ASSERT(len > 0); - // check if buffer was large enough - JSON_ASSERT(static_cast(len) < number_buffer.size()); - - // erase thousands separator - if (thousands_sep != '\0') - { - const auto end = std::remove(number_buffer.begin(), - number_buffer.begin() + len, thousands_sep); - std::fill(end, number_buffer.end(), '\0'); - JSON_ASSERT((end - number_buffer.begin()) <= len); - len = (end - number_buffer.begin()); - } - - // convert decimal point to '.' - if (decimal_point != '\0' && decimal_point != '.') - { - const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); - if (dec_pos != number_buffer.end()) - { - *dec_pos = '.'; + dump_float(x, std::integral_constant()); } - } - o->write_characters(number_buffer.data(), static_cast(len)); + void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) { + char *begin = number_buffer.data(); + char *end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); - // determine if need to append ".0" - const bool value_is_int_like = - std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, - [](char c) - { - return c == '.' || c == 'e'; - }); + o->write_characters(begin, static_cast(end - begin)); + } - if (value_is_int_like) - { - o->write_characters(".0", 2); - } - } + void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) { + // get number of digits for a float -> text -> float round-trip + static constexpr auto d = std::numeric_limits::max_digits10; - /*! + // the actual conversion + std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); + + // negative value indicates an error + JSON_ASSERT(len > 0); + // check if buffer was large enough + JSON_ASSERT(static_cast(len) < number_buffer.size()); + + // erase thousands separator + if (thousands_sep != '\0') { + const auto end = std::remove(number_buffer.begin(), + number_buffer.begin() + len, thousands_sep); + std::fill(end, number_buffer.end(), '\0'); + JSON_ASSERT((end - number_buffer.begin()) <= len); + len = (end - number_buffer.begin()); + } + + // convert decimal point to '.' + if (decimal_point != '\0' && decimal_point != '.') { + const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); + if (dec_pos != number_buffer.end()) { + *dec_pos = '.'; + } + } + + o->write_characters(number_buffer.data(), static_cast(len)); + + // determine if need to append ".0" + const bool value_is_int_like = + std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, + [](char c) { + return c == '.' || c == 'e'; + }); + + if (value_is_int_like) { + o->write_characters(".0", 2); + } + } + + /*! @brief check whether a string is UTF-8 encoded The function checks each byte of a string whether it is UTF-8 encoded. The @@ -16295,52 +14862,50 @@ class serializer @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ */ - static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept - { - static const std::array utf8d = - { - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF - 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF - 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF - 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF - 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 - 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 - 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 - 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 + static std::uint8_t decode(std::uint8_t &state, std::uint32_t &codep, const std::uint8_t byte) noexcept { + static const std::array utf8d = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF + 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF + 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF + 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF + 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 + 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 + 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 + 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 + } + }; + + const std::uint8_t type = utf8d[byte]; + + codep = (state != UTF8_ACCEPT) + ? (byte & 0x3fu) | (codep << 6u) + : (0xFFu >> type) & (byte); + + std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); + JSON_ASSERT(index < 400); + state = utf8d[index]; + return state; } - }; - const std::uint8_t type = utf8d[byte]; - - codep = (state != UTF8_ACCEPT) - ? (byte & 0x3fu) | (codep << 6u) - : (0xFFu >> type) & (byte); - - std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); - JSON_ASSERT(index < 400); - state = utf8d[index]; - return state; - } - - /* + /* * Overload to make the compiler happy while it is instantiating * dump_integer for number_unsigned_t. * Must never be called. */ - number_unsigned_t remove_sign(number_unsigned_t x) - { - JSON_ASSERT(false); // LCOV_EXCL_LINE - return x; // LCOV_EXCL_LINE - } + number_unsigned_t remove_sign(number_unsigned_t x) { + JSON_ASSERT(false); // LCOV_EXCL_LINE + return x; // LCOV_EXCL_LINE + } - /* + /* * Helper function for dump_integer * * This function takes a negative signed integer and returns its absolute @@ -16349,38 +14914,37 @@ class serializer * absolute values of INT_MIN and INT_MAX are usually not the same. See * #1708 for details. */ - inline number_unsigned_t remove_sign(number_integer_t x) noexcept - { - JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); - return static_cast(-(x + 1)) + 1; - } + inline number_unsigned_t remove_sign(number_integer_t x) noexcept { + JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); + return static_cast(-(x + 1)) + 1; + } - private: - /// the output of the serializer - output_adapter_t o = nullptr; + private: + /// the output of the serializer + output_adapter_t o = nullptr; - /// a (hopefully) large enough character buffer - std::array number_buffer{{}}; + /// a (hopefully) large enough character buffer + std::array number_buffer{{}}; - /// the locale - const std::lconv* loc = nullptr; - /// the locale's thousand separator character - const char thousands_sep = '\0'; - /// the locale's decimal point character - const char decimal_point = '\0'; + /// the locale + const std::lconv *loc = nullptr; + /// the locale's thousand separator character + const char thousands_sep = '\0'; + /// the locale's decimal point character + const char decimal_point = '\0'; - /// string buffer - std::array string_buffer{{}}; + /// string buffer + std::array string_buffer{{}}; - /// the indentation character - const char indent_char; - /// the indentation string - string_t indent_string; + /// the indentation character + const char indent_char; + /// the indentation string + string_t indent_string; - /// error_handler how to react on decoding errors - const error_handler_t error_handler; -}; -} // namespace detail + /// error_handler how to react on decoding errors + const error_handler_t error_handler; + }; + } // namespace detail } // namespace nlohmann // #include @@ -16395,168 +14959,138 @@ class serializer #include // pair #include // vector -namespace nlohmann -{ +namespace nlohmann { /// ordered_map: a minimal map-like container that preserves insertion order /// for use within nlohmann::basic_json -template , - class Allocator = std::allocator>> - struct ordered_map : std::vector, Allocator> -{ - using key_type = Key; - using mapped_type = T; - using Container = std::vector, Allocator>; - using typename Container::iterator; - using typename Container::const_iterator; - using typename Container::size_type; - using typename Container::value_type; + template, + class Allocator = std::allocator>> + struct ordered_map : std::vector, Allocator> { + using key_type = Key; + using mapped_type = T; + using Container = std::vector, Allocator>; + using typename Container::iterator; + using typename Container::const_iterator; + using typename Container::size_type; + using typename Container::value_type; - // Explicit constructors instead of `using Container::Container` - // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) - ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {} - template - ordered_map(It first, It last, const Allocator& alloc = Allocator()) - : Container{first, last, alloc} {} - ordered_map(std::initializer_list init, const Allocator& alloc = Allocator() ) - : Container{init, alloc} {} + // Explicit constructors instead of `using Container::Container` + // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) + ordered_map(const Allocator &alloc = Allocator()) : Container{alloc} {} - std::pair emplace(const key_type& key, T&& t) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return {it, false}; - } - } - Container::emplace_back(key, t); - return {--this->end(), true}; - } + template + ordered_map(It first, It last, const Allocator &alloc = Allocator()) + : Container{first, last, alloc} {} - T& operator[](const Key& key) - { - return emplace(key, T{}).first->second; - } + ordered_map(std::initializer_list init, const Allocator &alloc = Allocator()) + : Container{init, alloc} {} - const T& operator[](const Key& key) const - { - return at(key); - } - - T& at(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it->second; - } - } - - throw std::out_of_range("key not found"); - } - - const T& at(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it->second; - } - } - - throw std::out_of_range("key not found"); - } - - size_type erase(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - // Since we cannot move const Keys, re-construct them in place - for (auto next = it; ++next != this->end(); ++it) - { - it->~value_type(); // Destroy but keep allocation - new (&*it) value_type{std::move(*next)}; + std::pair emplace(const key_type &key, T &&t) { + for (auto it = this->begin(); it != this->end(); ++it) { + if (it->first == key) { + return {it, false}; } - Container::pop_back(); - return 1; } + Container::emplace_back(key, t); + return {--this->end(), true}; } - return 0; - } - iterator erase(iterator pos) - { - auto it = pos; - - // Since we cannot move const Keys, re-construct them in place - for (auto next = it; ++next != this->end(); ++it) - { - it->~value_type(); // Destroy but keep allocation - new (&*it) value_type{std::move(*next)}; + T &operator[](const Key &key) { + return emplace(key, T{}).first->second; } - Container::pop_back(); - return pos; - } - size_type count(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return 1; + const T &operator[](const Key &key) const { + return at(key); + } + + T &at(const Key &key) { + for (auto it = this->begin(); it != this->end(); ++it) { + if (it->first == key) { + return it->second; + } } - } - return 0; - } - iterator find(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it; + throw std::out_of_range("key not found"); + } + + const T &at(const Key &key) const { + for (auto it = this->begin(); it != this->end(); ++it) { + if (it->first == key) { + return it->second; + } } - } - return Container::end(); - } - const_iterator find(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it; + throw std::out_of_range("key not found"); + } + + size_type erase(const Key &key) { + for (auto it = this->begin(); it != this->end(); ++it) { + if (it->first == key) { + // Since we cannot move const Keys, re-construct them in place + for (auto next = it; ++next != this->end(); ++it) { + it->~value_type(); // Destroy but keep allocation + new(&*it) value_type{std::move(*next)}; + } + Container::pop_back(); + return 1; + } } + return 0; } - return Container::end(); - } - std::pair insert( value_type&& value ) - { - return emplace(value.first, std::move(value.second)); - } + iterator erase(iterator pos) { + auto it = pos; - std::pair insert( const value_type& value ) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == value.first) - { - return {it, false}; + // Since we cannot move const Keys, re-construct them in place + for (auto next = it; ++next != this->end(); ++it) { + it->~value_type(); // Destroy but keep allocation + new(&*it) value_type{std::move(*next)}; } + Container::pop_back(); + return pos; } - Container::push_back(value); - return {--this->end(), true}; - } -}; + + size_type count(const Key &key) const { + for (auto it = this->begin(); it != this->end(); ++it) { + if (it->first == key) { + return 1; + } + } + return 0; + } + + iterator find(const Key &key) { + for (auto it = this->begin(); it != this->end(); ++it) { + if (it->first == key) { + return it; + } + } + return Container::end(); + } + + const_iterator find(const Key &key) const { + for (auto it = this->begin(); it != this->end(); ++it) { + if (it->first == key) { + return it; + } + } + return Container::end(); + } + + std::pair insert(value_type &&value) { + return emplace(value.first, std::move(value.second)); + } + + std::pair insert(const value_type &value) { + for (auto it = this->begin(); it != this->end(); ++it) { + if (it->first == value.first) { + return {it, false}; + } + } + Container::push_back(value); + return {--this->end(), true}; + } + }; } // namespace nlohmann @@ -16566,8 +15100,7 @@ template , @see https://github.com/nlohmann @since version 1.0.0 */ -namespace nlohmann -{ +namespace nlohmann { /*! @brief a class to store JSON values @@ -16653,155 +15186,165 @@ Format](http://rfc7159.net/rfc7159) @nosubgrouping */ -NLOHMANN_BASIC_JSON_TPL_DECLARATION -class basic_json -{ - private: - template friend struct detail::external_constructor; - friend ::nlohmann::json_pointer; + NLOHMANN_BASIC_JSON_TPL_DECLARATION + class basic_json { + private: + template friend + struct detail::external_constructor; + friend ::nlohmann::json_pointer; - template - friend class ::nlohmann::detail::parser; - friend ::nlohmann::detail::serializer; - template - friend class ::nlohmann::detail::iter_impl; - template - friend class ::nlohmann::detail::binary_writer; - template - friend class ::nlohmann::detail::binary_reader; - template - friend class ::nlohmann::detail::json_sax_dom_parser; - template - friend class ::nlohmann::detail::json_sax_dom_callback_parser; + template + friend + class ::nlohmann::detail::parser; - /// workaround type for MSVC - using basic_json_t = NLOHMANN_BASIC_JSON_TPL; + friend ::nlohmann::detail::serializer; - // convenience aliases for types residing in namespace detail; - using lexer = ::nlohmann::detail::lexer_base; + template + friend + class ::nlohmann::detail::iter_impl; - template - static ::nlohmann::detail::parser parser( - InputAdapterType adapter, - detail::parser_callback_tcb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false - ) - { - return ::nlohmann::detail::parser(std::move(adapter), - std::move(cb), allow_exceptions, ignore_comments); - } + template + friend + class ::nlohmann::detail::binary_writer; - using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; - template - using internal_iterator = ::nlohmann::detail::internal_iterator; - template - using iter_impl = ::nlohmann::detail::iter_impl; - template - using iteration_proxy = ::nlohmann::detail::iteration_proxy; - template using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator; + template + friend + class ::nlohmann::detail::binary_reader; - template - using output_adapter_t = ::nlohmann::detail::output_adapter_t; + template + friend + class ::nlohmann::detail::json_sax_dom_parser; - template - using binary_reader = ::nlohmann::detail::binary_reader; - template using binary_writer = ::nlohmann::detail::binary_writer; + template + friend + class ::nlohmann::detail::json_sax_dom_callback_parser; - using serializer = ::nlohmann::detail::serializer; + /// workaround type for MSVC + using basic_json_t = NLOHMANN_BASIC_JSON_TPL; - public: - using value_t = detail::value_t; - /// JSON Pointer, see @ref nlohmann::json_pointer - using json_pointer = ::nlohmann::json_pointer; - template - using json_serializer = JSONSerializer; - /// how to treat decoding errors - using error_handler_t = detail::error_handler_t; - /// how to treat CBOR tags - using cbor_tag_handler_t = detail::cbor_tag_handler_t; - /// helper type for initializer lists of basic_json values - using initializer_list_t = std::initializer_list>; + // convenience aliases for types residing in namespace detail; + using lexer = ::nlohmann::detail::lexer_base; - using input_format_t = detail::input_format_t; - /// SAX interface type, see @ref nlohmann::json_sax - using json_sax_t = json_sax; + template + static ::nlohmann::detail::parser parser( + InputAdapterType adapter, + detail::parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false + ) { + return ::nlohmann::detail::parser(std::move(adapter), + std::move(cb), allow_exceptions, ignore_comments); + } - //////////////// - // exceptions // - //////////////// + using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; + template + using internal_iterator = ::nlohmann::detail::internal_iterator; + template + using iter_impl = ::nlohmann::detail::iter_impl; + template + using iteration_proxy = ::nlohmann::detail::iteration_proxy; + template using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator; - /// @name exceptions - /// Classes to implement user-defined exceptions. - /// @{ + template + using output_adapter_t = ::nlohmann::detail::output_adapter_t; - /// @copydoc detail::exception - using exception = detail::exception; - /// @copydoc detail::parse_error - using parse_error = detail::parse_error; - /// @copydoc detail::invalid_iterator - using invalid_iterator = detail::invalid_iterator; - /// @copydoc detail::type_error - using type_error = detail::type_error; - /// @copydoc detail::out_of_range - using out_of_range = detail::out_of_range; - /// @copydoc detail::other_error - using other_error = detail::other_error; + template + using binary_reader = ::nlohmann::detail::binary_reader; + template using binary_writer = ::nlohmann::detail::binary_writer; - /// @} + using serializer = ::nlohmann::detail::serializer; + + public: + using value_t = detail::value_t; + /// JSON Pointer, see @ref nlohmann::json_pointer + using json_pointer = ::nlohmann::json_pointer; + template + using json_serializer = JSONSerializer; + /// how to treat decoding errors + using error_handler_t = detail::error_handler_t; + /// how to treat CBOR tags + using cbor_tag_handler_t = detail::cbor_tag_handler_t; + /// helper type for initializer lists of basic_json values + using initializer_list_t = std::initializer_list>; + + using input_format_t = detail::input_format_t; + /// SAX interface type, see @ref nlohmann::json_sax + using json_sax_t = json_sax; + + //////////////// + // exceptions // + //////////////// + + /// @name exceptions + /// Classes to implement user-defined exceptions. + /// @{ + + /// @copydoc detail::exception + using exception = detail::exception; + /// @copydoc detail::parse_error + using parse_error = detail::parse_error; + /// @copydoc detail::invalid_iterator + using invalid_iterator = detail::invalid_iterator; + /// @copydoc detail::type_error + using type_error = detail::type_error; + /// @copydoc detail::out_of_range + using out_of_range = detail::out_of_range; + /// @copydoc detail::other_error + using other_error = detail::other_error; + + /// @} - ///////////////////// - // container types // - ///////////////////// + ///////////////////// + // container types // + ///////////////////// - /// @name container types - /// The canonic container types to use @ref basic_json like any other STL - /// container. - /// @{ + /// @name container types + /// The canonic container types to use @ref basic_json like any other STL + /// container. + /// @{ - /// the type of elements in a basic_json container - using value_type = basic_json; + /// the type of elements in a basic_json container + using value_type = basic_json; - /// the type of an element reference - using reference = value_type&; - /// the type of an element const reference - using const_reference = const value_type&; + /// the type of an element reference + using reference = value_type &; + /// the type of an element const reference + using const_reference = const value_type &; - /// a type to represent differences between iterators - using difference_type = std::ptrdiff_t; - /// a type to represent container sizes - using size_type = std::size_t; + /// a type to represent differences between iterators + using difference_type = std::ptrdiff_t; + /// a type to represent container sizes + using size_type = std::size_t; - /// the allocator type - using allocator_type = AllocatorType; + /// the allocator type + using allocator_type = AllocatorType; - /// the type of an element pointer - using pointer = typename std::allocator_traits::pointer; - /// the type of an element const pointer - using const_pointer = typename std::allocator_traits::const_pointer; + /// the type of an element pointer + using pointer = typename std::allocator_traits::pointer; + /// the type of an element const pointer + using const_pointer = typename std::allocator_traits::const_pointer; - /// an iterator for a basic_json container - using iterator = iter_impl; - /// a const iterator for a basic_json container - using const_iterator = iter_impl; - /// a reverse iterator for a basic_json container - using reverse_iterator = json_reverse_iterator; - /// a const reverse iterator for a basic_json container - using const_reverse_iterator = json_reverse_iterator; + /// an iterator for a basic_json container + using iterator = iter_impl; + /// a const iterator for a basic_json container + using const_iterator = iter_impl; + /// a reverse iterator for a basic_json container + using reverse_iterator = json_reverse_iterator; + /// a const reverse iterator for a basic_json container + using const_reverse_iterator = json_reverse_iterator; - /// @} + /// @} - /*! + /*! @brief returns the allocator associated with the container */ - static allocator_type get_allocator() - { - return allocator_type(); - } + static allocator_type get_allocator() { + return allocator_type(); + } - /*! + /*! @brief returns version information on the library This function returns a JSON object with information about the library, @@ -16827,26 +15370,25 @@ class basic_json @since 2.1.0 */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json meta() - { - basic_json result; + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json meta() { + basic_json result; - result["copyright"] = "(C) 2013-2020 Niels Lohmann"; - result["name"] = "JSON for Modern C++"; - result["url"] = "https://github.com/nlohmann/json"; - result["version"]["string"] = - std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + - std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + - std::to_string(NLOHMANN_JSON_VERSION_PATCH); - result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; - result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; - result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; + result["copyright"] = "(C) 2013-2020 Niels Lohmann"; + result["name"] = "JSON for Modern C++"; + result["url"] = "https://github.com/nlohmann/json"; + result["version"]["string"] = + std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + + std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + + std::to_string(NLOHMANN_JSON_VERSION_PATCH); + result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; + result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; + result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; #ifdef _WIN32 - result["platform"] = "win32"; + result["platform"] = "win32"; #elif defined __linux__ - result["platform"] = "linux"; + result["platform"] = "linux"; #elif defined __APPLE__ result["platform"] = "apple"; #elif defined __unix__ @@ -16856,13 +15398,14 @@ class basic_json #endif #if defined(__ICC) || defined(__INTEL_COMPILER) - result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; + result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; #elif defined(__clang__) - result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; + result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; #elif defined(__GNUC__) || defined(__GNUG__) - result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; + result["compiler"] = {{"family", "gcc"}, + {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; #elif defined(__HP_cc) || defined(__HP_aCC) - result["compiler"] = "hp" + result["compiler"] = "hp" #elif defined(__IBMCPP__) result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; #elif defined(_MSC_VER) @@ -16876,32 +15419,32 @@ class basic_json #endif #ifdef __cplusplus - result["compiler"]["c++"] = std::to_string(__cplusplus); + result["compiler"]["c++"] = std::to_string(__cplusplus); #else - result["compiler"]["c++"] = "unknown"; + result["compiler"]["c++"] = "unknown"; #endif - return result; - } + return result; + } - /////////////////////////// - // JSON value data types // - /////////////////////////// + /////////////////////////// + // JSON value data types // + /////////////////////////// - /// @name JSON value data types - /// The data types to store a JSON value. These types are derived from - /// the template arguments passed to class @ref basic_json. - /// @{ + /// @name JSON value data types + /// The data types to store a JSON value. These types are derived from + /// the template arguments passed to class @ref basic_json. + /// @{ #if defined(JSON_HAS_CPP_14) - // Use transparent comparator if possible, combined with perfect forwarding - // on find() and count() calls prevents unnecessary string construction. - using object_comparator_t = std::less<>; + // Use transparent comparator if possible, combined with perfect forwarding + // on find() and count() calls prevents unnecessary string construction. + using object_comparator_t = std::less<>; #else - using object_comparator_t = std::less; + using object_comparator_t = std::less; #endif - /*! + /*! @brief a type for an object [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: @@ -16984,13 +15527,13 @@ class basic_json 7159](http://rfc7159.net/rfc7159), because any order implements the specified "unordered" nature of JSON objects. */ - using object_t = ObjectType>>; + using object_t = ObjectType>>; - /*! + /*! @brief a type for an array [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: @@ -17034,9 +15577,9 @@ class basic_json @since version 1.0.0 */ - using array_t = ArrayType>; + using array_t = ArrayType>; - /*! + /*! @brief a type for a string [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: @@ -17087,9 +15630,9 @@ class basic_json @since version 1.0.0 */ - using string_t = StringType; + using string_t = StringType; - /*! + /*! @brief a type for a boolean [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a @@ -17113,9 +15656,9 @@ class basic_json @since version 1.0.0 */ - using boolean_t = BooleanType; + using boolean_t = BooleanType; - /*! + /*! @brief a type for a number (integer) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: @@ -17185,9 +15728,9 @@ class basic_json @since version 1.0.0 */ - using number_integer_t = NumberIntegerType; + using number_integer_t = NumberIntegerType; - /*! + /*! @brief a type for a number (unsigned) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: @@ -17256,9 +15799,9 @@ class basic_json @since version 2.0.0 */ - using number_unsigned_t = NumberUnsignedType; + using number_unsigned_t = NumberUnsignedType; - /*! + /*! @brief a type for a number (floating-point) [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: @@ -17324,9 +15867,9 @@ class basic_json @since version 1.0.0 */ - using number_float_t = NumberFloatType; + using number_float_t = NumberFloatType; - /*! + /*! @brief a type for a packed binary type This type is a type designed to carry binary data that appears in various @@ -17395,34 +15938,32 @@ class basic_json @since version 3.8.0 */ - using binary_t = nlohmann::byte_container_with_subtype; - /// @} + using binary_t = nlohmann::byte_container_with_subtype; + /// @} - private: + private: - /// helper for exception-safe object creation - template - JSON_HEDLEY_RETURNS_NON_NULL - static T* create(Args&& ... args) - { - AllocatorType alloc; - using AllocatorTraits = std::allocator_traits>; + /// helper for exception-safe object creation + template + JSON_HEDLEY_RETURNS_NON_NULL + static T *create(Args &&... args) { + AllocatorType alloc; + using AllocatorTraits = std::allocator_traits>; - auto deleter = [&](T * object) - { - AllocatorTraits::deallocate(alloc, object, 1); - }; - std::unique_ptr object(AllocatorTraits::allocate(alloc, 1), deleter); - AllocatorTraits::construct(alloc, object.get(), std::forward(args)...); - JSON_ASSERT(object != nullptr); - return object.release(); - } + auto deleter = [&](T *object) { + AllocatorTraits::deallocate(alloc, object, 1); + }; + std::unique_ptr object(AllocatorTraits::allocate(alloc, 1), deleter); + AllocatorTraits::construct(alloc, object.get(), std::forward(args)...); + JSON_ASSERT(object != nullptr); + return object.release(); + } - //////////////////////// - // JSON value storage // - //////////////////////// + //////////////////////// + // JSON value storage // + //////////////////////// - /*! + /*! @brief a JSON value The actual storage for a JSON value of the @ref basic_json class. This @@ -17447,258 +15988,223 @@ class basic_json @since version 1.0.0 */ - union json_value - { - /// object (stored with pointer to save storage) - object_t* object; - /// array (stored with pointer to save storage) - array_t* array; - /// string (stored with pointer to save storage) - string_t* string; - /// binary (stored with pointer to save storage) - binary_t* binary; - /// boolean - boolean_t boolean; - /// number (integer) - number_integer_t number_integer; - /// number (unsigned integer) - number_unsigned_t number_unsigned; - /// number (floating-point) - number_float_t number_float; + union json_value { + /// object (stored with pointer to save storage) + object_t *object; + /// array (stored with pointer to save storage) + array_t *array; + /// string (stored with pointer to save storage) + string_t *string; + /// binary (stored with pointer to save storage) + binary_t *binary; + /// boolean + boolean_t boolean; + /// number (integer) + number_integer_t number_integer; + /// number (unsigned integer) + number_unsigned_t number_unsigned; + /// number (floating-point) + number_float_t number_float; - /// default constructor (for null values) - json_value() = default; - /// constructor for booleans - json_value(boolean_t v) noexcept : boolean(v) {} - /// constructor for numbers (integer) - json_value(number_integer_t v) noexcept : number_integer(v) {} - /// constructor for numbers (unsigned) - json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} - /// constructor for numbers (floating-point) - json_value(number_float_t v) noexcept : number_float(v) {} - /// constructor for empty values of a given type - json_value(value_t t) - { - switch (t) - { - case value_t::object: - { - object = create(); - break; - } + /// default constructor (for null values) + json_value() = default; - case value_t::array: - { - array = create(); - break; - } + /// constructor for booleans + json_value(boolean_t v) noexcept: boolean(v) {} - case value_t::string: - { - string = create(""); - break; - } + /// constructor for numbers (integer) + json_value(number_integer_t v) noexcept: number_integer(v) {} - case value_t::binary: - { - binary = create(); - break; - } + /// constructor for numbers (unsigned) + json_value(number_unsigned_t v) noexcept: number_unsigned(v) {} - case value_t::boolean: - { - boolean = boolean_t(false); - break; - } + /// constructor for numbers (floating-point) + json_value(number_float_t v) noexcept: number_float(v) {} - case value_t::number_integer: - { - number_integer = number_integer_t(0); - break; - } - - case value_t::number_unsigned: - { - number_unsigned = number_unsigned_t(0); - break; - } - - case value_t::number_float: - { - number_float = number_float_t(0.0); - break; - } - - case value_t::null: - { - object = nullptr; // silence warning, see #821 - break; - } - - default: - { - object = nullptr; // silence warning, see #821 - if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) - { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1")); // LCOV_EXCL_LINE + /// constructor for empty values of a given type + json_value(value_t t) { + switch (t) { + case value_t::object: { + object = create(); + break; } - break; - } - } - } - /// constructor for strings - json_value(const string_t& value) - { - string = create(value); - } + case value_t::array: { + array = create(); + break; + } - /// constructor for rvalue strings - json_value(string_t&& value) - { - string = create(std::move(value)); - } + case value_t::string: { + string = create(""); + break; + } - /// constructor for objects - json_value(const object_t& value) - { - object = create(value); - } + case value_t::binary: { + binary = create(); + break; + } - /// constructor for rvalue objects - json_value(object_t&& value) - { - object = create(std::move(value)); - } + case value_t::boolean: { + boolean = boolean_t(false); + break; + } - /// constructor for arrays - json_value(const array_t& value) - { - array = create(value); - } + case value_t::number_integer: { + number_integer = number_integer_t(0); + break; + } - /// constructor for rvalue arrays - json_value(array_t&& value) - { - array = create(std::move(value)); - } + case value_t::number_unsigned: { + number_unsigned = number_unsigned_t(0); + break; + } - /// constructor for binary arrays - json_value(const typename binary_t::container_type& value) - { - binary = create(value); - } + case value_t::number_float: { + number_float = number_float_t(0.0); + break; + } - /// constructor for rvalue binary arrays - json_value(typename binary_t::container_type&& value) - { - binary = create(std::move(value)); - } + case value_t::null: { + object = nullptr; // silence warning, see #821 + break; + } - /// constructor for binary arrays (internal type) - json_value(const binary_t& value) - { - binary = create(value); - } - - /// constructor for rvalue binary arrays (internal type) - json_value(binary_t&& value) - { - binary = create(std::move(value)); - } - - void destroy(value_t t) noexcept - { - // flatten the current json_value to a heap-allocated stack - std::vector stack; - - // move the top-level items to stack - if (t == value_t::array) - { - stack.reserve(array->size()); - std::move(array->begin(), array->end(), std::back_inserter(stack)); - } - else if (t == value_t::object) - { - stack.reserve(object->size()); - for (auto&& it : *object) - { - stack.push_back(std::move(it.second)); + default: { + object = nullptr; // silence warning, see #821 + if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) { + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1")); // LCOV_EXCL_LINE + } + break; + } } } - while (!stack.empty()) - { - // move the last item to local variable to be processed - basic_json current_item(std::move(stack.back())); - stack.pop_back(); + /// constructor for strings + json_value(const string_t &value) { + string = create(value); + } - // if current_item is array/object, move - // 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)); + /// constructor for rvalue strings + json_value(string_t &&value) { + string = create(std::move(value)); + } - current_item.m_value.array->clear(); - } - else if (current_item.is_object()) - { - for (auto&& it : *current_item.m_value.object) - { + /// constructor for objects + json_value(const object_t &value) { + object = create(value); + } + + /// constructor for rvalue objects + json_value(object_t &&value) { + object = create(std::move(value)); + } + + /// constructor for arrays + json_value(const array_t &value) { + array = create(value); + } + + /// constructor for rvalue arrays + json_value(array_t &&value) { + array = create(std::move(value)); + } + + /// constructor for binary arrays + json_value(const typename binary_t::container_type &value) { + binary = create(value); + } + + /// constructor for rvalue binary arrays + json_value(typename binary_t::container_type &&value) { + binary = create(std::move(value)); + } + + /// constructor for binary arrays (internal type) + json_value(const binary_t &value) { + binary = create(value); + } + + /// constructor for rvalue binary arrays (internal type) + json_value(binary_t &&value) { + binary = create(std::move(value)); + } + + void destroy(value_t t) noexcept { + // flatten the current json_value to a heap-allocated stack + std::vector stack; + + // move the top-level items to stack + if (t == value_t::array) { + stack.reserve(array->size()); + std::move(array->begin(), array->end(), std::back_inserter(stack)); + } else if (t == value_t::object) { + stack.reserve(object->size()); + for (auto &&it: *object) { stack.push_back(std::move(it.second)); } - - current_item.m_value.object->clear(); } - // it's now safe that current_item get destructed - // since it doesn't have any children - } + while (!stack.empty()) { + // move the last item to local variable to be processed + basic_json current_item(std::move(stack.back())); + stack.pop_back(); - switch (t) - { - case value_t::object: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, object); - std::allocator_traits::deallocate(alloc, object, 1); - break; + // if current_item is array/object, move + // 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)); + + current_item.m_value.array->clear(); + } else if (current_item.is_object()) { + for (auto &&it: *current_item.m_value.object) { + stack.push_back(std::move(it.second)); + } + + current_item.m_value.object->clear(); + } + + // it's now safe that current_item get destructed + // since it doesn't have any children } - case value_t::array: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, array); - std::allocator_traits::deallocate(alloc, array, 1); - break; - } + switch (t) { + case value_t::object: { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, object); + std::allocator_traits::deallocate(alloc, object, 1); + break; + } - case value_t::string: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, string); - std::allocator_traits::deallocate(alloc, string, 1); - break; - } + case value_t::array: { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, array); + std::allocator_traits::deallocate(alloc, array, 1); + break; + } - case value_t::binary: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, binary); - std::allocator_traits::deallocate(alloc, binary, 1); - break; - } + case value_t::string: { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, string); + std::allocator_traits::deallocate(alloc, string, 1); + break; + } - default: - { - break; + case value_t::binary: { + AllocatorType alloc; + std::allocator_traits::destroy(alloc, binary); + std::allocator_traits::deallocate(alloc, binary, 1); + break; + } + + default: { + break; + } } } - } - }; + }; - /*! + /*! @brief checks the class invariants This function asserts the class invariants. It needs to be called at the @@ -17707,20 +16213,19 @@ class basic_json value is changed, because the invariant expresses a relationship between @a m_type and @a m_value. */ - void assert_invariant() 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); - } + void assert_invariant() 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); + } - public: - ////////////////////////// - // JSON parser callback // - ////////////////////////// + public: + ////////////////////////// + // JSON parser callback // + ////////////////////////// - /*! + /*! @brief parser event types The parser callback distinguishes the following events: @@ -17735,9 +16240,9 @@ class basic_json @sa @ref parser_callback_t for more information and examples */ - using parse_event_t = detail::parse_event_t; + using parse_event_t = detail::parse_event_t; - /*! + /*! @brief per-element parser callback type With a parser callback function, the result of parsing a JSON text can be @@ -17786,18 +16291,18 @@ class basic_json @since version 1.0.0 */ - using parser_callback_t = detail::parser_callback_t; + using parser_callback_t = detail::parser_callback_t; - ////////////////// - // constructors // - ////////////////// + ////////////////// + // constructors // + ////////////////// - /// @name constructors and destructors - /// Constructors of class @ref basic_json, copy/move constructor, copy - /// assignment, static functions creating objects, and the destructor. - /// @{ + /// @name constructors and destructors + /// Constructors of class @ref basic_json, copy/move constructor, copy + /// assignment, static functions creating objects, and the destructor. + /// @{ - /*! + /*! @brief create an empty value with a given type Create an empty JSON value with a given type. The value will be default @@ -17827,13 +16332,12 @@ class basic_json @since version 1.0.0 */ - basic_json(const value_t v) - : m_type(v), m_value(v) - { - assert_invariant(); - } + basic_json(const value_t v) + : m_type(v), m_value(v) { + assert_invariant(); + } - /*! + /*! @brief create a null object Create a `null` JSON value. It either takes a null pointer as parameter @@ -17851,13 +16355,12 @@ class basic_json @since version 1.0.0 */ - basic_json(std::nullptr_t = nullptr) noexcept - : basic_json(value_t::null) - { - assert_invariant(); - } + basic_json(std::nullptr_t = nullptr) noexcept + : basic_json(value_t::null) { + assert_invariant(); + } - /*! + /*! @brief create a JSON value This is a "catch all" constructor for all compatible JSON types; that is, @@ -17920,19 +16423,18 @@ class basic_json @since version 2.1.0 */ - template < typename CompatibleType, - typename U = detail::uncvref_t, - detail::enable_if_t < - !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > - basic_json(CompatibleType && val) noexcept(noexcept( - JSONSerializer::to_json(std::declval(), - std::forward(val)))) - { - JSONSerializer::to_json(*this, std::forward(val)); - assert_invariant(); - } + template, + detail::enable_if_t< + !detail::is_basic_json::value && detail::is_compatible_type::value, int> = 0> + basic_json(CompatibleType &&val) noexcept(noexcept( + JSONSerializer::to_json(std::declval(), + std::forward(val)))) { + JSONSerializer::to_json(*this, std::forward(val)); + assert_invariant(); + } - /*! + /*! @brief create a JSON value from an existing one This is a constructor for existing @ref basic_json types. @@ -17958,59 +16460,57 @@ class basic_json @since version 3.2.0 */ - template < typename BasicJsonType, - detail::enable_if_t < - detail::is_basic_json::value&& !std::is_same::value, int > = 0 > - basic_json(const BasicJsonType& val) - { - using other_boolean_t = typename BasicJsonType::boolean_t; - using other_number_float_t = typename BasicJsonType::number_float_t; - using other_number_integer_t = typename BasicJsonType::number_integer_t; - using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using other_string_t = typename BasicJsonType::string_t; - using other_object_t = typename BasicJsonType::object_t; - using other_array_t = typename BasicJsonType::array_t; - using other_binary_t = typename BasicJsonType::binary_t; + template::value && !std::is_same::value, int> = 0> + basic_json(const BasicJsonType &val) { + using other_boolean_t = typename BasicJsonType::boolean_t; + using other_number_float_t = typename BasicJsonType::number_float_t; + using other_number_integer_t = typename BasicJsonType::number_integer_t; + using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using other_string_t = typename BasicJsonType::string_t; + using other_object_t = typename BasicJsonType::object_t; + using other_array_t = typename BasicJsonType::array_t; + using other_binary_t = typename BasicJsonType::binary_t; - switch (val.type()) - { - case value_t::boolean: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_float: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_integer: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_unsigned: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::string: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::object: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::array: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::binary: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::null: - *this = nullptr; - break; - case value_t::discarded: - m_type = value_t::discarded; - break; - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE + switch (val.type()) { + case value_t::boolean: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_float: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_integer: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::number_unsigned: + JSONSerializer::to_json(*this, val.template get()); + break; + case value_t::string: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::object: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::array: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::binary: + JSONSerializer::to_json(*this, val.template get_ref()); + break; + case value_t::null: + *this = nullptr; + break; + case value_t::discarded: + m_type = value_t::discarded; + break; + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // LCOV_EXCL_LINE + } + assert_invariant(); } - assert_invariant(); - } - /*! + /*! @brief create a container (array or object) from an initializer list Creates a JSON value of type array or object from the passed initializer @@ -18084,59 +16584,50 @@ class basic_json @since version 1.0.0 */ - basic_json(initializer_list_t init, - bool type_deduction = true, - value_t manual_type = value_t::array) - { - // check if each element is an array with two elements whose first - // element is a string - bool is_an_object = std::all_of(init.begin(), init.end(), - [](const detail::json_ref& element_ref) - { - return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); - }); + basic_json(initializer_list_t init, + bool type_deduction = true, + value_t manual_type = value_t::array) { + // check if each element is an array with two elements whose first + // element is a string + bool is_an_object = std::all_of(init.begin(), init.end(), + [](const detail::json_ref &element_ref) { + return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); + }); - // adjust type if type deduction is not wanted - if (!type_deduction) - { - // if array is wanted, do not create an object though possible - if (manual_type == value_t::array) - { - is_an_object = false; + // adjust type if type deduction is not wanted + if (!type_deduction) { + // if array is wanted, do not create an object though possible + if (manual_type == value_t::array) { + is_an_object = false; + } + + // if object is wanted but impossible, throw an exception + if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) { + JSON_THROW(type_error::create(301, "cannot create object from initializer list")); + } } - // if object is wanted but impossible, throw an exception - if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) - { - JSON_THROW(type_error::create(301, "cannot create object from initializer list")); + if (is_an_object) { + // the initializer list is a list of pairs -> create object + m_type = value_t::object; + m_value = value_t::object; + + std::for_each(init.begin(), init.end(), [this](const detail::json_ref &element_ref) { + 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])); + }); + } else { + // the initializer list describes an array -> create array + m_type = value_t::array; + m_value.array = create(init.begin(), init.end()); } + + assert_invariant(); } - if (is_an_object) - { - // the initializer list is a list of pairs -> create object - m_type = value_t::object; - m_value = value_t::object; - - std::for_each(init.begin(), init.end(), [this](const detail::json_ref& element_ref) - { - 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])); - }); - } - else - { - // the initializer list describes an array -> create array - m_type = value_t::array; - m_value.array = create(init.begin(), init.end()); - } - - assert_invariant(); - } - - /*! + /*! @brief explicitly create a binary array (without subtype) Creates a JSON binary array value from a given binary container. Binary @@ -18163,16 +16654,15 @@ class basic_json @since version 3.8.0 */ - JSON_HEDLEY_WARN_UNUSED_RESULT - 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; - return res; - } + JSON_HEDLEY_WARN_UNUSED_RESULT + 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; + return res; + } - /*! + /*! @brief explicitly create a binary array (with subtype) Creates a JSON binary array value from a given binary container. Binary @@ -18200,36 +16690,33 @@ class basic_json @since version 3.8.0 */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(const typename binary_t::container_type& init, std::uint8_t subtype) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(init, subtype); - return res; - } + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(const typename binary_t::container_type &init, std::uint8_t subtype) { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = binary_t(init, subtype); + return res; + } - /// @copydoc binary(const typename binary_t::container_type&) - JSON_HEDLEY_WARN_UNUSED_RESULT - 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); - return res; - } + /// @copydoc binary(const typename binary_t::container_type&) + JSON_HEDLEY_WARN_UNUSED_RESULT + 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); + return res; + } - /// @copydoc binary(const typename binary_t::container_type&, std::uint8_t) - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(typename binary_t::container_type&& init, std::uint8_t subtype) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(std::move(init), subtype); - return res; - } + /// @copydoc binary(const typename binary_t::container_type&, std::uint8_t) + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json binary(typename binary_t::container_type &&init, std::uint8_t subtype) { + auto res = basic_json(); + res.m_type = value_t::binary; + res.m_value = binary_t(std::move(init), subtype); + return res; + } - /*! + /*! @brief explicitly create an array from an initializer list Creates a JSON array value from a given initializer list. That is, given a @@ -18266,13 +16753,12 @@ class basic_json @since version 1.0.0 */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json array(initializer_list_t init = {}) - { - return basic_json(init, false, value_t::array); - } + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json array(initializer_list_t init = {}) { + return basic_json(init, false, value_t::array); + } - /*! + /*! @brief explicitly create an object from an initializer list Creates a JSON object value from a given initializer list. The initializer @@ -18310,13 +16796,12 @@ class basic_json @since version 1.0.0 */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json object(initializer_list_t init = {}) - { - return basic_json(init, false, value_t::object); - } + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json object(initializer_list_t init = {}) { + return basic_json(init, false, value_t::object); + } - /*! + /*! @brief construct an array with count copies of given value Constructs a JSON array value by creating @a cnt copies of a passed value. @@ -18338,14 +16823,13 @@ class basic_json @since version 1.0.0 */ - basic_json(size_type cnt, const basic_json& val) - : m_type(value_t::array) - { - m_value.array = create(cnt, val); - assert_invariant(); - } + basic_json(size_type cnt, const basic_json &val) + : m_type(value_t::array) { + m_value.array = create(cnt, val); + assert_invariant(); + } - /*! + /*! @brief construct a JSON container given an iterator range Constructs the JSON value with the contents of the range `[first, last)`. @@ -18400,115 +16884,101 @@ class basic_json @since version 1.0.0 */ - template < class InputIT, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type = 0 > - basic_json(InputIT first, InputIT last) - { - JSON_ASSERT(first.m_object != nullptr); - JSON_ASSERT(last.m_object != nullptr); + template::value || + std::is_same::value, int>::type = 0> + basic_json(InputIT first, InputIT last) { + JSON_ASSERT(first.m_object != nullptr); + JSON_ASSERT(last.m_object != nullptr); - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); - } + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { + JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); + } - // copy type from first iterator - m_type = first.m_object->m_type; + // copy type from first iterator + m_type = first.m_object->m_type; - // check if iterator range is complete for primitive values - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - { - if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() - || !last.m_it.primitive_iterator.is_end())) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); + // check if iterator range is complete for primitive values + switch (m_type) { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: { + if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() + || !last.m_it.primitive_iterator.is_end())) { + JSON_THROW(invalid_iterator::create(204, "iterators out of range")); + } + break; } - break; + + default: + break; } - default: - break; + switch (m_type) { + case value_t::number_integer: { + m_value.number_integer = first.m_object->m_value.number_integer; + break; + } + + case value_t::number_unsigned: { + m_value.number_unsigned = first.m_object->m_value.number_unsigned; + break; + } + + case value_t::number_float: { + m_value.number_float = first.m_object->m_value.number_float; + break; + } + + case value_t::boolean: { + m_value.boolean = first.m_object->m_value.boolean; + break; + } + + case value_t::string: { + m_value = *first.m_object->m_value.string; + break; + } + + case value_t::object: { + m_value.object = create(first.m_it.object_iterator, + last.m_it.object_iterator); + break; + } + + case value_t::array: { + m_value.array = create(first.m_it.array_iterator, + last.m_it.array_iterator); + break; + } + + case value_t::binary: { + m_value = *first.m_object->m_value.binary; + break; + } + + default: + JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + + std::string(first.m_object->type_name()))); + } + + assert_invariant(); } - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = first.m_object->m_value.number_integer; - break; - } - case value_t::number_unsigned: - { - m_value.number_unsigned = first.m_object->m_value.number_unsigned; - break; - } + /////////////////////////////////////// + // other constructors and destructor // + /////////////////////////////////////// - case value_t::number_float: - { - m_value.number_float = first.m_object->m_value.number_float; - break; - } + template, + std::is_same>::value, int> = 0> + basic_json(const JsonRef &ref) : basic_json(ref.moved_or_copied()) {} - case value_t::boolean: - { - m_value.boolean = first.m_object->m_value.boolean; - break; - } - - case value_t::string: - { - m_value = *first.m_object->m_value.string; - break; - } - - case value_t::object: - { - m_value.object = create(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - m_value.array = create(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - case value_t::binary: - { - m_value = *first.m_object->m_value.binary; - break; - } - - default: - JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + - std::string(first.m_object->type_name()))); - } - - assert_invariant(); - } - - - /////////////////////////////////////// - // other constructors and destructor // - /////////////////////////////////////// - - template, - std::is_same>::value, int> = 0 > - basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} - - /*! + /*! @brief copy constructor Creates a copy of a given JSON value. @@ -18533,70 +17003,60 @@ class basic_json @since version 1.0.0 */ - basic_json(const basic_json& other) - : m_type(other.m_type) - { - // check of passed value is valid - other.assert_invariant(); + basic_json(const basic_json &other) + : m_type(other.m_type) { + // check of passed value is valid + other.assert_invariant(); - switch (m_type) - { - case value_t::object: - { - m_value = *other.m_value.object; - break; + switch (m_type) { + case value_t::object: { + m_value = *other.m_value.object; + break; + } + + case value_t::array: { + m_value = *other.m_value.array; + break; + } + + case value_t::string: { + m_value = *other.m_value.string; + break; + } + + case value_t::boolean: { + m_value = other.m_value.boolean; + break; + } + + case value_t::number_integer: { + m_value = other.m_value.number_integer; + break; + } + + case value_t::number_unsigned: { + m_value = other.m_value.number_unsigned; + break; + } + + case value_t::number_float: { + m_value = other.m_value.number_float; + break; + } + + case value_t::binary: { + m_value = *other.m_value.binary; + break; + } + + default: + break; } - case value_t::array: - { - m_value = *other.m_value.array; - break; - } - - case value_t::string: - { - m_value = *other.m_value.string; - break; - } - - case value_t::boolean: - { - m_value = other.m_value.boolean; - break; - } - - case value_t::number_integer: - { - m_value = other.m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value = other.m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value = other.m_value.number_float; - break; - } - - case value_t::binary: - { - m_value = *other.m_value.binary; - break; - } - - default: - break; + assert_invariant(); } - assert_invariant(); - } - - /*! + /*! @brief move constructor Move constructor. Constructs a JSON value with the contents of the given @@ -18622,21 +17082,20 @@ class basic_json @since version 1.0.0 */ - basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) - { - // check that passed value is valid - other.assert_invariant(); + basic_json(basic_json &&other) noexcept + : m_type(std::move(other.m_type)), + m_value(std::move(other.m_value)) { + // check that passed value is valid + other.assert_invariant(); - // invalidate payload - other.m_type = value_t::null; - other.m_value = {}; + // invalidate payload + other.m_type = value_t::null; + other.m_value = {}; - assert_invariant(); - } + assert_invariant(); + } - /*! + /*! @brief copy assignment Copy assignment operator. Copies a JSON value via the "copy and swap" @@ -18659,25 +17118,24 @@ class basic_json @since version 1.0.0 */ - basic_json& operator=(basic_json other) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& + basic_json &operator=(basic_json other) noexcept( + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value && + std::is_nothrow_move_constructible::value && std::is_nothrow_move_assignable::value - ) - { - // check that passed value is valid - other.assert_invariant(); + ) { + // check that passed value is valid + other.assert_invariant(); - using std::swap; - swap(m_type, other.m_type); - swap(m_value, other.m_value); + using std::swap; + swap(m_type, other.m_type); + swap(m_value, other.m_value); - assert_invariant(); - return *this; - } + assert_invariant(); + return *this; + } - /*! + /*! @brief destructor Destroys the JSON value and frees all allocated memory. @@ -18692,24 +17150,23 @@ class basic_json @since version 1.0.0 */ - ~basic_json() noexcept - { - assert_invariant(); - m_value.destroy(m_type); - } + ~basic_json() noexcept { + assert_invariant(); + m_value.destroy(m_type); + } - /// @} + /// @} - public: - /////////////////////// - // object inspection // - /////////////////////// + public: + /////////////////////// + // object inspection // + /////////////////////// - /// @name object inspection - /// Functions to inspect the type of a JSON value. - /// @{ + /// @name object inspection + /// Functions to inspect the type of a JSON value. + /// @{ - /*! + /*! @brief serialization Serialization function for JSON values. The function tries to mimic @@ -18756,27 +17213,23 @@ class basic_json handlers added in version 3.4.0; serialization of binary values added in version 3.8.0. */ - string_t dump(const int indent = -1, - const char indent_char = ' ', - const bool ensure_ascii = false, - const error_handler_t error_handler = error_handler_t::strict) const - { - string_t result; - serializer s(detail::output_adapter(result), indent_char, error_handler); + string_t dump(const int indent = -1, + const char indent_char = ' ', + const bool ensure_ascii = false, + const error_handler_t error_handler = error_handler_t::strict) const { + string_t result; + serializer s(detail::output_adapter(result), indent_char, error_handler); - if (indent >= 0) - { - s.dump(*this, true, ensure_ascii, static_cast(indent)); - } - else - { - s.dump(*this, false, ensure_ascii, 0); + if (indent >= 0) { + s.dump(*this, true, ensure_ascii, static_cast(indent)); + } else { + s.dump(*this, false, ensure_ascii, 0); + } + + return result; } - return result; - } - - /*! + /*! @brief return the type of the JSON value (explicit) Return the type of the JSON value as a value from the @ref value_t @@ -18809,12 +17262,11 @@ class basic_json @since version 1.0.0 */ - constexpr value_t type() const noexcept - { - return m_type; - } + constexpr value_t type() const noexcept { + return m_type; + } - /*! + /*! @brief return whether type is primitive This function returns true if and only if the JSON type is primitive @@ -18840,12 +17292,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_primitive() const noexcept - { - return is_null() || is_string() || is_boolean() || is_number() || is_binary(); - } + constexpr bool is_primitive() const noexcept { + return is_null() || is_string() || is_boolean() || is_number() || is_binary(); + } - /*! + /*! @brief return whether type is structured This function returns true if and only if the JSON type is structured @@ -18867,12 +17318,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_structured() const noexcept - { - return is_array() || is_object(); - } + constexpr bool is_structured() const noexcept { + return is_array() || is_object(); + } - /*! + /*! @brief return whether value is null This function returns true if and only if the JSON value is null. @@ -18889,12 +17339,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_null() const noexcept - { - return m_type == value_t::null; - } + constexpr bool is_null() const noexcept { + return m_type == value_t::null; + } - /*! + /*! @brief return whether value is a boolean This function returns true if and only if the JSON value is a boolean. @@ -18911,12 +17360,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_boolean() const noexcept - { - return m_type == value_t::boolean; - } + constexpr bool is_boolean() const noexcept { + return m_type == value_t::boolean; + } - /*! + /*! @brief return whether value is a number This function returns true if and only if the JSON value is a number. This @@ -18941,12 +17389,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_number() const noexcept - { - return is_number_integer() || is_number_float(); - } + constexpr bool is_number() const noexcept { + return is_number_integer() || is_number_float(); + } - /*! + /*! @brief return whether value is an integer number This function returns true if and only if the JSON value is a signed or @@ -18970,12 +17417,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_number_integer() const noexcept - { - return m_type == value_t::number_integer || m_type == value_t::number_unsigned; - } + constexpr bool is_number_integer() const noexcept { + return m_type == value_t::number_integer || m_type == value_t::number_unsigned; + } - /*! + /*! @brief return whether value is an unsigned integer number This function returns true if and only if the JSON value is an unsigned @@ -18998,12 +17444,11 @@ class basic_json @since version 2.0.0 */ - constexpr bool is_number_unsigned() const noexcept - { - return m_type == value_t::number_unsigned; - } + constexpr bool is_number_unsigned() const noexcept { + return m_type == value_t::number_unsigned; + } - /*! + /*! @brief return whether value is a floating-point number This function returns true if and only if the JSON value is a @@ -19026,12 +17471,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_number_float() const noexcept - { - return m_type == value_t::number_float; - } + constexpr bool is_number_float() const noexcept { + return m_type == value_t::number_float; + } - /*! + /*! @brief return whether value is an object This function returns true if and only if the JSON value is an object. @@ -19048,12 +17492,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_object() const noexcept - { - return m_type == value_t::object; - } + constexpr bool is_object() const noexcept { + return m_type == value_t::object; + } - /*! + /*! @brief return whether value is an array This function returns true if and only if the JSON value is an array. @@ -19070,12 +17513,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_array() const noexcept - { - return m_type == value_t::array; - } + constexpr bool is_array() const noexcept { + return m_type == value_t::array; + } - /*! + /*! @brief return whether value is a string This function returns true if and only if the JSON value is a string. @@ -19092,12 +17534,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_string() const noexcept - { - return m_type == value_t::string; - } + constexpr bool is_string() const noexcept { + return m_type == value_t::string; + } - /*! + /*! @brief return whether value is a binary array This function returns true if and only if the JSON value is a binary array. @@ -19114,12 +17555,11 @@ class basic_json @since version 3.8.0 */ - constexpr bool is_binary() const noexcept - { - return m_type == value_t::binary; - } + constexpr bool is_binary() const noexcept { + return m_type == value_t::binary; + } - /*! + /*! @brief return whether value is discarded This function returns true if and only if the JSON value was discarded @@ -19141,12 +17581,11 @@ class basic_json @since version 1.0.0 */ - constexpr bool is_discarded() const noexcept - { - return m_type == value_t::discarded; - } + constexpr bool is_discarded() const noexcept { + return m_type == value_t::discarded; + } - /*! + /*! @brief return the type of the JSON value (implicit) Implicitly return the type of the JSON value as a value from the @ref @@ -19167,126 +17606,107 @@ class basic_json @since version 1.0.0 */ - constexpr operator value_t() const noexcept - { - return m_type; - } - - /// @} - - private: - ////////////////// - // value access // - ////////////////// - - /// get a boolean (explicit) - boolean_t get_impl(boolean_t* /*unused*/) const - { - if (JSON_HEDLEY_LIKELY(is_boolean())) - { - return m_value.boolean; + constexpr operator value_t() const noexcept { + return m_type; } - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()))); - } + /// @} - /// get a pointer to the value (object) - object_t* get_impl_ptr(object_t* /*unused*/) noexcept - { - return is_object() ? m_value.object : nullptr; - } + private: + ////////////////// + // value access // + ////////////////// - /// get a pointer to the value (object) - constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept - { - return is_object() ? m_value.object : nullptr; - } + /// get a boolean (explicit) + boolean_t get_impl(boolean_t * /*unused*/) const { + if (JSON_HEDLEY_LIKELY(is_boolean())) { + return m_value.boolean; + } - /// get a pointer to the value (array) - array_t* get_impl_ptr(array_t* /*unused*/) noexcept - { - return is_array() ? m_value.array : nullptr; - } + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()))); + } - /// get a pointer to the value (array) - constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept - { - return is_array() ? m_value.array : nullptr; - } + /// get a pointer to the value (object) + object_t *get_impl_ptr(object_t * /*unused*/) noexcept { + return is_object() ? m_value.object : nullptr; + } - /// get a pointer to the value (string) - string_t* get_impl_ptr(string_t* /*unused*/) noexcept - { - return is_string() ? m_value.string : nullptr; - } + /// get a pointer to the value (object) + constexpr const object_t *get_impl_ptr(const object_t * /*unused*/) const noexcept { + return is_object() ? m_value.object : nullptr; + } - /// get a pointer to the value (string) - constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept - { - return is_string() ? m_value.string : nullptr; - } + /// get a pointer to the value (array) + array_t *get_impl_ptr(array_t * /*unused*/) noexcept { + return is_array() ? m_value.array : nullptr; + } - /// get a pointer to the value (boolean) - boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } + /// get a pointer to the value (array) + constexpr const array_t *get_impl_ptr(const array_t * /*unused*/) const noexcept { + return is_array() ? m_value.array : nullptr; + } - /// get a pointer to the value (boolean) - constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } + /// get a pointer to the value (string) + string_t *get_impl_ptr(string_t * /*unused*/) noexcept { + return is_string() ? m_value.string : nullptr; + } - /// get a pointer to the value (integer number) - number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } + /// get a pointer to the value (string) + constexpr const string_t *get_impl_ptr(const string_t * /*unused*/) const noexcept { + return is_string() ? m_value.string : nullptr; + } - /// get a pointer to the value (integer number) - constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } + /// get a pointer to the value (boolean) + boolean_t *get_impl_ptr(boolean_t * /*unused*/) noexcept { + return is_boolean() ? &m_value.boolean : nullptr; + } - /// get a pointer to the value (unsigned number) - number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } + /// get a pointer to the value (boolean) + constexpr const boolean_t *get_impl_ptr(const boolean_t * /*unused*/) const noexcept { + return is_boolean() ? &m_value.boolean : nullptr; + } - /// get a pointer to the value (unsigned number) - constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } + /// get a pointer to the value (integer number) + number_integer_t *get_impl_ptr(number_integer_t * /*unused*/) noexcept { + return is_number_integer() ? &m_value.number_integer : nullptr; + } - /// get a pointer to the value (floating-point number) - number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } + /// get a pointer to the value (integer number) + constexpr const number_integer_t *get_impl_ptr(const number_integer_t * /*unused*/) const noexcept { + return is_number_integer() ? &m_value.number_integer : nullptr; + } - /// get a pointer to the value (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; - } + /// get a pointer to the value (unsigned number) + number_unsigned_t *get_impl_ptr(number_unsigned_t * /*unused*/) noexcept { + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + } - /// get a pointer to the value (binary) - binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept - { - return is_binary() ? m_value.binary : nullptr; - } + /// get a pointer to the value (unsigned number) + constexpr const number_unsigned_t *get_impl_ptr(const number_unsigned_t * /*unused*/) const noexcept { + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; + } - /// get a pointer to the value (binary) - constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept - { - return is_binary() ? m_value.binary : nullptr; - } + /// get a pointer to the value (floating-point number) + number_float_t *get_impl_ptr(number_float_t * /*unused*/) noexcept { + return is_number_float() ? &m_value.number_float : nullptr; + } - /*! + /// get a pointer to the value (floating-point number) + constexpr const number_float_t *get_impl_ptr(const number_float_t * /*unused*/) const noexcept { + return is_number_float() ? &m_value.number_float : nullptr; + } + + /// get a pointer to the value (binary) + binary_t *get_impl_ptr(binary_t * /*unused*/) noexcept { + return is_binary() ? 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; + } + + /*! @brief helper function to implement get_ref() This function helps to implement get_ref() without code duplication for @@ -19297,26 +17717,24 @@ class basic_json @throw type_error.303 if ReferenceType does not match underlying value type of the current JSON */ - template - static ReferenceType get_ref_impl(ThisType& obj) - { - // delegate the call to get_ptr<>() - auto ptr = obj.template get_ptr::type>(); + template + static ReferenceType get_ref_impl(ThisType &obj) { + // delegate the call to get_ptr<>() + auto ptr = obj.template get_ptr::type>(); - if (JSON_HEDLEY_LIKELY(ptr != nullptr)) - { - return *ptr; + if (JSON_HEDLEY_LIKELY(ptr != nullptr)) { + return *ptr; + } + + JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()))); } - JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()))); - } + public: + /// @name value access + /// Direct access to the stored value of a JSON value. + /// @{ - public: - /// @name value access - /// Direct access to the stored value of a JSON value. - /// @{ - - /*! + /*! @brief get special-case overload This overloads avoids a lot of template boilerplate, it can be seen as the @@ -19330,15 +17748,14 @@ class basic_json @since version 2.1.0 */ - template::type, basic_json_t>::value, - int> = 0> - basic_json get() const - { - return *this; - } + template::type, basic_json_t>::value, + int> = 0> + basic_json get() const { + return *this; + } - /*! + /*! @brief get special-case overload This overloads converts the current @ref basic_json in a different @@ -19353,15 +17770,14 @@ class basic_json @since version 3.2.0 */ - template < typename BasicJsonType, detail::enable_if_t < - !std::is_same::value&& - detail::is_basic_json::value, int > = 0 > - BasicJsonType get() const - { - return *this; - } + template::value && + detail::is_basic_json::value, int> = 0> + BasicJsonType get() const { + return *this; + } - /*! + /*! @brief get a value (explicit) Explicit type conversion between the JSON value and a compatible value @@ -19400,29 +17816,28 @@ class basic_json @since version 2.1.0 */ - template < typename ValueTypeCV, typename ValueType = detail::uncvref_t, - detail::enable_if_t < - !detail::is_basic_json::value && - detail::has_from_json::value && - !detail::has_non_default_from_json::value, - int > = 0 > - ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) - { - // we cannot static_assert on ValueTypeCV being non-const, because - // there is support for get(), which is why we - // still need the uncvref - static_assert(!std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - static_assert(std::is_default_constructible::value, - "types must be DefaultConstructible when used with get()"); + template, + detail::enable_if_t< + !detail::is_basic_json::value && + detail::has_from_json::value && + !detail::has_non_default_from_json::value, + int> = 0> + ValueType get() const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), std::declval()))) { + // we cannot static_assert on ValueTypeCV being non-const, because + // there is support for get(), which is why we + // still need the uncvref + static_assert(!std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + static_assert(std::is_default_constructible::value, + "types must be DefaultConstructible when used with get()"); - ValueType ret; - JSONSerializer::from_json(*this, ret); - return ret; - } + ValueType ret; + JSONSerializer::from_json(*this, ret); + return ret; + } - /*! + /*! @brief get a value (explicit); special case Explicit type conversion between the JSON value and a compatible value @@ -19453,19 +17868,18 @@ class basic_json @since version 2.1.0 */ - template < typename ValueTypeCV, typename ValueType = detail::uncvref_t, - detail::enable_if_t < !std::is_same::value && - detail::has_non_default_from_json::value, - int > = 0 > - ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) - { - static_assert(!std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - return JSONSerializer::from_json(*this); - } + template, + detail::enable_if_t::value && + detail::has_non_default_from_json::value, + int> = 0> + ValueType get() const noexcept(noexcept( + JSONSerializer::from_json(std::declval()))) { + static_assert(!std::is_reference::value, + "get() cannot be used with reference types, you might want to use get_ref()"); + return JSONSerializer::from_json(*this); + } - /*! + /*! @brief get a value (explicit) Explicit type conversion between the JSON value and a compatible value. @@ -19498,45 +17912,42 @@ class basic_json @since version 3.3.0 */ - template < typename ValueType, - detail::enable_if_t < - !detail::is_basic_json::value&& - detail::has_from_json::value, - int > = 0 > - ValueType & get_to(ValueType& v) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), v))) - { - JSONSerializer::from_json(*this, v); - return v; - } + template::value && + detail::has_from_json::value, + int> = 0> + ValueType &get_to(ValueType &v) const noexcept(noexcept( + JSONSerializer::from_json(std::declval(), v))) { + JSONSerializer::from_json(*this, v); + return v; + } - // specialization to allow to call get_to with a basic_json value - // see https://github.com/nlohmann/json/issues/2175 - template::value, - int> = 0> - ValueType & get_to(ValueType& v) const - { - v = *this; - return v; - } + // specialization to allow to call get_to with a basic_json value + // see https://github.com/nlohmann/json/issues/2175 + template::value, + int> = 0> + ValueType &get_to(ValueType &v) const { + v = *this; + return v; + } - template < - typename T, std::size_t N, - typename Array = T (&)[N], - detail::enable_if_t < - detail::has_from_json::value, int > = 0 > - Array get_to(T (&v)[N]) const - noexcept(noexcept(JSONSerializer::from_json( - std::declval(), v))) - { - JSONSerializer::from_json(*this, v); - return v; - } + template< + typename T, std::size_t N, + typename Array = T (&)[N], + detail::enable_if_t< + detail::has_from_json::value, int> = 0> + Array get_to(T (&v)[N]) const + noexcept(noexcept(JSONSerializer::from_json( + std::declval(), v))) { + JSONSerializer::from_json(*this, v); + return v; + } - /*! + /*! @brief get a pointer value (implicit) Implicit pointer access to the internally stored JSON value. No copies are @@ -19562,28 +17973,26 @@ class basic_json @since version 1.0.0 */ - template::value, int>::type = 0> - auto get_ptr() noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) - { - // delegate the call to get_impl_ptr<>() - return get_impl_ptr(static_cast(nullptr)); - } + template::value, int>::type = 0> + auto get_ptr() noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) { + // delegate the call to get_impl_ptr<>() + return get_impl_ptr(static_cast(nullptr)); + } - /*! + /*! @brief get a pointer value (implicit) @copydoc get_ptr() */ - template < typename PointerType, typename std::enable_if < - std::is_pointer::value&& - std::is_const::type>::value, int >::type = 0 > - constexpr auto get_ptr() const noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) - { - // delegate the call to get_impl_ptr<>() const - return get_impl_ptr(static_cast(nullptr)); - } + template::value && + std::is_const::type>::value, int>::type = 0> + constexpr auto get_ptr() const noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) { + // delegate the call to get_impl_ptr<>() const + return get_impl_ptr(static_cast(nullptr)); + } - /*! + /*! @brief get a pointer value (explicit) Explicit pointer access to the internally stored JSON value. No copies are @@ -19610,27 +18019,25 @@ class basic_json @since version 1.0.0 */ - template::value, int>::type = 0> - auto get() noexcept -> decltype(std::declval().template get_ptr()) - { - // delegate the call to get_ptr - return get_ptr(); - } + template::value, int>::type = 0> + auto get() noexcept -> decltype(std::declval().template get_ptr()) { + // delegate the call to get_ptr + return get_ptr(); + } - /*! + /*! @brief get a pointer value (explicit) @copydoc get() */ - template::value, int>::type = 0> - constexpr auto get() const noexcept -> decltype(std::declval().template get_ptr()) - { - // delegate the call to get_ptr - return get_ptr(); - } + template::value, int>::type = 0> + constexpr auto get() const noexcept -> decltype(std::declval().template get_ptr()) { + // delegate the call to get_ptr + return get_ptr(); + } - /*! + /*! @brief get a reference value (implicit) Implicit reference access to the internally stored JSON value. No copies @@ -19656,28 +18063,26 @@ class basic_json @since version 1.1.0 */ - template::value, int>::type = 0> - ReferenceType get_ref() - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } + template::value, int>::type = 0> + ReferenceType get_ref() { + // delegate call to get_ref_impl + return get_ref_impl(*this); + } - /*! + /*! @brief get a reference value (implicit) @copydoc get_ref() */ - template < typename ReferenceType, typename std::enable_if < - std::is_reference::value&& - std::is_const::type>::value, int >::type = 0 > - ReferenceType get_ref() const - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } + template::value && + std::is_const::type>::value, int>::type = 0> + ReferenceType get_ref() const { + // delegate call to get_ref_impl + return get_ref_impl(*this); + } - /*! + /*! @brief get a value (implicit) Implicit type conversion between the JSON value and a compatible value. @@ -19706,24 +18111,22 @@ class basic_json @since version 1.0.0 */ - template < typename ValueType, typename std::enable_if < - !std::is_pointer::value&& - !std::is_same>::value&& - !std::is_same::value&& - !detail::is_basic_json::value - && !std::is_same>::value -#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) - && !std::is_same::value -#endif - && detail::is_detected::value - , int >::type = 0 > - JSON_EXPLICIT operator ValueType() const - { - // delegate the call to get<>() const - return get(); - } + template::value && + !std::is_same>::value && + !std::is_same::value && + !detail::is_basic_json::value + && !std::is_same>::value + #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) + && !std::is_same::value + #endif + && detail::is_detected::value, int>::type = 0> + JSON_EXPLICIT operator ValueType() const { + // delegate the call to get<>() const + return get(); + } - /*! + /*! @return reference to the binary value @throw type_error.302 if the value is not binary @@ -19732,39 +18135,35 @@ class basic_json @since version 3.8.0 */ - binary_t& get_binary() - { - if (!is_binary()) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()))); + binary_t &get_binary() { + if (!is_binary()) { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()))); + } + + return *get_ptr(); } - return *get_ptr(); - } + /// @copydoc get_binary() + const binary_t &get_binary() const { + if (!is_binary()) { + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()))); + } - /// @copydoc get_binary() - const binary_t& get_binary() const - { - if (!is_binary()) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()))); + return *get_ptr(); } - return *get_ptr(); - } - - /// @} + /// @} - //////////////////// - // element access // - //////////////////// + //////////////////// + // element access // + //////////////////// - /// @name element access - /// Access to the JSON value. - /// @{ + /// @name element access + /// Access to the JSON value. + /// @{ - /*! + /*! @brief access specified array element with bounds checking Returns a reference to the element at specified location @a idx, with @@ -19790,28 +18189,22 @@ class basic_json written using `at()`. It also demonstrates the different exceptions that can be thrown.,at__size_type} */ - reference at(size_type idx) - { - // at only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + reference at(size_type idx) { + // at only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) { + JSON_TRY { + return m_value.array->at(idx); + } + JSON_CATCH (std::out_of_range &) { + // create better exception explanation + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + } + } else { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); } } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - /*! + /*! @brief access specified array element with bounds checking Returns a const reference to the element at specified location @a idx, @@ -19837,28 +18230,22 @@ class basic_json `at()`. It also demonstrates the different exceptions that can be thrown., at__size_type_const} */ - const_reference at(size_type idx) const - { - // at only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + const_reference at(size_type idx) const { + // at only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) { + JSON_TRY { + return m_value.array->at(idx); + } + JSON_CATCH (std::out_of_range &) { + // create better exception explanation + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + } + } else { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); } } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - /*! + /*! @brief access specified object element with bounds checking Returns a reference to the element at with specified key @a key, with @@ -19888,28 +18275,22 @@ class basic_json written using `at()`. It also demonstrates the different exceptions that can be thrown.,at__object_t_key_type} */ - reference at(const typename object_t::key_type& key) - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); + reference at(const typename object_t::key_type &key) { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) { + JSON_TRY { + return m_value.object->at(key); + } + JSON_CATCH (std::out_of_range &) { + // create better exception explanation + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); + } + } else { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); } } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - /*! + /*! @brief access specified object element with bounds checking Returns a const reference to the element at with specified key @a key, @@ -19939,28 +18320,22 @@ class basic_json `at()`. It also demonstrates the different exceptions that can be thrown., at__object_t_key_type_const} */ - const_reference at(const typename object_t::key_type& key) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); + const_reference at(const typename object_t::key_type &key) const { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) { + JSON_TRY { + return m_value.object->at(key); + } + JSON_CATCH (std::out_of_range &) { + // create better exception explanation + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); + } + } else { + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); } } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - /*! + /*! @brief access specified array element Returns a reference to the element at specified location @a idx. @@ -19985,34 +18360,30 @@ class basic_json @since version 1.0.0 */ - reference operator[](size_type idx) - { - // implicitly convert null value to an empty array - if (is_null()) - { - m_type = value_t::array; - m_value.array = create(); - assert_invariant(); - } - - // operator[] only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // fill up array with null values if given idx is outside range - if (idx >= m_value.array->size()) - { - m_value.array->insert(m_value.array->end(), - idx - m_value.array->size() + 1, - basic_json()); + reference operator[](size_type idx) { + // implicitly convert null value to an empty array + if (is_null()) { + m_type = value_t::array; + m_value.array = create(); + assert_invariant(); } - return m_value.array->operator[](idx); + // operator[] only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) { + // fill up array with null values if given idx is outside range + if (idx >= m_value.array->size()) { + m_value.array->insert(m_value.array->end(), + idx - m_value.array->size() + 1, + basic_json()); + } + + return m_value.array->operator[](idx); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()))); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()))); - } - - /*! + /*! @brief access specified array element Returns a const reference to the element at specified location @a idx. @@ -20031,18 +18402,16 @@ class basic_json @since version 1.0.0 */ - const_reference operator[](size_type idx) const - { - // const operator[] only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - return m_value.array->operator[](idx); + const_reference operator[](size_type idx) const { + // const operator[] only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) { + return m_value.array->operator[](idx); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()))); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()))); - } - - /*! + /*! @brief access specified object element Returns a reference to the element at with specified key @a key. @@ -20069,26 +18438,23 @@ class basic_json @since version 1.0.0 */ - reference operator[](const typename object_t::key_type& key) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); + reference operator[](const typename object_t::key_type &key) { + // implicitly convert null value to an empty object + if (is_null()) { + m_type = value_t::object; + m_value.object = create(); + assert_invariant(); + } + + // operator[] only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) { + return m_value.object->operator[](key); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); } - // operator[] only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->operator[](key); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! + /*! @brief read-only access specified object element Returns a const reference to the element at with specified key @a key. No @@ -20118,19 +18484,17 @@ class basic_json @since version 1.0.0 */ - const_reference operator[](const typename object_t::key_type& key) const - { - // const operator[] only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; + const_reference operator[](const typename object_t::key_type &key) const { + // const operator[] only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) { + JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! + /*! @brief access specified object element Returns a reference to the element at with specified key @a key. @@ -20157,28 +18521,25 @@ class basic_json @since version 1.1.0 */ - template - JSON_HEDLEY_NON_NULL(2) - reference operator[](T* key) - { - // implicitly convert null to object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); + template + JSON_HEDLEY_NON_NULL(2) + reference operator[](T *key) { + // implicitly convert null to object + if (is_null()) { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) { + return m_value.object->operator[](key); + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); } - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->operator[](key); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! + /*! @brief read-only access specified object element Returns a const reference to the element at with specified key @a key. No @@ -20208,21 +18569,19 @@ class basic_json @since version 1.1.0 */ - template - JSON_HEDLEY_NON_NULL(2) - const_reference operator[](T* key) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; + template + JSON_HEDLEY_NON_NULL(2) + const_reference operator[](T *key) const { + // at only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) { + JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); + return m_value.object->find(key)->second; + } + + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! + /*! @brief access specified object element with default value Returns either a copy of an object's element at the specified key @a key @@ -20272,38 +18631,34 @@ class basic_json @since version 1.0.0 */ - // using std::is_convertible in a std::enable_if will fail when using explicit conversions - template < class ValueType, typename std::enable_if < - detail::is_getable::value - && !std::is_same::value, int >::type = 0 > - ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const - { - // at 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(); + // using std::is_convertible in a std::enable_if will fail when using explicit conversions + template::value + && !std::is_same::value, int>::type = 0> + ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const { + // at 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(); + } + + return default_value; } - return default_value; + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); } - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); - } - - /*! + /*! @brief overload for a default value of type const char* @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const */ - string_t value(const typename object_t::key_type& key, const char* default_value) const - { - return value(key, string_t(default_value)); - } + string_t value(const typename object_t::key_type &key, const char *default_value) const { + return value(key, string_t(default_value)); + } - /*! + /*! @brief access specified object element via JSON Pointer with default value Returns either a copy of an object's element at the specified key @a key @@ -20346,38 +18701,33 @@ class basic_json @since version 2.0.2 */ - template::value, int>::type = 0> - ValueType value(const json_pointer& ptr, const ValueType& default_value) const - { - // at 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 default_value; + template::value, int>::type = 0> + ValueType value(const json_pointer &ptr, const ValueType &default_value) const { + // at 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 default_value; + } } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); } - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); - } - - /*! + /*! @brief overload for a default value of type const char* @copydoc basic_json::value(const json_pointer&, ValueType) const */ - JSON_HEDLEY_NON_NULL(3) - string_t value(const json_pointer& ptr, const char* default_value) const - { - return value(ptr, string_t(default_value)); - } + JSON_HEDLEY_NON_NULL(3) + string_t value(const json_pointer &ptr, const char *default_value) const { + return value(ptr, string_t(default_value)); + } - /*! + /*! @brief access the first element Returns a reference to the first element in the container. For a JSON @@ -20402,20 +18752,18 @@ class basic_json @since version 1.0.0 */ - reference front() - { - return *begin(); - } + reference front() { + return *begin(); + } - /*! + /*! @copydoc basic_json::front() */ - const_reference front() const - { - return *cbegin(); - } + const_reference front() const { + return *cbegin(); + } - /*! + /*! @brief access the last element Returns a reference to the last element in the container. For a JSON @@ -20446,24 +18794,22 @@ class basic_json @since version 1.0.0 */ - reference back() - { - auto tmp = end(); - --tmp; - return *tmp; - } + reference back() { + auto tmp = end(); + --tmp; + return *tmp; + } - /*! + /*! @copydoc basic_json::back() */ - const_reference back() const - { - auto tmp = cend(); - --tmp; - return *tmp; - } + const_reference back() const { + auto tmp = cend(); + --tmp; + return *tmp; + } - /*! + /*! @brief remove element given an iterator Removes the element specified by iterator @a pos. The iterator @a pos must @@ -20509,74 +18855,64 @@ class basic_json @since version 1.0.0 */ - template < class IteratorType, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type - = 0 > - IteratorType erase(IteratorType pos) - { - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + template::value || + std::is_same::value, int>::type + = 0> + IteratorType erase(IteratorType pos) { + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + } + + IteratorType result = end(); + + switch (m_type) { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + case value_t::binary: { + if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) { + JSON_THROW(invalid_iterator::create(205, "iterator out of range")); + } + + 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; + } 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; + } + + m_type = value_t::null; + assert_invariant(); + break; + } + + case value_t::object: { + result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); + break; + } + + case value_t::array: { + result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); + break; + } + + default: + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); + } + + return result; } - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - case value_t::binary: - { - if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) - { - JSON_THROW(invalid_iterator::create(205, "iterator out of range")); - } - - 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; - } - 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; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); - break; - } - - default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - - return result; - } - - /*! + /*! @brief remove elements given an iterator range Removes the element specified by the range `[first; last)`. The iterator @@ -20622,77 +18958,67 @@ class basic_json @since version 1.0.0 */ - template < class IteratorType, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type - = 0 > - IteratorType erase(IteratorType first, IteratorType last) - { - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) - { - JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value")); + template::value || + std::is_same::value, int>::type + = 0> + IteratorType erase(IteratorType first, IteratorType last) { + // make sure iterator fits the current value + if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) { + JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value")); + } + + IteratorType result = end(); + + switch (m_type) { + case value_t::boolean: + case value_t::number_float: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::string: + case value_t::binary: { + if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() + || !last.m_it.primitive_iterator.is_end())) { + JSON_THROW(invalid_iterator::create(204, "iterators out of range")); + } + + 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; + } 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; + } + + m_type = value_t::null; + assert_invariant(); + break; + } + + case value_t::object: { + result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, + last.m_it.object_iterator); + break; + } + + case value_t::array: { + result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, + last.m_it.array_iterator); + break; + } + + default: + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); + } + + return result; } - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - case value_t::binary: - { - if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() - || !last.m_it.primitive_iterator.is_end())) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); - } - - 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; - } - 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; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - - return result; - } - - /*! + /*! @brief remove element from a JSON object given a key Removes elements from a JSON object with the key value @a key. @@ -20721,18 +19047,16 @@ class basic_json @since version 1.0.0 */ - size_type erase(const typename object_t::key_type& key) - { - // this erase only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->erase(key); + size_type erase(const typename object_t::key_type &key) { + // this erase only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) { + return m_value.object->erase(key); + } + + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); } - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - - /*! + /*! @brief remove element from a JSON array given an index Removes element from a JSON array at the index @a idx. @@ -20756,35 +19080,30 @@ class basic_json @since version 1.0.0 */ - void erase(const size_type idx) - { - // this erase only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - if (JSON_HEDLEY_UNLIKELY(idx >= size())) - { - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + void erase(const size_type idx) { + // this erase only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) { + if (JSON_HEDLEY_UNLIKELY(idx >= size())) { + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + } + + m_value.array->erase(m_value.array->begin() + static_cast(idx)); + } else { + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); } - - m_value.array->erase(m_value.array->begin() + static_cast(idx)); } - else - { - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - } - /// @} + /// @} - //////////// - // lookup // - //////////// + //////////// + // lookup // + //////////// - /// @name lookup - /// @{ + /// @name lookup + /// @{ - /*! + /*! @brief find an element in a JSON object Finds an element in a JSON object with key equivalent to @a key. If the @@ -20808,37 +19127,33 @@ class basic_json @since version 1.0.0 */ - template - iterator find(KeyT&& key) - { - auto result = end(); + template + iterator find(KeyT &&key) { + auto result = end(); - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); + if (is_object()) { + result.m_it.object_iterator = m_value.object->find(std::forward(key)); + } + + return result; } - return result; - } - - /*! + /*! @brief find an element in a JSON object @copydoc find(KeyT&&) */ - template - const_iterator find(KeyT&& key) const - { - auto result = cend(); + template + const_iterator find(KeyT &&key) const { + auto result = cend(); - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); + if (is_object()) { + result.m_it.object_iterator = m_value.object->find(std::forward(key)); + } + + return result; } - return result; - } - - /*! + /*! @brief returns the number of occurrences of a key in a JSON object Returns the number of elements with key @a key. If ObjectType is the @@ -20859,14 +19174,13 @@ class basic_json @since version 1.0.0 */ - template - size_type count(KeyT&& key) const - { - // return 0 for all nonobject types - return is_object() ? m_value.object->count(std::forward(key)) : 0; - } + template + size_type count(KeyT &&key) const { + // return 0 for all nonobject types + return is_object() ? m_value.object->count(std::forward(key)) : 0; + } - /*! + /*! @brief check the existence of an element in a JSON object Check whether an element exists in a JSON object with key equivalent to @@ -20891,14 +19205,13 @@ class basic_json @since version 3.6.0 */ - template < typename KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value, int >::type = 0 > - bool contains(KeyT && key) const - { - return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); - } + template::type, json_pointer>::value, int>::type = 0> + bool contains(KeyT &&key) const { + return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); + } - /*! + /*! @brief check the existence of an element in a JSON object given a JSON pointer Check whether the given JSON pointer @a ptr can be resolved in the current @@ -20924,22 +19237,21 @@ class basic_json @since version 3.7.0 */ - bool contains(const json_pointer& ptr) const - { - return ptr.contains(this); - } + bool contains(const json_pointer &ptr) const { + return ptr.contains(this); + } - /// @} + /// @} - /////////////// - // iterators // - /////////////// + /////////////// + // iterators // + /////////////// - /// @name iterators - /// @{ + /// @name iterators + /// @{ - /*! + /*! @brief returns an iterator to the first element Returns an iterator to the first element. @@ -20963,22 +19275,20 @@ class basic_json @since version 1.0.0 */ - iterator begin() noexcept - { - iterator result(this); - result.set_begin(); - return result; - } + iterator begin() noexcept { + iterator result(this); + result.set_begin(); + return result; + } - /*! + /*! @copydoc basic_json::cbegin() */ - const_iterator begin() const noexcept - { - return cbegin(); - } + const_iterator begin() const noexcept { + return cbegin(); + } - /*! + /*! @brief returns a const iterator to the first element Returns a const iterator to the first element. @@ -21003,14 +19313,13 @@ class basic_json @since version 1.0.0 */ - const_iterator cbegin() const noexcept - { - const_iterator result(this); - result.set_begin(); - return result; - } + const_iterator cbegin() const noexcept { + const_iterator result(this); + result.set_begin(); + return result; + } - /*! + /*! @brief returns an iterator to one past the last element Returns an iterator to one past the last element. @@ -21034,22 +19343,20 @@ class basic_json @since version 1.0.0 */ - iterator end() noexcept - { - iterator result(this); - result.set_end(); - return result; - } + iterator end() noexcept { + iterator result(this); + result.set_end(); + return result; + } - /*! + /*! @copydoc basic_json::cend() */ - const_iterator end() const noexcept - { - return cend(); - } + const_iterator end() const noexcept { + return cend(); + } - /*! + /*! @brief returns a const iterator to one past the last element Returns a const iterator to one past the last element. @@ -21074,14 +19381,13 @@ class basic_json @since version 1.0.0 */ - const_iterator cend() const noexcept - { - const_iterator result(this); - result.set_end(); - return result; - } + const_iterator cend() const noexcept { + const_iterator result(this); + result.set_end(); + return result; + } - /*! + /*! @brief returns an iterator to the reverse-beginning Returns an iterator to the reverse-beginning; that is, the last element. @@ -21104,20 +19410,18 @@ class basic_json @since version 1.0.0 */ - reverse_iterator rbegin() noexcept - { - return reverse_iterator(end()); - } + reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); + } - /*! + /*! @copydoc basic_json::crbegin() */ - const_reverse_iterator rbegin() const noexcept - { - return crbegin(); - } + const_reverse_iterator rbegin() const noexcept { + return crbegin(); + } - /*! + /*! @brief returns an iterator to the reverse-end Returns an iterator to the reverse-end; that is, one before the first @@ -21141,20 +19445,18 @@ class basic_json @since version 1.0.0 */ - reverse_iterator rend() noexcept - { - return reverse_iterator(begin()); - } + reverse_iterator rend() noexcept { + return reverse_iterator(begin()); + } - /*! + /*! @copydoc basic_json::crend() */ - const_reverse_iterator rend() const noexcept - { - return crend(); - } + const_reverse_iterator rend() const noexcept { + return crend(); + } - /*! + /*! @brief returns a const reverse iterator to the last element Returns a const iterator to the reverse-beginning; that is, the last @@ -21178,12 +19480,11 @@ class basic_json @since version 1.0.0 */ - const_reverse_iterator crbegin() const noexcept - { - return const_reverse_iterator(cend()); - } + const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator(cend()); + } - /*! + /*! @brief returns a const reverse iterator to one before the first Returns a const reverse iterator to the reverse-end; that is, one before @@ -21207,13 +19508,12 @@ class basic_json @since version 1.0.0 */ - const_reverse_iterator crend() const noexcept - { - return const_reverse_iterator(cbegin()); - } + const_reverse_iterator crend() const noexcept { + return const_reverse_iterator(cbegin()); + } - public: - /*! + public: + /*! @brief wrapper to access iterator member functions in range-based for This function allows to access @ref iterator::key() and @ref @@ -21270,22 +19570,20 @@ class basic_json future 4.0.0 of the library. Please use @ref items() instead; that is, replace `json::iterator_wrapper(j)` with `j.items()`. */ - JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) - static iteration_proxy iterator_wrapper(reference ref) noexcept - { - return ref.items(); - } + JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) + static iteration_proxy iterator_wrapper(reference ref) noexcept { + return ref.items(); + } - /*! + /*! @copydoc iterator_wrapper(reference) */ - JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) - static iteration_proxy iterator_wrapper(const_reference ref) noexcept - { - return ref.items(); - } + JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) + static iteration_proxy iterator_wrapper(const_reference ref) noexcept { + return ref.items(); + } - /*! + /*! @brief helper to access iterator member functions in range-based for This function allows to access @ref iterator::key() and @ref @@ -21353,30 +19651,28 @@ class basic_json @since version 3.1.0, structured bindings support since 3.5.0. */ - iteration_proxy items() noexcept - { - return iteration_proxy(*this); - } + iteration_proxy items() noexcept { + return iteration_proxy(*this); + } - /*! + /*! @copydoc items() */ - iteration_proxy items() const noexcept - { - return iteration_proxy(*this); - } + iteration_proxy items() const noexcept { + return iteration_proxy(*this); + } - /// @} + /// @} - ////////////// - // capacity // - ////////////// + ////////////// + // capacity // + ////////////// - /// @name capacity - /// @{ + /// @name capacity + /// @{ - /*! + /*! @brief checks whether the container is empty. Checks if a JSON value has no elements (i.e. whether its @ref size is `0`). @@ -21418,37 +19714,31 @@ class basic_json @since version 1.0.0 */ - bool empty() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return true; - } + bool empty() const noexcept { + switch (m_type) { + case value_t::null: { + // null values are empty + return true; + } - case value_t::array: - { - // delegate call to array_t::empty() - return m_value.array->empty(); - } + case value_t::array: { + // delegate call to array_t::empty() + return m_value.array->empty(); + } - case value_t::object: - { - // delegate call to object_t::empty() - return m_value.object->empty(); - } + case value_t::object: { + // delegate call to object_t::empty() + return m_value.object->empty(); + } - default: - { - // all other types are nonempty - return false; + default: { + // all other types are nonempty + return false; + } } } - } - /*! + /*! @brief returns the number of elements Returns the number of elements in a JSON value. @@ -21491,37 +19781,31 @@ class basic_json @since version 1.0.0 */ - size_type size() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return 0; - } + size_type size() const noexcept { + switch (m_type) { + case value_t::null: { + // null values are empty + return 0; + } - case value_t::array: - { - // delegate call to array_t::size() - return m_value.array->size(); - } + case value_t::array: { + // delegate call to array_t::size() + return m_value.array->size(); + } - case value_t::object: - { - // delegate call to object_t::size() - return m_value.object->size(); - } + case value_t::object: { + // delegate call to object_t::size() + return m_value.object->size(); + } - default: - { - // all other types have size 1 - return 1; + default: { + // all other types have size 1 + return 1; + } } } - } - /*! + /*! @brief returns the maximum possible number of elements Returns the maximum number of elements a JSON value is able to hold due to @@ -21562,41 +19846,36 @@ class basic_json @since version 1.0.0 */ - size_type max_size() const noexcept - { - switch (m_type) - { - case value_t::array: - { - // delegate call to array_t::max_size() - return m_value.array->max_size(); - } + size_type max_size() const noexcept { + switch (m_type) { + case value_t::array: { + // delegate call to array_t::max_size() + return m_value.array->max_size(); + } - case value_t::object: - { - // delegate call to object_t::max_size() - return m_value.object->max_size(); - } + case value_t::object: { + // delegate call to object_t::max_size() + return m_value.object->max_size(); + } - default: - { - // all other types have max_size() == size() - return size(); + default: { + // all other types have max_size() == size() + return size(); + } } } - } - /// @} + /// @} - /////////////// - // modifiers // - /////////////// + /////////////// + // modifiers // + /////////////// - /// @name modifiers - /// @{ + /// @name modifiers + /// @{ - /*! + /*! @brief clears the contents Clears the content of a JSON value and resets it to the default value as @@ -21633,64 +19912,54 @@ class basic_json @since version 1.0.0 */ - void clear() noexcept - { - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = 0; - break; - } + void clear() noexcept { + switch (m_type) { + case value_t::number_integer: { + m_value.number_integer = 0; + break; + } - case value_t::number_unsigned: - { - m_value.number_unsigned = 0; - break; - } + case value_t::number_unsigned: { + m_value.number_unsigned = 0; + break; + } - case value_t::number_float: - { - m_value.number_float = 0.0; - break; - } + case value_t::number_float: { + m_value.number_float = 0.0; + break; + } - case value_t::boolean: - { - m_value.boolean = false; - break; - } + case value_t::boolean: { + m_value.boolean = false; + break; + } - case value_t::string: - { - m_value.string->clear(); - break; - } + case value_t::string: { + m_value.string->clear(); + break; + } - case value_t::binary: - { - m_value.binary->clear(); - break; - } + case value_t::binary: { + m_value.binary->clear(); + break; + } - case value_t::array: - { - m_value.array->clear(); - break; - } + case value_t::array: { + m_value.array->clear(); + break; + } - case value_t::object: - { - m_value.object->clear(); - break; - } + case value_t::object: { + m_value.object->clear(); + break; + } - default: - break; + default: + break; + } } - } - /*! + /*! @brief add an object to an array Appends the given element @a val to the end of the JSON value. If the @@ -21710,72 +19979,64 @@ class basic_json @since version 1.0.0 */ - void push_back(basic_json&& val) - { - // push_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + void push_back(basic_json &&val) { + // push_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + } + + // transform null object into an array + if (is_null()) { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array (move semantics) + m_value.array->push_back(std::move(val)); + // if val is moved from, basic_json move constructor marks it null so we do not call the destructor } - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (move semantics) - m_value.array->push_back(std::move(val)); - // if val is moved from, basic_json move constructor marks it null so we do not call the destructor - } - - /*! + /*! @brief add an object to an array @copydoc push_back(basic_json&&) */ - reference operator+=(basic_json&& val) - { - push_back(std::move(val)); - return *this; - } + reference operator+=(basic_json &&val) { + push_back(std::move(val)); + return *this; + } - /*! + /*! @brief add an object to an array @copydoc push_back(basic_json&&) */ - void push_back(const basic_json& val) - { - // push_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + void push_back(const basic_json &val) { + // push_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + } + + // transform null object into an array + if (is_null()) { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } + + // add element to array + m_value.array->push_back(val); } - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array - m_value.array->push_back(val); - } - - /*! + /*! @brief add an object to an array @copydoc push_back(basic_json&&) */ - reference operator+=(const basic_json& val) - { - push_back(val); - return *this; - } + reference operator+=(const basic_json &val) { + push_back(val); + return *this; + } - /*! + /*! @brief add an object to an object Inserts the given element @a val to the JSON object. If the function is @@ -21795,37 +20056,33 @@ class basic_json @since version 1.0.0 */ - void push_back(const typename object_t::value_type& val) - { - // push_back only works for null objects or objects - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + void push_back(const typename object_t::value_type &val) { + // push_back only works for null objects or objects + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) { + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + } + + // transform null object into an object + if (is_null()) { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // add element to array + m_value.object->insert(val); } - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to array - m_value.object->insert(val); - } - - /*! + /*! @brief add an object to an object @copydoc push_back(const typename object_t::value_type&) */ - reference operator+=(const typename object_t::value_type& val) - { - push_back(val); - return *this; - } + reference operator+=(const typename object_t::value_type &val) { + push_back(val); + return *this; + } - /*! + /*! @brief add an object to an object This function allows to use `push_back` with an initializer list. In case @@ -21850,31 +20107,26 @@ class basic_json @liveexample{The example shows how initializer lists are treated as objects when possible.,push_back__initializer_list} */ - void push_back(initializer_list_t init) - { - if (is_object() && init.size() == 2 && (*init.begin())->is_string()) - { - basic_json&& key = init.begin()->moved_or_copied(); - push_back(typename object_t::value_type( - std::move(key.get_ref()), (init.begin() + 1)->moved_or_copied())); + void push_back(initializer_list_t init) { + if (is_object() && init.size() == 2 && (*init.begin())->is_string()) { + basic_json &&key = init.begin()->moved_or_copied(); + push_back(typename object_t::value_type( + std::move(key.get_ref()), (init.begin() + 1)->moved_or_copied())); + } else { + push_back(basic_json(init)); + } } - else - { - push_back(basic_json(init)); - } - } - /*! + /*! @brief add an object to an object @copydoc push_back(initializer_list_t) */ - reference operator+=(initializer_list_t init) - { - push_back(init); - return *this; - } + reference operator+=(initializer_list_t init) { + push_back(init); + return *this; + } - /*! + /*! @brief add an object to an array Creates a JSON value from the passed parameters @a args to the end of the @@ -21897,33 +20149,30 @@ class basic_json @since version 2.0.8, returns reference since 3.7.0 */ - template - reference emplace_back(Args&& ... args) - { - // emplace_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()))); - } + template + reference emplace_back(Args &&... args) { + // emplace_back only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) { + JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()))); + } - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } + // transform null object into an array + if (is_null()) { + m_type = value_t::array; + m_value = value_t::array; + assert_invariant(); + } - // add element to array (perfect forwarding) + // add element to array (perfect forwarding) #ifdef JSON_HAS_CPP_17 - return m_value.array->emplace_back(std::forward(args)...); + return m_value.array->emplace_back(std::forward(args)...); #else - m_value.array->emplace_back(std::forward(args)...); + m_value.array->emplace_back(std::forward(args)...); return m_value.array->back(); #endif - } + } - /*! + /*! @brief add an object to an object if key does not exist Inserts a new element into a JSON object constructed in-place with the @@ -21950,54 +20199,50 @@ class basic_json @since version 2.0.8 */ - template - std::pair emplace(Args&& ... args) - { - // emplace only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) - { - JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()))); + template + std::pair emplace(Args &&... args) { + // emplace only works for null objects or arrays + if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) { + JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()))); + } + + // transform null object into an object + if (is_null()) { + m_type = value_t::object; + m_value = value_t::object; + assert_invariant(); + } + + // add element to array (perfect forwarding) + auto res = m_value.object->emplace(std::forward(args)...); + // create result iterator and set iterator to the result of emplace + auto it = begin(); + it.m_it.object_iterator = res.first; + + // return pair of iterator and boolean + return {it, res.second}; } - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); + /// Helper for insertion of an iterator + /// @note: This uses std::distance to support GCC 4.8, + /// see https://github.com/nlohmann/json/pull/1257 + template + iterator insert_iterator(const_iterator pos, Args &&... args) { + iterator result(this); + JSON_ASSERT(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; + + // This could have been written as: + // result.m_it.array_iterator = 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. + + return result; } - // add element to array (perfect forwarding) - auto res = m_value.object->emplace(std::forward(args)...); - // create result iterator and set iterator to the result of emplace - auto it = begin(); - it.m_it.object_iterator = res.first; - - // return pair of iterator and boolean - return {it, res.second}; - } - - /// Helper for insertion of an iterator - /// @note: This uses std::distance to support GCC 4.8, - /// see https://github.com/nlohmann/json/pull/1257 - template - iterator insert_iterator(const_iterator pos, Args&& ... args) - { - iterator result(this); - JSON_ASSERT(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; - - // This could have been written as: - // result.m_it.array_iterator = 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. - - return result; - } - - /*! + /*! @brief inserts element Inserts element @a val before iterator @a pos. @@ -22019,34 +20264,30 @@ class basic_json @since version 1.0.0 */ - iterator insert(const_iterator pos, const basic_json& val) - { - // insert only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + iterator insert(const_iterator pos, const basic_json &val) { + // insert only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) { + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + } + + // insert to array and return iterator + return insert_iterator(pos, val); } - // insert to array and return iterator - return insert_iterator(pos, val); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); } - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - /*! + /*! @brief inserts element @copydoc insert(const_iterator, const basic_json&) */ - iterator insert(const_iterator pos, basic_json&& val) - { - return insert(pos, val); - } + iterator insert(const_iterator pos, basic_json &&val) { + return insert(pos, val); + } - /*! + /*! @brief inserts elements Inserts @a cnt copies of @a val before iterator @a pos. @@ -22070,25 +20311,22 @@ class basic_json @since version 1.0.0 */ - iterator insert(const_iterator pos, size_type cnt, const basic_json& val) - { - // insert only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + iterator insert(const_iterator pos, size_type cnt, const basic_json &val) { + // insert only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) { + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + } + + // insert to array and return iterator + return insert_iterator(pos, cnt, val); } - // insert to array and return iterator - return insert_iterator(pos, cnt, val); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); } - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - /*! + /*! @brief inserts elements Inserts elements from range `[first, last)` before iterator @a pos. @@ -22118,36 +20356,31 @@ class basic_json @since version 1.0.0 */ - iterator insert(const_iterator pos, const_iterator first, const_iterator last) - { - // insert only works for arrays - if (JSON_HEDLEY_UNLIKELY(!is_array())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + iterator insert(const_iterator pos, const_iterator first, const_iterator last) { + // insert only works for arrays + if (JSON_HEDLEY_UNLIKELY(!is_array())) { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + } + + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + } + + if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) { + JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container")); + } + + // insert to array and return iterator + return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); } - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) - { - JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container")); - } - - // insert to array and return iterator - return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); - } - - /*! + /*! @brief inserts elements Inserts elements from initializer list @a ilist before iterator @a pos. @@ -22171,25 +20404,22 @@ class basic_json @since version 1.0.0 */ - iterator insert(const_iterator pos, initializer_list_t ilist) - { - // insert only works for arrays - if (JSON_HEDLEY_UNLIKELY(!is_array())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + iterator insert(const_iterator pos, initializer_list_t ilist) { + // insert only works for arrays + if (JSON_HEDLEY_UNLIKELY(!is_array())) { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + } + + // check if iterator pos fits to this JSON value + if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + } + + // insert to array and return iterator + return insert_iterator(pos, ilist.begin(), ilist.end()); } - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - return insert_iterator(pos, ilist.begin(), ilist.end()); - } - - /*! + /*! @brief inserts elements Inserts elements from range `[first, last)`. @@ -22212,30 +20442,26 @@ class basic_json @since version 3.0.0 */ - void insert(const_iterator first, const_iterator last) - { - // insert only works for objects - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + void insert(const_iterator first, const_iterator last) { + // insert only works for objects + if (JSON_HEDLEY_UNLIKELY(!is_object())) { + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + } + + // passed iterators must belong to objects + if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); + } + + m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); } - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - // passed iterators must belong to objects - if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) - { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); - } - - 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 Inserts all values from JSON object @a j and overwrites existing keys. @@ -22254,32 +20480,27 @@ class basic_json @since version 3.0.0 */ - void update(const_reference j) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); + void update(const_reference j) { + // implicitly convert null value to an empty object + if (is_null()) { + m_type = value_t::object; + m_value.object = create(); + assert_invariant(); + } + + if (JSON_HEDLEY_UNLIKELY(!is_object())) { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); + } + if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()))); + } + + for (auto it = j.cbegin(); it != j.cend(); ++it) { + m_value.object->operator[](it.key()) = it.value(); + } } - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); - } - if (JSON_HEDLEY_UNLIKELY(!j.is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()))); - } - - for (auto it = j.cbegin(); it != j.cend(); ++it) - { - m_value.object->operator[](it.key()) = it.value(); - } - } - - /*! + /*! @brief updates a JSON object from another object, overwriting existing keys Inserts all values from from range `[first, last)` and overwrites existing @@ -22305,41 +20526,35 @@ class basic_json @since version 3.0.0 */ - void update(const_iterator first, const_iterator last) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); + void update(const_iterator first, const_iterator last) { + // implicitly convert null value to an empty object + if (is_null()) { + m_type = value_t::object; + m_value.object = create(); + assert_invariant(); + } + + if (JSON_HEDLEY_UNLIKELY(!is_object())) { + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); + } + + // check if range iterators belong to the same JSON object + if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { + JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + } + + // passed iterators must belong to objects + if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object() + || !last.m_object->is_object())) { + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); + } + + for (auto it = first; it != last; ++it) { + m_value.object->operator[](it.key()) = it.value(); + } } - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - // passed iterators must belong to objects - if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object() - || !last.m_object->is_object())) - { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); - } - - for (auto it = first; it != last; ++it) - { - m_value.object->operator[](it.key()) = it.value(); - } - } - - /*! + /*! @brief exchanges the values Exchanges the contents of the JSON value with those of @a other. Does not @@ -22356,19 +20571,18 @@ class basic_json @since version 1.0.0 */ - void swap(reference other) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& + void swap(reference other) noexcept( + 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::swap(m_type, other.m_type); - std::swap(m_value, other.m_value); - assert_invariant(); - } + ) { + std::swap(m_type, other.m_type); + std::swap(m_value, other.m_value); + assert_invariant(); + } - /*! + /*! @brief exchanges the values Exchanges the contents of the JSON value from @a left with those of @a right. Does not @@ -22386,17 +20600,16 @@ class basic_json @since version 1.0.0 */ - friend void swap(reference left, reference right) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& + friend void swap(reference left, reference right) noexcept( + std::is_nothrow_move_constructible::value && + std::is_nothrow_move_assignable::value && + std::is_nothrow_move_constructible::value && std::is_nothrow_move_assignable::value - ) - { - left.swap(right); - } + ) { + left.swap(right); + } - /*! + /*! @brief exchanges the values Exchanges the contents of a JSON array with those of @a other. Does not @@ -22416,20 +20629,16 @@ class basic_json @since version 1.0.0 */ - void swap(array_t& other) - { - // swap only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - std::swap(*(m_value.array), other); + void swap(array_t &other) { + // swap only works for arrays + if (JSON_HEDLEY_LIKELY(is_array())) { + std::swap(*(m_value.array), other); + } else { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + } } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - /*! + /*! @brief exchanges the values Exchanges the contents of a JSON object with those of @a other. Does not @@ -22449,20 +20658,16 @@ class basic_json @since version 1.0.0 */ - void swap(object_t& other) - { - // swap only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - std::swap(*(m_value.object), other); + void swap(object_t &other) { + // swap only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) { + std::swap(*(m_value.object), other); + } else { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + } } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - /*! + /*! @brief exchanges the values Exchanges the contents of a JSON string with those of @a other. Does not @@ -22482,20 +20687,16 @@ class basic_json @since version 1.0.0 */ - void swap(string_t& other) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_string())) - { - std::swap(*(m_value.string), other); + void swap(string_t &other) { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_string())) { + std::swap(*(m_value.string), other); + } else { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + } } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - /*! + /*! @brief exchanges the values Exchanges the contents of a JSON string with those of @a other. Does not @@ -22515,44 +20716,36 @@ class basic_json @since version 3.8.0 */ - void swap(binary_t& other) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_binary())) - { - std::swap(*(m_value.binary), other); + void swap(binary_t &other) { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_binary())) { + std::swap(*(m_value.binary), other); + } else { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + } } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + + /// @copydoc swap(binary_t) + void swap(typename binary_t::container_type &other) { + // swap only works for strings + if (JSON_HEDLEY_LIKELY(is_binary())) { + std::swap(*(m_value.binary), other); + } else { + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + } } - } - /// @copydoc swap(binary_t) - void swap(typename binary_t::container_type& other) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_binary())) - { - std::swap(*(m_value.binary), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } + /// @} - /// @} + public: + ////////////////////////////////////////// + // lexicographical comparison operators // + ////////////////////////////////////////// - public: - ////////////////////////////////////////// - // lexicographical comparison operators // - ////////////////////////////////////////// + /// @name lexicographical comparison operators + /// @{ - /// @name lexicographical comparison operators - /// @{ - - /*! + /*! @brief comparison: equal Compares two JSON values for equality according to the following rules: @@ -22607,97 +20800,80 @@ class basic_json @since version 1.0.0 */ - friend bool operator==(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); + friend bool operator==(const_reference lhs, const_reference rhs) noexcept { + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - return *lhs.m_value.array == *rhs.m_value.array; + if (lhs_type == rhs_type) { + switch (lhs_type) { + case value_t::array: + return *lhs.m_value.array == *rhs.m_value.array; - case value_t::object: - return *lhs.m_value.object == *rhs.m_value.object; + case value_t::object: + return *lhs.m_value.object == *rhs.m_value.object; - case value_t::null: - return true; + case value_t::null: + return true; - case value_t::string: - return *lhs.m_value.string == *rhs.m_value.string; + case value_t::string: + return *lhs.m_value.string == *rhs.m_value.string; - case value_t::boolean: - return lhs.m_value.boolean == rhs.m_value.boolean; + case value_t::boolean: + return lhs.m_value.boolean == rhs.m_value.boolean; - case value_t::number_integer: - return lhs.m_value.number_integer == rhs.m_value.number_integer; + case value_t::number_integer: + return lhs.m_value.number_integer == rhs.m_value.number_integer; - case value_t::number_unsigned: - return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; + case value_t::number_unsigned: + return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; - case value_t::number_float: - return lhs.m_value.number_float == rhs.m_value.number_float; + case value_t::number_float: + return lhs.m_value.number_float == rhs.m_value.number_float; - case value_t::binary: - return *lhs.m_value.binary == *rhs.m_value.binary; + case value_t::binary: + return *lhs.m_value.binary == *rhs.m_value.binary; - default: - return false; + default: + return false; + } + } else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) { + return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; + } else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) { + return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); + } else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) { + return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; + } else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) { + return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); + } else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) { + return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; + } else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) { + return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); } - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); + + return false; } - return false; - } - - /*! + /*! @brief comparison: equal @copydoc operator==(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs == basic_json(rhs); - } + template::value, int>::type = 0> + friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept { + return lhs == basic_json(rhs); + } - /*! + /*! @brief comparison: equal @copydoc operator==(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) == rhs; - } + template::value, int>::type = 0> + friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept { + return basic_json(lhs) == rhs; + } - /*! + /*! @brief comparison: not equal Compares two JSON values for inequality by calculating `not (lhs == rhs)`. @@ -22715,34 +20891,31 @@ class basic_json @since version 1.0.0 */ - friend bool operator!=(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs == rhs); - } + friend bool operator!=(const_reference lhs, const_reference rhs) noexcept { + return !(lhs == rhs); + } - /*! + /*! @brief comparison: not equal @copydoc operator!=(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs != basic_json(rhs); - } + template::value, int>::type = 0> + friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept { + return lhs != basic_json(rhs); + } - /*! + /*! @brief comparison: not equal @copydoc operator!=(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) != rhs; - } + template::value, int>::type = 0> + friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept { + return basic_json(lhs) != rhs; + } - /*! + /*! @brief comparison: less than Compares whether one JSON value @a lhs is less than another JSON value @a @@ -22768,102 +20941,85 @@ class basic_json @since version 1.0.0 */ - friend bool operator<(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); + friend bool operator<(const_reference lhs, const_reference rhs) noexcept { + const auto lhs_type = lhs.type(); + const auto rhs_type = rhs.type(); - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - // note parentheses are necessary, see - // https://github.com/nlohmann/json/issues/1530 - return (*lhs.m_value.array) < (*rhs.m_value.array); + if (lhs_type == rhs_type) { + switch (lhs_type) { + case value_t::array: + // note parentheses are necessary, see + // https://github.com/nlohmann/json/issues/1530 + return (*lhs.m_value.array) < (*rhs.m_value.array); - case value_t::object: - return (*lhs.m_value.object) < (*rhs.m_value.object); + case value_t::object: + return (*lhs.m_value.object) < (*rhs.m_value.object); - case value_t::null: - return false; + case value_t::null: + return false; - case value_t::string: - return (*lhs.m_value.string) < (*rhs.m_value.string); + case value_t::string: + return (*lhs.m_value.string) < (*rhs.m_value.string); - case value_t::boolean: - return (lhs.m_value.boolean) < (rhs.m_value.boolean); + case value_t::boolean: + return (lhs.m_value.boolean) < (rhs.m_value.boolean); - case value_t::number_integer: - return (lhs.m_value.number_integer) < (rhs.m_value.number_integer); + case value_t::number_integer: + return (lhs.m_value.number_integer) < (rhs.m_value.number_integer); - case value_t::number_unsigned: - return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned); + case value_t::number_unsigned: + return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned); - case value_t::number_float: - return (lhs.m_value.number_float) < (rhs.m_value.number_float); + case value_t::number_float: + return (lhs.m_value.number_float) < (rhs.m_value.number_float); - case value_t::binary: - return (*lhs.m_value.binary) < (*rhs.m_value.binary); + case value_t::binary: + return (*lhs.m_value.binary) < (*rhs.m_value.binary); - default: - return false; + default: + return false; + } + } else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) { + return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; + } else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) { + return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); + } else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) { + return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; + } else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) { + return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); + } else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) { + return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); + } else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) { + return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; } - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; + + // We only reach this line if we cannot compare values. In that case, + // we compare types. Note we have to call the operator explicitly, + // because MSVC has problems otherwise. + return operator<(lhs_type, rhs_type); } - // We only reach this line if we cannot compare values. In that case, - // we compare types. Note we have to call the operator explicitly, - // because MSVC has problems otherwise. - return operator<(lhs_type, rhs_type); - } - - /*! + /*! @brief comparison: less than @copydoc operator<(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs < basic_json(rhs); - } + template::value, int>::type = 0> + friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept { + return lhs < basic_json(rhs); + } - /*! + /*! @brief comparison: less than @copydoc operator<(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) < rhs; - } + template::value, int>::type = 0> + friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept { + return basic_json(lhs) < rhs; + } - /*! + /*! @brief comparison: less than or equal Compares whether one JSON value @a lhs is less than or equal to another @@ -22882,34 +21038,31 @@ class basic_json @since version 1.0.0 */ - friend bool operator<=(const_reference lhs, const_reference rhs) noexcept - { - return !(rhs < lhs); - } + friend bool operator<=(const_reference lhs, const_reference rhs) noexcept { + return !(rhs < lhs); + } - /*! + /*! @brief comparison: less than or equal @copydoc operator<=(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs <= basic_json(rhs); - } + template::value, int>::type = 0> + friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept { + return lhs <= basic_json(rhs); + } - /*! + /*! @brief comparison: less than or equal @copydoc operator<=(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) <= rhs; - } + template::value, int>::type = 0> + friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept { + return basic_json(lhs) <= rhs; + } - /*! + /*! @brief comparison: greater than Compares whether one JSON value @a lhs is greater than another @@ -22928,34 +21081,31 @@ class basic_json @since version 1.0.0 */ - friend bool operator>(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs <= rhs); - } + friend bool operator>(const_reference lhs, const_reference rhs) noexcept { + return !(lhs <= rhs); + } - /*! + /*! @brief comparison: greater than @copydoc operator>(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs > basic_json(rhs); - } + template::value, int>::type = 0> + friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept { + return lhs > basic_json(rhs); + } - /*! + /*! @brief comparison: greater than @copydoc operator>(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) > rhs; - } + template::value, int>::type = 0> + friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept { + return basic_json(lhs) > rhs; + } - /*! + /*! @brief comparison: greater than or equal Compares whether one JSON value @a lhs is greater than or equal to another @@ -22974,43 +21124,40 @@ class basic_json @since version 1.0.0 */ - friend bool operator>=(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs < rhs); - } + friend bool operator>=(const_reference lhs, const_reference rhs) noexcept { + return !(lhs < rhs); + } - /*! + /*! @brief comparison: greater than or equal @copydoc operator>=(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs >= basic_json(rhs); - } + template::value, int>::type = 0> + friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept { + return lhs >= basic_json(rhs); + } - /*! + /*! @brief comparison: greater than or equal @copydoc operator>=(const_reference, const_reference) */ - template::value, int>::type = 0> - friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) >= rhs; - } + template::value, int>::type = 0> + friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept { + return basic_json(lhs) >= rhs; + } - /// @} + /// @} - /////////////////// - // serialization // - /////////////////// + /////////////////// + // serialization // + /////////////////// - /// @name serialization - /// @{ + /// @name serialization + /// @{ - /*! + /*! @brief serialize to stream Serialize the given JSON value @a j to the output stream @a o. The JSON @@ -23041,22 +21188,21 @@ class basic_json @since version 1.0.0; indentation character added in version 3.0.0 */ - friend std::ostream& operator<<(std::ostream& o, const basic_json& j) - { - // read width member and use it as indentation parameter if nonzero - const bool pretty_print = o.width() > 0; - const auto indentation = pretty_print ? o.width() : 0; + friend std::ostream &operator<<(std::ostream &o, const basic_json &j) { + // read width member and use it as indentation parameter if nonzero + const bool pretty_print = o.width() > 0; + const auto indentation = pretty_print ? o.width() : 0; - // reset width to 0 for subsequent calls to this stream - o.width(0); + // reset width to 0 for subsequent calls to this stream + o.width(0); - // do the actual serialization - serializer s(detail::output_adapter(o), o.fill()); - s.dump(j, pretty_print, false, static_cast(indentation)); - return o; - } + // do the actual serialization + serializer s(detail::output_adapter(o), o.fill()); + s.dump(j, pretty_print, false, static_cast(indentation)); + return o; + } - /*! + /*! @brief serialize to stream @deprecated This stream operator is deprecated and will be removed in future 4.0.0 of the library. Please use @@ -23064,23 +21210,22 @@ class basic_json instead; that is, replace calls like `j >> o;` with `o << j;`. @since version 1.0.0; deprecated since version 3.0.0 */ - JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) - friend std::ostream& operator>>(const basic_json& j, std::ostream& o) - { - return o << j; - } + JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream & , const basic_json&)) + friend std::ostream &operator>>(const basic_json &j, std::ostream &o) { + return o << j; + } - /// @} + /// @} - ///////////////////// - // deserialization // - ///////////////////// + ///////////////////// + // deserialization // + ///////////////////// - /// @name deserialization - /// @{ + /// @name deserialization + /// @{ - /*! + /*! @brief deserialize from a compatible input @tparam InputType A compatible input, for instance @@ -23131,19 +21276,18 @@ class basic_json @since version 2.0.3 (contiguous containers); version 3.9.0 allowed to ignore comments. */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json parse(InputType&& i, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(detail::input_adapter(std::forward(i)), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json parse(InputType &&i, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) { + basic_json result; + parser(detail::input_adapter(std::forward(i)), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } - /*! + /*! @brief deserialize from a pair of character iterators The value_type of the iterator must be a integral type with size of 1, 2 or @@ -23169,32 +21313,30 @@ class basic_json @throw parse_error.102 if to_unicode fails or surrogate error @throw parse_error.103 if to_unicode fails */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json parse(IteratorType first, - IteratorType last, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json parse(IteratorType first, + IteratorType last, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) { + basic_json result; + parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) - static basic_json parse(detail::span_input_adapter&& i, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) + static basic_json parse(detail::span_input_adapter &&i, + const parser_callback_t cb = nullptr, + const bool allow_exceptions = true, + const bool ignore_comments = false) { + basic_json result; + parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); + return result; + } - /*! + /*! @brief check if the input is valid JSON Unlike the @ref parse(InputType&&, const parser_callback_t,const bool) @@ -23224,29 +21366,26 @@ class basic_json @liveexample{The example below demonstrates the `accept()` function reading from a string.,accept__string} */ - template - static bool accept(InputType&& i, - const bool ignore_comments = false) - { - return parser(detail::input_adapter(std::forward(i)), nullptr, false, ignore_comments).accept(true); - } + template + static bool accept(InputType &&i, + const bool ignore_comments = false) { + return parser(detail::input_adapter(std::forward(i)), nullptr, false, ignore_comments).accept(true); + } - template - static bool accept(IteratorType first, IteratorType last, - const bool ignore_comments = false) - { - return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); - } + template + static bool accept(IteratorType first, IteratorType last, + const bool ignore_comments = false) { + return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); + } - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) - static bool accept(detail::span_input_adapter&& i, - const bool ignore_comments = false) - { - return parser(i.get(), nullptr, false, ignore_comments).accept(true); - } + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) + static bool accept(detail::span_input_adapter &&i, + const bool ignore_comments = false) { + return parser(i.get(), nullptr, false, ignore_comments).accept(true); + } - /*! + /*! @brief generate SAX events The SAX event lister must follow the interface of @ref json_sax. @@ -23286,47 +21425,44 @@ class basic_json @since version 3.2.0 */ - template - JSON_HEDLEY_NON_NULL(2) - static bool sax_parse(InputType&& i, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = detail::input_adapter(std::forward(i)); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } + template + JSON_HEDLEY_NON_NULL(2) + static bool sax_parse(InputType &&i, SAX *sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) { + auto ia = detail::input_adapter(std::forward(i)); + return format == input_format_t::json + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } - template - JSON_HEDLEY_NON_NULL(3) - static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = detail::input_adapter(std::move(first), std::move(last)); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } + template + JSON_HEDLEY_NON_NULL(3) + static bool sax_parse(IteratorType first, IteratorType last, SAX *sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) { + auto ia = detail::input_adapter(std::move(first), std::move(last)); + return format == input_format_t::json + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } - template - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) - JSON_HEDLEY_NON_NULL(2) - static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = i.get(); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } + template + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) + JSON_HEDLEY_NON_NULL(2) + static bool sax_parse(detail::span_input_adapter &&i, SAX *sax, + input_format_t format = input_format_t::json, + const bool strict = true, + const bool ignore_comments = false) { + auto ia = i.get(); + return format == input_format_t::json + ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) + : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); + } - /*! + /*! @brief deserialize from stream @deprecated This stream operator is deprecated and will be removed in version 4.0.0 of the library. Please use @@ -23334,13 +21470,12 @@ class basic_json instead; that is, replace calls like `j << i;` with `i >> j;`. @since version 1.0.0; deprecated since version 3.0.0 */ - JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) - friend std::istream& operator<<(basic_json& j, std::istream& i) - { - return operator>>(i, j); - } + JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream & , basic_json & )) + friend std::istream &operator<<(basic_json &j, std::istream &i) { + return operator>>(i, j); + } - /*! + /*! @brief deserialize from stream Deserializes an input stream to a JSON value. @@ -23365,19 +21500,18 @@ class basic_json @since version 1.0.0 */ - friend std::istream& operator>>(std::istream& i, basic_json& j) - { - parser(detail::input_adapter(i)).parse(false, j); - return i; - } + friend std::istream &operator>>(std::istream &i, basic_json &j) { + parser(detail::input_adapter(i)).parse(false, j); + return i; + } - /// @} + /// @} - /////////////////////////// - // convenience functions // - /////////////////////////// + /////////////////////////// + // convenience functions // + /////////////////////////// - /*! + /*! @brief return the type as string Returns the type name as string to be used in error messages - usually to @@ -23408,53 +21542,51 @@ class basic_json @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept` since 3.0.0 */ - JSON_HEDLEY_RETURNS_NON_NULL - const char* type_name() const noexcept - { - { - switch (m_type) + JSON_HEDLEY_RETURNS_NON_NULL + const char *type_name() const noexcept { { - case value_t::null: - return "null"; - case value_t::object: - return "object"; - case value_t::array: - return "array"; - case value_t::string: - return "string"; - case value_t::boolean: - return "boolean"; - case value_t::binary: - return "binary"; - case value_t::discarded: - return "discarded"; - default: - return "number"; + switch (m_type) { + case value_t::null: + return "null"; + case value_t::object: + return "object"; + case value_t::array: + return "array"; + case value_t::string: + return "string"; + case value_t::boolean: + return "boolean"; + case value_t::binary: + return "binary"; + case value_t::discarded: + return "discarded"; + default: + return "number"; + } } } - } - private: - ////////////////////// - // member variables // - ////////////////////// + private: + ////////////////////// + // member variables // + ////////////////////// - /// the type of the current element - value_t m_type = value_t::null; + /// 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 = {}; - ////////////////////////////////////////// - // binary serialization/deserialization // - ////////////////////////////////////////// + ////////////////////////////////////////// + // binary serialization/deserialization // + ////////////////////////////////////////// - /// @name binary serialization/deserialization support - /// @{ + /// @name binary serialization/deserialization support + /// @{ - public: - /*! + public: + /*! @brief create a CBOR serialization of a given JSON value Serializes a given JSON value @a j to a byte vector using the CBOR (Concise @@ -23548,24 +21680,21 @@ class basic_json @since version 2.0.9; compact representation of floating-point numbers since version 3.8.0 */ - static std::vector to_cbor(const basic_json& j) - { - std::vector result; - to_cbor(j, result); - return result; - } + static std::vector to_cbor(const basic_json &j) { + std::vector result; + to_cbor(j, result); + return result; + } - static void to_cbor(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_cbor(j); - } + static void to_cbor(const basic_json &j, detail::output_adapter o) { + binary_writer(o).write_cbor(j); + } - static void to_cbor(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_cbor(j); - } + static void to_cbor(const basic_json &j, detail::output_adapter o) { + binary_writer(o).write_cbor(j); + } - /*! + /*! @brief create a MessagePack serialization of a given JSON value Serializes a given JSON value @a j to a byte vector using the MessagePack @@ -23643,24 +21772,21 @@ class basic_json @since version 2.0.9 */ - static std::vector to_msgpack(const basic_json& j) - { - std::vector result; - to_msgpack(j, result); - return result; - } + static std::vector to_msgpack(const basic_json &j) { + std::vector result; + to_msgpack(j, result); + return result; + } - static void to_msgpack(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_msgpack(j); - } + static void to_msgpack(const basic_json &j, detail::output_adapter o) { + binary_writer(o).write_msgpack(j); + } - static void to_msgpack(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_msgpack(j); - } + static void to_msgpack(const basic_json &j, detail::output_adapter o) { + binary_writer(o).write_msgpack(j); + } - /*! + /*! @brief create a UBJSON serialization of a given JSON value Serializes a given JSON value @a j to a byte vector using the UBJSON @@ -23746,29 +21872,26 @@ class basic_json @since version 3.1.0 */ - static std::vector to_ubjson(const basic_json& j, - const bool use_size = false, - const bool use_type = false) - { - std::vector result; - to_ubjson(j, result, use_size, use_type); - return result; - } + static std::vector to_ubjson(const basic_json &j, + const bool use_size = false, + const bool use_type = false) { + std::vector result; + to_ubjson(j, result, use_size, use_type); + return result; + } - static void to_ubjson(const basic_json& j, detail::output_adapter o, - const bool use_size = false, const bool use_type = false) - { - binary_writer(o).write_ubjson(j, use_size, use_type); - } + static void to_ubjson(const basic_json &j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false) { + binary_writer(o).write_ubjson(j, use_size, use_type); + } - static void to_ubjson(const basic_json& j, detail::output_adapter o, - const bool use_size = false, const bool use_type = false) - { - binary_writer(o).write_ubjson(j, use_size, use_type); - } + static void to_ubjson(const basic_json &j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false) { + binary_writer(o).write_ubjson(j, use_size, use_type); + } - /*! + /*! @brief Serializes the given JSON object `j` to BSON and returns a vector containing the corresponding BSON-representation. @@ -23824,14 +21947,13 @@ class basic_json @sa @ref to_cbor(const basic_json&) for the related CBOR format @sa @ref to_msgpack(const basic_json&) for the related MessagePack format */ - static std::vector to_bson(const basic_json& j) - { - std::vector result; - to_bson(j, result); - return result; - } + static std::vector to_bson(const basic_json &j) { + std::vector result; + to_bson(j, result); + return result; + } - /*! + /*! @brief Serializes the given JSON object `j` to BSON and forwards the corresponding BSON-representation to the given output_adapter `o`. @param j The JSON object to convert to BSON. @@ -23839,21 +21961,19 @@ class basic_json @pre The input `j` shall be an object: `j.is_object() == true` @sa @ref to_bson(const basic_json&) */ - static void to_bson(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_bson(j); - } + static void to_bson(const basic_json &j, detail::output_adapter o) { + binary_writer(o).write_bson(j); + } - /*! + /*! @copydoc to_bson(const basic_json&, detail::output_adapter) */ - static void to_bson(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_bson(j); - } + static void to_bson(const basic_json &j, detail::output_adapter o) { + binary_writer(o).write_bson(j); + } - /*! + /*! @brief create a JSON value from an input in CBOR format Deserializes a given input @a i to a JSON value using the CBOR (Concise @@ -23955,64 +22075,60 @@ class basic_json @a strict parameter since 3.0.0; added @a allow_exceptions parameter since 3.2.0; added @a tag_handler parameter since 3.9.0. */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_cbor(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_cbor(InputType &&i, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } - /*! + /*! @copydoc from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_cbor(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_cbor(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) - static basic_json from_cbor(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) + static basic_json from_cbor(const T *ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { + return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); + } - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) - static basic_json from_cbor(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) + static basic_json from_cbor(detail::span_input_adapter &&i, + const bool strict = true, + const bool allow_exceptions = true, + const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + return res ? result : basic_json(value_t::discarded); + } - /*! + /*! @brief create a JSON value from an input in MessagePack format Deserializes a given input @a i to a JSON value using the MessagePack @@ -24098,61 +22214,57 @@ class basic_json @a strict parameter since 3.0.0; added @a allow_exceptions parameter since 3.2.0 */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_msgpack(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_msgpack(InputType &&i, + const bool strict = true, + const bool allow_exceptions = true) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } - /*! + /*! @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool) */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_msgpack(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_msgpack(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) - static basic_json from_msgpack(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_msgpack(ptr, ptr + len, strict, allow_exceptions); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) + static basic_json from_msgpack(const T *ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) { + return from_msgpack(ptr, ptr + len, strict, allow_exceptions); + } - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) - static basic_json from_msgpack(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) + static basic_json from_msgpack(detail::span_input_adapter &&i, + const bool strict = true, + const bool allow_exceptions = true) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } - /*! + /*! @brief create a JSON value from an input in UBJSON format Deserializes a given input @a i to a JSON value using the UBJSON (Universal @@ -24214,60 +22326,56 @@ class basic_json @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0 */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_ubjson(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_ubjson(InputType &&i, + const bool strict = true, + const bool allow_exceptions = true) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } - /*! + /*! @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool) */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_ubjson(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_ubjson(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) - static basic_json from_ubjson(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_ubjson(ptr, ptr + len, strict, allow_exceptions); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) + static basic_json from_ubjson(const T *ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) { + return from_ubjson(ptr, ptr + len, strict, allow_exceptions); + } - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) - static basic_json from_ubjson(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) + static basic_json from_ubjson(detail::span_input_adapter &&i, + const bool strict = true, + const bool allow_exceptions = true) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } - /*! + /*! @brief Create a JSON value from an input in BSON format Deserializes a given input @a i to a JSON value using the BSON (Binary JSON) @@ -24327,67 +22435,63 @@ class basic_json @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the related UBJSON format */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bson(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_bson(InputType &&i, + const bool strict = true, + const bool allow_exceptions = true) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::forward(i)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } - /*! + /*! @copydoc from_bson(detail::input_adapter&&, const bool, const bool) */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bson(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json from_bson(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = detail::input_adapter(std::move(first), std::move(last)); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) - static basic_json from_bson(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_bson(ptr, ptr + len, strict, allow_exceptions); - } + template + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) + static basic_json from_bson(const T *ptr, std::size_t len, + const bool strict = true, + const bool allow_exceptions = true) { + return from_bson(ptr, ptr + len, strict, allow_exceptions); + } - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) - static basic_json from_bson(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - /// @} + JSON_HEDLEY_WARN_UNUSED_RESULT + JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) + static basic_json from_bson(detail::span_input_adapter &&i, + const bool strict = true, + const bool allow_exceptions = true) { + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + auto ia = i.get(); + const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); + } + /// @} - ////////////////////////// - // JSON Pointer support // - ////////////////////////// + ////////////////////////// + // JSON Pointer support // + ////////////////////////// - /// @name JSON Pointer functions - /// @{ + /// @name JSON Pointer functions + /// @{ - /*! + /*! @brief access specified element via JSON Pointer Uses a JSON pointer to retrieve a reference to the respective JSON value. @@ -24420,12 +22524,11 @@ class basic_json @since version 2.0.0 */ - reference operator[](const json_pointer& ptr) - { - return ptr.get_unchecked(this); - } + reference operator[](const json_pointer &ptr) { + return ptr.get_unchecked(this); + } - /*! + /*! @brief access specified element via JSON Pointer Uses a JSON pointer to retrieve a reference to the respective JSON value. @@ -24448,12 +22551,11 @@ class basic_json @since version 2.0.0 */ - const_reference operator[](const json_pointer& ptr) const - { - return ptr.get_unchecked(this); - } + const_reference operator[](const json_pointer &ptr) const { + return ptr.get_unchecked(this); + } - /*! + /*! @brief access specified element via JSON Pointer Returns a reference to the element at with specified JSON pointer @a ptr, @@ -24491,12 +22593,11 @@ class basic_json @liveexample{The behavior is shown in the example.,at_json_pointer} */ - reference at(const json_pointer& ptr) - { - return ptr.get_checked(this); - } + reference at(const json_pointer &ptr) { + return ptr.get_checked(this); + } - /*! + /*! @brief access specified element via JSON Pointer Returns a const reference to the element at with specified JSON pointer @a @@ -24534,12 +22635,11 @@ class basic_json @liveexample{The behavior is shown in the example.,at_json_pointer_const} */ - const_reference at(const json_pointer& ptr) const - { - return ptr.get_checked(this); - } + const_reference at(const json_pointer &ptr) const { + return ptr.get_checked(this); + } - /*! + /*! @brief return flattened JSON value The function creates a JSON object whose keys are JSON pointers (see [RFC @@ -24561,14 +22661,13 @@ class basic_json @since version 2.0.0 */ - basic_json flatten() const - { - basic_json result(value_t::object); - json_pointer::flatten("", *this, result); - return result; - } + basic_json flatten() const { + basic_json result(value_t::object); + json_pointer::flatten("", *this, result); + return result; + } - /*! + /*! @brief unflatten a previously flattened JSON value The function restores the arbitrary nesting of a JSON value that has been @@ -24598,21 +22697,20 @@ class basic_json @since version 2.0.0 */ - basic_json unflatten() const - { - return json_pointer::unflatten(*this); - } + basic_json unflatten() const { + return json_pointer::unflatten(*this); + } - /// @} + /// @} - ////////////////////////// - // JSON Patch functions // - ////////////////////////// + ////////////////////////// + // JSON Patch functions // + ////////////////////////// - /// @name JSON Patch functions - /// @{ + /// @name JSON Patch functions + /// @{ - /*! + /*! @brief applies a JSON patch [JSON Patch](http://jsonpatch.com) defines a JSON document structure for @@ -24659,269 +22757,229 @@ class basic_json @since version 2.0.0 */ - basic_json patch(const basic_json& json_patch) const - { - // make a working copy to apply the patch to - basic_json result = *this; + basic_json patch(const basic_json &json_patch) const { + // make a working copy to apply the patch to + basic_json result = *this; - // the valid JSON Patch operations - enum class patch_operations {add, remove, replace, move, copy, test, invalid}; - - const auto get_op = [](const std::string & op) - { - if (op == "add") - { - return patch_operations::add; - } - if (op == "remove") - { - return patch_operations::remove; - } - if (op == "replace") - { - return patch_operations::replace; - } - if (op == "move") - { - return patch_operations::move; - } - if (op == "copy") - { - return patch_operations::copy; - } - if (op == "test") - { - return patch_operations::test; - } - - return patch_operations::invalid; - }; - - // wrapper for "add" operation; add value at ptr - const auto operation_add = [&result](json_pointer & ptr, basic_json val) - { - // adding to the root of the target document means replacing it - if (ptr.empty()) - { - result = val; - return; - } - - // make sure the top element of the pointer exists - json_pointer top_pointer = ptr.top(); - if (top_pointer != ptr) - { - result.at(top_pointer); - } - - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.back(); - ptr.pop_back(); - basic_json& parent = result[ptr]; - - switch (parent.m_type) - { - case value_t::null: - case value_t::object: - { - // use operator[] to add value - parent[last_path] = val; - break; - } - - case value_t::array: - { - if (last_path == "-") - { - // special case: append to back - parent.push_back(val); - } - else - { - const auto idx = json_pointer::array_index(last_path); - if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) - { - // avoid undefined behavior - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - - // default case: insert add offset - parent.insert(parent.begin() + static_cast(idx), val); - } - break; - } - - // if there exists a parent it cannot be primitive - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - }; - - // wrapper for "remove" operation; remove value at ptr - const auto operation_remove = [&result](json_pointer & ptr) - { - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.back(); - ptr.pop_back(); - basic_json& parent = result.at(ptr); - - // remove child - if (parent.is_object()) - { - // perform range check - auto it = parent.find(last_path); - if (JSON_HEDLEY_LIKELY(it != parent.end())) - { - parent.erase(it); - } - else - { - JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found")); - } - } - else if (parent.is_array()) - { - // note erase performs range check - parent.erase(json_pointer::array_index(last_path)); - } - }; - - // type check: top level value must be an array - if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); - } - - // iterate and apply the operations - for (const auto& val : json_patch) - { - // wrapper to get a value for an operation - const auto get_value = [&val](const std::string & op, - const std::string & member, - bool string_type) -> basic_json & - { - // find value - auto it = val.m_value.object->find(member); - - // context-sensitive error message - const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; - - // check if desired value is present - if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) - { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'")); - } - - // check if result is of type string - if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) - { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'")); - } - - // no error: return value - return it->second; + // the valid JSON Patch operations + enum class patch_operations { + add, remove, replace, move, copy, test, invalid }; - // type check: every element of the array must be an object - if (JSON_HEDLEY_UNLIKELY(!val.is_object())) - { + const auto get_op = [](const std::string &op) { + if (op == "add") { + return patch_operations::add; + } + if (op == "remove") { + return patch_operations::remove; + } + if (op == "replace") { + return patch_operations::replace; + } + if (op == "move") { + return patch_operations::move; + } + if (op == "copy") { + return patch_operations::copy; + } + if (op == "test") { + return patch_operations::test; + } + + return patch_operations::invalid; + }; + + // wrapper for "add" operation; add value at ptr + const auto operation_add = [&result](json_pointer &ptr, basic_json val) { + // adding to the root of the target document means replacing it + if (ptr.empty()) { + result = val; + return; + } + + // make sure the top element of the pointer exists + json_pointer top_pointer = ptr.top(); + if (top_pointer != ptr) { + result.at(top_pointer); + } + + // get reference to parent of JSON pointer ptr + const auto last_path = ptr.back(); + ptr.pop_back(); + basic_json &parent = result[ptr]; + + switch (parent.m_type) { + case value_t::null: + case value_t::object: { + // use operator[] to add value + parent[last_path] = val; + break; + } + + case value_t::array: { + if (last_path == "-") { + // special case: append to back + parent.push_back(val); + } else { + const auto idx = json_pointer::array_index(last_path); + if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) { + // avoid undefined behavior + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + } + + // default case: insert add offset + parent.insert(parent.begin() + static_cast(idx), val); + } + break; + } + + // if there exists a parent it cannot be primitive + default: // LCOV_EXCL_LINE + JSON_ASSERT(false); // LCOV_EXCL_LINE + } + }; + + // wrapper for "remove" operation; remove value at ptr + const auto operation_remove = [&result](json_pointer &ptr) { + // get reference to parent of JSON pointer ptr + const auto last_path = ptr.back(); + ptr.pop_back(); + basic_json &parent = result.at(ptr); + + // remove child + if (parent.is_object()) { + // perform range check + auto it = parent.find(last_path); + if (JSON_HEDLEY_LIKELY(it != parent.end())) { + parent.erase(it); + } else { + JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found")); + } + } else if (parent.is_array()) { + // note erase performs range check + parent.erase(json_pointer::array_index(last_path)); + } + }; + + // type check: top level value must be an array + if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) { JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); } - // collect mandatory members - const auto op = get_value("op", "op", true).template get(); - const auto path = get_value(op, "path", true).template get(); - json_pointer ptr(path); + // iterate and apply the operations + for (const auto &val: json_patch) { + // wrapper to get a value for an operation + const auto get_value = [&val](const std::string &op, + const std::string &member, + bool string_type) -> basic_json & { + // find value + auto it = val.m_value.object->find(member); - switch (get_op(op)) - { - case patch_operations::add: - { - operation_add(ptr, get_value("add", "value", false)); - break; + // context-sensitive error message + const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; + + // check if desired value is present + if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) { + JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'")); + } + + // check if result is of type string + if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) { + JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'")); + } + + // no error: return value + return it->second; + }; + + // type check: every element of the array must be an object + if (JSON_HEDLEY_UNLIKELY(!val.is_object())) { + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); } - case patch_operations::remove: - { - operation_remove(ptr); - break; - } + // collect mandatory members + const auto op = get_value("op", "op", true).template get(); + const auto path = get_value(op, "path", true).template get(); + json_pointer ptr(path); - case patch_operations::replace: - { - // the "path" location must exist - use at() - result.at(ptr) = get_value("replace", "value", false); - break; - } + switch (get_op(op)) { + case patch_operations::add: { + operation_add(ptr, get_value("add", "value", false)); + break; + } - case patch_operations::move: - { - const auto from_path = get_value("move", "from", true).template get(); - json_pointer from_ptr(from_path); + case patch_operations::remove: { + operation_remove(ptr); + break; + } - // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); - - // The move operation is functionally identical to a - // "remove" operation on the "from" location, followed - // immediately by an "add" operation at the target - // location with the value that was just removed. - operation_remove(from_ptr); - operation_add(ptr, v); - break; - } - - case patch_operations::copy: - { - const auto from_path = get_value("copy", "from", true).template get(); - const json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); - - // The copy is functionally identical to an "add" - // operation at the target location using the value - // specified in the "from" member. - operation_add(ptr, v); - break; - } - - case patch_operations::test: - { - bool success = false; - JSON_TRY - { - // check if "value" matches the one at "path" + case patch_operations::replace: { // the "path" location must exist - use at() - success = (result.at(ptr) == get_value("test", "value", false)); - } - JSON_INTERNAL_CATCH (out_of_range&) - { - // ignore out of range errors: success remains false + result.at(ptr) = get_value("replace", "value", false); + break; } - // throw an exception if test fails - if (JSON_HEDLEY_UNLIKELY(!success)) - { - JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); + case patch_operations::move: { + const auto from_path = get_value("move", "from", true).template get(); + json_pointer from_ptr(from_path); + + // the "from" location must exist - use at() + basic_json v = result.at(from_ptr); + + // The move operation is functionally identical to a + // "remove" operation on the "from" location, followed + // immediately by an "add" operation at the target + // location with the value that was just removed. + operation_remove(from_ptr); + operation_add(ptr, v); + break; } - break; - } + case patch_operations::copy: { + const auto from_path = get_value("copy", "from", true).template get(); + const json_pointer from_ptr(from_path); - default: - { - // op must be "add", "remove", "replace", "move", "copy", or - // "test" - JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid")); + // the "from" location must exist - use at() + basic_json v = result.at(from_ptr); + + // The copy is functionally identical to an "add" + // operation at the target location using the value + // specified in the "from" member. + operation_add(ptr, v); + break; + } + + case patch_operations::test: { + bool success = false; + JSON_TRY { + // check if "value" matches the one at "path" + // the "path" location must exist - use at() + success = (result.at(ptr) == get_value("test", "value", false)); + } + JSON_INTERNAL_CATCH (out_of_range &) { + // ignore out of range errors: success remains false + } + + // throw an exception if test fails + if (JSON_HEDLEY_UNLIKELY(!success)) { + JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); + } + + break; + } + + default: { + // op must be "add", "remove", "replace", "move", "copy", or + // "test" + JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid")); + } } } + + return result; } - return result; - } - - /*! + /*! @brief creates a diff as a JSON patch Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can @@ -24954,141 +23012,131 @@ class basic_json @since version 2.0.0 */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json diff(const basic_json& source, const basic_json& target, - const std::string& path = "") - { - // the patch - basic_json result(value_t::array); + JSON_HEDLEY_WARN_UNUSED_RESULT + static basic_json diff(const basic_json &source, const basic_json &target, + const std::string &path = "") { + // the patch + basic_json result(value_t::array); - // if the values are the same, return empty patch - if (source == target) - { - return result; - } - - if (source.type() != target.type()) - { - // different types: replace value - result.push_back( - { - {"op", "replace"}, {"path", path}, {"value", target} - }); - return result; - } - - switch (source.type()) - { - case value_t::array: - { - // first pass: traverse common elements - std::size_t i = 0; - while (i < source.size() && i < target.size()) - { - // recursive call to compare array values at index i - auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - ++i; - } - - // i now reached the end of at least one array - // in a second pass, traverse the remaining elements - - // remove my remaining elements - const auto end_index = static_cast(result.size()); - while (i < source.size()) - { - // add operations in reverse order to avoid invalid - // indices - result.insert(result.begin() + end_index, object( - { - {"op", "remove"}, - {"path", path + "/" + std::to_string(i)} - })); - ++i; - } - - // add other remaining elements - while (i < target.size()) - { - result.push_back( - { - {"op", "add"}, - {"path", path + "/-"}, - {"value", target[i]} - }); - ++i; - } - - break; + // if the values are the same, return empty patch + if (source == target) { + return result; } - case value_t::object: - { - // first pass: traverse this object's elements - for (auto it = source.cbegin(); it != source.cend(); ++it) - { - // escape the key name to be used in a JSON patch - const auto key = json_pointer::escape(it.key()); - - if (target.find(it.key()) != target.end()) - { - // recursive call to compare object values at key it - auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - } - else - { - // found a key that is not in o -> remove it - result.push_back(object( - { - {"op", "remove"}, {"path", path + "/" + key} - })); - } - } - - // second pass: traverse other object's elements - for (auto it = target.cbegin(); it != target.cend(); ++it) - { - if (source.find(it.key()) == source.end()) - { - // found a key that is not in this -> add it - const auto key = json_pointer::escape(it.key()); - result.push_back( - { - {"op", "add"}, {"path", path + "/" + key}, - {"value", it.value()} - }); - } - } - - break; - } - - default: - { - // both primitive type: replace value + if (source.type() != target.type()) { + // different types: replace value result.push_back( - { - {"op", "replace"}, {"path", path}, {"value", target} - }); - break; + { + {"op", "replace"}, + {"path", path}, + {"value", target} + }); + return result; } + + switch (source.type()) { + case value_t::array: { + // first pass: traverse common elements + std::size_t i = 0; + while (i < source.size() && i < target.size()) { + // recursive call to compare array values at index i + auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); + result.insert(result.end(), temp_diff.begin(), temp_diff.end()); + ++i; + } + + // i now reached the end of at least one array + // in a second pass, traverse the remaining elements + + // remove my remaining elements + const auto end_index = static_cast(result.size()); + while (i < source.size()) { + // add operations in reverse order to avoid invalid + // indices + result.insert(result.begin() + end_index, object( + { + {"op", "remove"}, + {"path", path + "/" + std::to_string(i)} + })); + ++i; + } + + // add other remaining elements + while (i < target.size()) { + result.push_back( + { + {"op", "add"}, + {"path", path + "/-"}, + {"value", target[i]} + }); + ++i; + } + + break; + } + + case value_t::object: { + // first pass: traverse this object's elements + for (auto it = source.cbegin(); it != source.cend(); ++it) { + // escape the key name to be used in a JSON patch + const auto key = json_pointer::escape(it.key()); + + if (target.find(it.key()) != target.end()) { + // recursive call to compare object values at key it + auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key); + result.insert(result.end(), temp_diff.begin(), temp_diff.end()); + } else { + // found a key that is not in o -> remove it + result.push_back(object( + { + {"op", "remove"}, + {"path", path + "/" + key} + })); + } + } + + // second pass: traverse other object's elements + for (auto it = target.cbegin(); it != target.cend(); ++it) { + if (source.find(it.key()) == source.end()) { + // found a key that is not in this -> add it + const auto key = json_pointer::escape(it.key()); + result.push_back( + { + {"op", "add"}, + {"path", path + "/" + key}, + {"value", it.value()} + }); + } + } + + break; + } + + default: { + // both primitive type: replace value + result.push_back( + { + {"op", "replace"}, + {"path", path}, + {"value", target} + }); + break; + } + } + + return result; } - return result; - } + /// @} - /// @} + //////////////////////////////// + // JSON Merge Patch functions // + //////////////////////////////// - //////////////////////////////// - // JSON Merge Patch functions // - //////////////////////////////// + /// @name JSON Merge Patch functions + /// @{ - /// @name JSON Merge Patch functions - /// @{ - - /*! + /*! @brief applies a JSON Merge Patch The merge patch format is primarily intended for use with the HTTP PATCH @@ -25130,34 +23178,25 @@ class basic_json @since version 3.0.0 */ - void merge_patch(const basic_json& apply_patch) - { - if (apply_patch.is_object()) - { - if (!is_object()) - { - *this = object(); - } - for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) - { - if (it.value().is_null()) - { - erase(it.key()); + void merge_patch(const basic_json &apply_patch) { + if (apply_patch.is_object()) { + if (!is_object()) { + *this = object(); } - else - { - operator[](it.key()).merge_patch(it.value()); + for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) { + if (it.value().is_null()) { + erase(it.key()); + } else { + operator[](it.key()).merge_patch(it.value()); + } } + } else { + *this = apply_patch; } } - else - { - *this = apply_patch; - } - } - /// @} -}; + /// @} + }; /*! @brief user-defined to_string function for JSON values @@ -25168,11 +23207,10 @@ This function implements a user-defined to_string for JSON objects. @return a std::string object */ -NLOHMANN_BASIC_JSON_TPL_DECLARATION -std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) -{ - return j.dump(); -} + NLOHMANN_BASIC_JSON_TPL_DECLARATION + std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j) { + return j.dump(); + } } // namespace nlohmann /////////////////////// @@ -25180,40 +23218,35 @@ std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) /////////////////////// // specialization of std::swap, and std::hash -namespace std -{ +namespace std { /// hash value for JSON objects -template<> -struct hash -{ - /*! + template<> + struct hash { + /*! @brief return a hash value for a JSON object @since version 1.0.0 */ - std::size_t operator()(const nlohmann::json& j) const - { - return nlohmann::detail::hash(j); - } -}; + std::size_t operator()(const nlohmann::json &j) const { + return nlohmann::detail::hash(j); + } + }; /// specialization for std::less /// @note: do not remove the space after '<', /// see https://github.com/nlohmann/json/pull/679 -template<> -struct less<::nlohmann::detail::value_t> -{ - /*! + template<> + struct less<::nlohmann::detail::value_t> { + /*! @brief compare two value_t enum values @since version 3.0.0 */ - bool operator()(nlohmann::detail::value_t lhs, - nlohmann::detail::value_t rhs) const noexcept - { - return nlohmann::detail::operator<(lhs, rhs); - } -}; + bool operator()(nlohmann::detail::value_t lhs, + nlohmann::detail::value_t rhs) const noexcept { + return nlohmann::detail::operator<(lhs, rhs); + } + }; // C++20 prohibit function specialization in the std namespace. #ifndef JSON_HAS_CPP_20 @@ -25223,14 +23256,13 @@ struct less<::nlohmann::detail::value_t> @since version 1.0.0 */ -template<> -inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( - is_nothrow_move_constructible::value&& + template<> + inline void swap(nlohmann::json &j1, nlohmann::json &j2) noexcept( + is_nothrow_move_constructible::value && is_nothrow_move_assignable::value - ) -{ - j1.swap(j2); -} + ) { + j1.swap(j2); + } #endif @@ -25250,8 +23282,7 @@ if no parse error occurred. @since version 1.0.0 */ JSON_HEDLEY_NON_NULL(1) -inline nlohmann::json operator "" _json(const char* s, std::size_t n) -{ +inline nlohmann::json operator "" _json(const char *s, std::size_t n) { return nlohmann::json::parse(s, s + n); } @@ -25269,8 +23300,7 @@ object if no parse error occurred. @since version 2.0.0 */ JSON_HEDLEY_NON_NULL(1) -inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) -{ +inline nlohmann::json::json_pointer operator "" _json_pointer(const char *s, std::size_t n) { return nlohmann::json::json_pointer(std::string(s, n)); } @@ -25279,10 +23309,10 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std // restore GCC/clang diagnostic settings #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif #if defined(__clang__) - #pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif // clean up @@ -25443,5 +23473,4 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #undef JSON_HEDLEY_FALL_THROUGH - #endif // INCLUDE_NLOHMANN_JSON_HPP_ \ No newline at end of file