diff --git a/Benchmarks/Tests.hpp b/Benchmarks/Tests.hpp index d60b84692..f125e43be 100644 --- a/Benchmarks/Tests.hpp +++ b/Benchmarks/Tests.hpp @@ -96,7 +96,7 @@ namespace tests { static constexpr bnch_swt::string_literal testNameRead{ testName + "-Read-Raw-Json-Data" }; static constexpr bnch_swt::string_literal testNameWrite{ testName + "-Write-Raw-Json-Data" }; static constexpr bool partialRead{ std::is_same_v> || std::is_same_v }; - static constexpr bool knownOrder{ !std::is_same_v && !std::is_same_v> }; + static constexpr bool knownOrder{ true }; std::vector newStrings{ iterations }; results_data r{ jsonifierLibraryName, testName, jsonifierCommitUrl }; jsonifier::jsonifier_core parser{}; @@ -166,7 +166,7 @@ namespace tests { static constexpr bnch_swt::string_literal testNameRead{ testName + "-Read" }; static constexpr bnch_swt::string_literal testNameWrite{ testName + "-Write" }; static constexpr bool partialRead{ std::is_same_v> || std::is_same_v }; - static constexpr bool knownOrder{ !std::is_same_v && !std::is_same_v> }; + static constexpr bool knownOrder{ true }; results_data r{ jsonifierLibraryName, testName, jsonifierCommitUrl }; jsonifier::jsonifier_core parser{}; std::vector> newStrings{ iterations }; @@ -217,7 +217,7 @@ namespace tests { }); r.readResult = result{ "teal", readResult }; r.writeResult = result{ "steelblue", writeResult }; - bnch_swt::file_loader::saveFile(static_cast(parser.serializeJson(testDatas[0])), + bnch_swt::file_loader::saveFile(static_cast(parser.serializeJson(testDatas)), jsonOutPath.operator std::string() + "/" + testName.operator std::string() + "-jsonifier.json"); return r; } @@ -230,7 +230,7 @@ namespace tests { static constexpr bnch_swt::string_literal testNameRead{ testName + "-Read" }; static constexpr bnch_swt::string_literal testNameWrite{ testName + "-Write" }; static constexpr bool partialRead{ std::is_same_v> || std::is_same_v }; - static constexpr bool knownOrder{ !std::is_same_v && !std::is_same_v> }; + static constexpr bool knownOrder{ true }; results_data r{ jsonifierLibraryName, testName, jsonifierCommitUrl }; jsonifier::jsonifier_core parser{}; std::vector newStrings{ iterations }; @@ -278,7 +278,7 @@ namespace tests { static constexpr bnch_swt::string_literal testNameRead{ testName + "-Read" }; static constexpr bnch_swt::string_literal testNameWrite{ testName + "-Write" }; static constexpr bool partialRead{ std::is_same_v> || std::is_same_v }; - static constexpr bool knownOrder{ !std::is_same_v && !std::is_same_v> }; + static constexpr bool knownOrder{ true }; results_data r{ jsonifierLibraryName, testName, jsonifierCommitUrl }; jsonifier::jsonifier_core parser{}; std::vector newStrings{ iterations }; @@ -422,7 +422,8 @@ namespace tests { testDatas[x].resize(testDataNew[x].size()); } size_t currentIndex{}; - bnch_swt::performance_metrics readResult = bnch_swt::benchmark_stage::template runBenchmark([&]() mutable { + bnch_swt::performance_metrics readResult = + bnch_swt::benchmark_stage::template runBenchmark([&]() mutable { size_t newSize{}; for (size_t x = 0; x < testDatas[currentIndex].size(); ++x) { get_ref_t reference = testDatas[currentIndex][x]; @@ -439,7 +440,7 @@ namespace tests { } ++currentIndex; return newSize; - }); + }); for (size_t x = 0; x < iterations; ++x) { for (size_t y = 0; y < testDataNew[x].size(); ++y) { newStrings[x][y] = std::string{}; @@ -462,7 +463,7 @@ namespace tests { r.readResult = result{ "dodgerblue", readResult }; r.writeResult = result{ "skyblue", writeResult }; std::string newString{}; - auto newResult = glz::write_json(testDatas[0], newString); + auto newResult = glz::write_json(testDatas, newString); ( void )newResult; bnch_swt::file_loader::saveFile(newString, jsonOutPath.operator std::string() + "/" + testName.operator std::string() + "-glaze.json"); return r; @@ -669,7 +670,7 @@ namespace tests { }); r.readResult = result{ "cadetblue", readResult }; std::string newString{}; - auto newResult = glz::write_json(testDatas[0], newString); + auto newResult = glz::write_json(testDatas, newString); ( void )newResult; bnch_swt::file_loader::saveFile(newString, jsonOutPath.operator std::string() + "/" + testName.operator std::string() + "-simdjson.json"); return r; @@ -994,21 +995,13 @@ In contrast, hash-based solutions offer a viable alternative by circumventing th JSONIFIER_CLANG_INLINE void testFunction() { std::string jsonDataNew{}; jsonifier::jsonifier_core parser{}; - std::vector jsonDataSmallNewer{ maxIterations }; - for (size_t x = 0; x < maxIterations; ++x) { - jsonDataSmallNewer[x] = test_generator::generateTestStruct(); - } std::vector> jsonDataNewer{ maxIterations }; for (size_t x = 0; x < maxIterations; ++x) { jsonDataNewer[x] = test_generator::generateTest(); } - parser.serializeJson(jsonDataSmallNewer[0], jsonDataNew); - bnch_swt::file_loader::saveFile(jsonDataNew, jsonOutPath.operator std::string() + "/Json Test (Small) (Prettified).json"); - std::string jsonMinifiedData{ parser.minifyJson(jsonDataNew) }; - bnch_swt::file_loader::saveFile(jsonMinifiedData, jsonOutPath.operator std::string() + "/Json Test (Small) (Minified).json"); parser.serializeJson(jsonDataNewer[0], jsonDataNew); bnch_swt::file_loader::saveFile(jsonDataNew, jsonOutPath.operator std::string() + "/Json Test (Prettified).json"); - jsonMinifiedData = parser.minifyJson(jsonDataNew); + std::string jsonMinifiedData = parser.minifyJson(jsonDataNew); bnch_swt::file_loader::saveFile(jsonMinifiedData, jsonOutPath.operator std::string() + "/Json Test (Minified).json"); bnch_swt::file_loader::saveFile(jsonDataNew, jsonOutPath.operator std::string() + "/Partial Test (Prettified).json"); bnch_swt::file_loader::saveFile(jsonMinifiedData, jsonOutPath.operator std::string() + "/Partial Test (Minified).json"); @@ -1023,51 +1016,45 @@ In contrast, hash-based solutions offer a viable alternative by circumventing th static_cast(section001) }; test_results testResults{}; { - std::vector> doubleData{ test_generator::generateValues(maxIterations, 2500) }; - parser.serializeJson(doubleData[0], jsonDataNew); + std::vector> doubleData{ test_generator::generateValues(maxIterations, 100) }; + parser.serializeJson(doubleData, jsonDataNew); bnch_swt::file_loader::saveFile(jsonDataNew, jsonOutPath.operator std::string() + "/Double Test.json"); testResults = json_tests_helper>, false, maxIterations, "Double Test">::run(doubleData); newerString += testResults.markdownResults; benchmark_data.emplace_back(testResults); } { - std::vector> stringData{ test_generator::generateValues(maxIterations, 2500) }; - parser.serializeJson(stringData[0], jsonDataNew); + std::vector> stringData{ test_generator::generateValues(maxIterations, 100) }; + parser.serializeJson(stringData, jsonDataNew); bnch_swt::file_loader::saveFile(jsonDataNew, jsonOutPath.operator std::string() + "/String Test.json"); testResults = json_tests_helper>, false, maxIterations, "String Test">::run(stringData); newerString += testResults.markdownResults; benchmark_data.emplace_back(testResults); } { - std::vector> uintData{ test_generator::generateValues(maxIterations, 2500) }; - parser.serializeJson(uintData[0], jsonDataNew); + std::vector> uintData{ test_generator::generateValues(maxIterations, 100) }; + parser.serializeJson(uintData, jsonDataNew); bnch_swt::file_loader::saveFile(jsonDataNew, jsonOutPath.operator std::string() + "/Uint Test.json"); testResults = json_tests_helper>, false, maxIterations, "Uint Test">::run(uintData); newerString += testResults.markdownResults; benchmark_data.emplace_back(testResults); } { - std::vector> intData{ test_generator::generateValues(maxIterations, 2500) }; - parser.serializeJson(intData[0], jsonDataNew); + std::vector> intData{ test_generator::generateValues(maxIterations, 100) }; + parser.serializeJson(intData, jsonDataNew); bnch_swt::file_loader::saveFile(jsonDataNew, jsonOutPath.operator std::string() + "/Int Test.json"); testResults = json_tests_helper>, false, maxIterations, "Int Test">::run(intData); newerString += testResults.markdownResults; benchmark_data.emplace_back(testResults); } { - std::vector> boolData{ test_generator::generateValues(maxIterations, 2500) }; - parser.serializeJson(boolData[0], jsonDataNew); + std::vector> boolData{ test_generator::generateValues(maxIterations, 100) }; + parser.serializeJson(boolData, jsonDataNew); bnch_swt::file_loader::saveFile(jsonDataNew, jsonOutPath.operator std::string() + "/Bool Test.json"); testResults = json_tests_helper>, false, maxIterations, "Bool Test">::run(boolData); newerString += testResults.markdownResults; benchmark_data.emplace_back(testResults); } - testResults = json_tests_helper::run(jsonDataSmallNewer); - newerString += testResults.markdownResults; - benchmark_data.emplace_back(testResults); - testResults = json_tests_helper::run(jsonDataSmallNewer); - newerString += testResults.markdownResults; - benchmark_data.emplace_back(testResults); testResults = json_tests_helper, false, maxIterations, "Json Test (Prettified)">::run(jsonDataNewer); newerString += testResults.markdownResults; benchmark_data.emplace_back(testResults); diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ec890c1b..6fc42f5ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,7 +67,7 @@ set(JSONIFIER-AVX512_EXITCODE 0 CACHE INTERNAL "For cross-compiling.") "$" ) -if (NOT JSONIFIER_CPU_INSTRUCTIONS) +if (NOT DEFINED JSONIFIER_CPU_INSTRUCTIONS) include("JsonifierDetectArchitecture") endif() diff --git a/Include/jsonifier/Containers/Allocator.hpp b/Include/jsonifier/Containers/Allocator.hpp index 86e0af713..a0130c027 100644 --- a/Include/jsonifier/Containers/Allocator.hpp +++ b/Include/jsonifier/Containers/Allocator.hpp @@ -67,7 +67,7 @@ namespace jsonifier::internal { using size_type = size_t; using allocator_traits = std::allocator_traits>; - JSONIFIER_INLINE pointer allocate(size_type count) noexcept { + JSONIFIER_INLINE static pointer allocate(size_type count) noexcept { if JSONIFIER_UNLIKELY (count == 0) { return nullptr; } @@ -88,7 +88,7 @@ namespace jsonifier::internal { } } - template JSONIFIER_INLINE void construct(pointer ptr, arg_types&&... args) noexcept { + template JSONIFIER_INLINE static void construct(pointer ptr, arg_types&&... args) noexcept { new (ptr) value_type(internal::forward(args)...); } @@ -96,7 +96,7 @@ namespace jsonifier::internal { return allocator_traits::max_size(alloc_wrapper{}); } - JSONIFIER_INLINE void destroy(pointer ptr) noexcept { + JSONIFIER_INLINE static void destroy(pointer ptr) noexcept { ptr->~value_type(); } }; diff --git a/Include/jsonifier/Containers/Array.hpp b/Include/jsonifier/Containers/Array.hpp index 7bedf9ad2..75313c0b2 100644 --- a/Include/jsonifier/Containers/Array.hpp +++ b/Include/jsonifier/Containers/Array.hpp @@ -28,281 +28,266 @@ namespace jsonifier::internal { - template class array_iterator { + template class array { public: - using iterator_concept = std::contiguous_iterator_tag; - using iterator_category = std::random_access_iterator_tag; - using element_type = value_type_new; - using value_type = value_type_new; - using difference_type = std::ptrdiff_t; - using pointer = value_type*; - using reference = value_type&; + static_assert(std::is_object_v, "The C++ Standard forbids containers of non-object types because of [container.requirements]."); - JSONIFIER_INLINE constexpr array_iterator() noexcept : ptr() { - } + using value_type = value_type_new; + using size_type = size_t; + using difference_type = ptrdiff_t; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using iterator = array_iterator; + using const_iterator = const array_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; - JSONIFIER_INLINE constexpr array_iterator(pointer ptrNew) noexcept : ptr(ptrNew) { + JSONIFIER_INLINE constexpr void fill(const value_type& _Value) { + std::fill_n(dataVal, sizeNew, _Value); } - JSONIFIER_INLINE constexpr reference operator*() const noexcept { - return *ptr; + JSONIFIER_INLINE constexpr void swap(array& _Other) noexcept(std::is_nothrow_swappable::value) { + std::swap_ranges(dataVal, dataVal + sizeNew, _Other.dataVal); } - JSONIFIER_INLINE constexpr pointer operator->() const noexcept { - return std::pointer_traits::pointer_to(**this); + JSONIFIER_INLINE constexpr iterator begin() noexcept { + return iterator(dataVal); } - JSONIFIER_INLINE constexpr array_iterator& operator++() noexcept { - ++ptr; - return *this; + JSONIFIER_INLINE constexpr const_iterator begin() const noexcept { + return const_iterator(dataVal); } - JSONIFIER_INLINE constexpr array_iterator operator++(int32_t) noexcept { - array_iterator temp = *this; - ++*this; - return temp; + JSONIFIER_INLINE constexpr iterator end() noexcept { + return iterator(dataVal); } - JSONIFIER_INLINE constexpr array_iterator& operator--() noexcept { - --ptr; - return *this; + JSONIFIER_INLINE constexpr const_iterator end() const noexcept { + return const_iterator(dataVal); } - JSONIFIER_INLINE constexpr array_iterator operator--(int32_t) noexcept { - array_iterator temp = *this; - --*this; - return temp; + JSONIFIER_INLINE constexpr reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); } - JSONIFIER_INLINE constexpr array_iterator& operator+=(const difference_type offSet) noexcept { - ptr += offSet; - return *this; + JSONIFIER_INLINE constexpr const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator(end()); } - JSONIFIER_INLINE constexpr array_iterator operator+(const difference_type offSet) const noexcept { - array_iterator temp = *this; - temp += offSet; - return temp; + JSONIFIER_INLINE constexpr reverse_iterator rend() noexcept { + return reverse_iterator(begin()); } - JSONIFIER_INLINE friend constexpr array_iterator operator+(const difference_type offSet, array_iterator _Next) noexcept { - _Next += offSet; - return _Next; + JSONIFIER_INLINE constexpr const_reverse_iterator rend() const noexcept { + return const_reverse_iterator(begin()); } - JSONIFIER_INLINE constexpr array_iterator& operator-=(const difference_type offSet) noexcept { - return *this += -offSet; + JSONIFIER_INLINE constexpr const_iterator cbegin() const noexcept { + return begin(); } - JSONIFIER_INLINE constexpr array_iterator operator-(const difference_type offSet) const noexcept { - array_iterator temp = *this; - temp -= offSet; - return temp; + JSONIFIER_INLINE constexpr const_iterator cend() const noexcept { + return end(); } - JSONIFIER_INLINE constexpr difference_type operator-(const array_iterator& other) const noexcept { - return static_cast(ptr - other.ptr); + JSONIFIER_INLINE constexpr const_reverse_iterator crbegin() const noexcept { + return rbegin(); } - JSONIFIER_INLINE constexpr reference operator[](const difference_type offSet) const noexcept { - return *(*this + offSet); + JSONIFIER_INLINE constexpr const_reverse_iterator crend() const noexcept { + return rend(); } - JSONIFIER_INLINE constexpr bool operator==(const array_iterator& other) const noexcept { - return ptr == other.ptr; + JSONIFIER_INLINE constexpr size_type size() const noexcept { + return sizeNew; } - JSONIFIER_INLINE constexpr std::strong_ordering operator<=>(const array_iterator& other) const noexcept { - return ptr <=> other.ptr; + JSONIFIER_INLINE constexpr size_type max_size() const noexcept { + return sizeNew; } - JSONIFIER_INLINE constexpr bool operator!=(const array_iterator& other) const noexcept { - return !(*this == other); + JSONIFIER_INLINE constexpr bool empty() const noexcept { + return false; } - JSONIFIER_INLINE constexpr bool operator<(const array_iterator& other) const noexcept { - return ptr < other.ptr; - } + JSONIFIER_INLINE constexpr reference at(size_type position) { + if (sizeNew <= position) { + std::runtime_error{ "invalid array subscript" }; + } - JSONIFIER_INLINE constexpr bool operator>(const array_iterator& other) const noexcept { - return other < *this; + return dataVal[position]; } - JSONIFIER_INLINE constexpr bool operator<=(const array_iterator& other) const noexcept { - return !(other < *this); + JSONIFIER_INLINE constexpr const_reference at(size_type position) const { + if (sizeNew <= position) { + std::runtime_error{ "invalid array subscript" }; + } + + return dataVal[position]; } - JSONIFIER_INLINE constexpr bool operator>=(const array_iterator& other) const noexcept { - return !(*this < other); + JSONIFIER_INLINE constexpr reference operator[](size_type position) noexcept { + return dataVal[position]; } - pointer ptr; - }; + JSONIFIER_INLINE constexpr const_reference operator[](size_type position) const noexcept { + return dataVal[position]; + } - template class array_iterator { - public: - using iterator_concept = std::contiguous_iterator_tag; - using iterator_category = std::random_access_iterator_tag; - using element_type = value_type_new; - using value_type = value_type_new; - using difference_type = std::ptrdiff_t; - using pointer = value_type*; - using reference = value_type&; + JSONIFIER_INLINE constexpr reference front() noexcept { + return dataVal[0]; + } - JSONIFIER_INLINE constexpr array_iterator() noexcept { + JSONIFIER_INLINE constexpr const_reference front() const noexcept { + return dataVal[0]; } - JSONIFIER_INLINE constexpr array_iterator(std::nullptr_t ptrNew) noexcept { + JSONIFIER_INLINE constexpr reference back() noexcept { + return dataVal[sizeNew - 1]; } - JSONIFIER_INLINE constexpr bool operator==(const array_iterator& other) const noexcept { - return true; + JSONIFIER_INLINE constexpr const_reference back() const noexcept { + return dataVal[sizeNew - 1]; } - JSONIFIER_INLINE constexpr bool operator!=(const array_iterator& other) const noexcept { - return !(*this == other); + JSONIFIER_INLINE constexpr value_type* data() noexcept { + return dataVal; } - JSONIFIER_INLINE constexpr bool operator>=(const array_iterator& other) const noexcept { - return !(*this < other); + JSONIFIER_INLINE constexpr const value_type* data() const noexcept { + return dataVal; } + + value_type dataVal[sizeNew]; }; - template struct array { + struct empty_array_element {}; + + template class array { + public: + static_assert(std::is_object_v, "The C++ Standard forbids containers of non-object types because of [container.requirements]."); + using value_type = value_type_new; + using size_type = size_t; + using difference_type = ptrdiff_t; + using pointer = value_type*; + using const_pointer = const value_type*; using reference = value_type&; using const_reference = const value_type&; - using size_type = size_t; - using iterator = array_iterator; - using const_iterator = array_iterator; + using iterator = array_iterator; + using const_iterator = const array_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - constexpr array() noexcept = default; + JSONIFIER_INLINE constexpr void fill(const value_type&) { + } - constexpr array(std::initializer_list initList) { - for (size_t i = 0; i < initList.size() && i < sizeNew; ++i) { - values[i] = initList.begin()[i]; - } + JSONIFIER_INLINE constexpr void swap(array&) noexcept { } JSONIFIER_INLINE constexpr iterator begin() noexcept { - return iterator{ values }; + return iterator{}; } JSONIFIER_INLINE constexpr const_iterator begin() const noexcept { - return const_iterator{ values }; + return const_iterator{}; } JSONIFIER_INLINE constexpr iterator end() noexcept { - return iterator{ values + sizeNew }; + return iterator{}; } JSONIFIER_INLINE constexpr const_iterator end() const noexcept { - return const_iterator{ values + sizeNew }; + return const_iterator{}; } JSONIFIER_INLINE constexpr reverse_iterator rbegin() noexcept { - return reverse_iterator{ end() }; + return reverse_iterator(end()); } JSONIFIER_INLINE constexpr const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator{ end() }; + return const_reverse_iterator(end()); } JSONIFIER_INLINE constexpr reverse_iterator rend() noexcept { - return reverse_iterator{ begin() }; + return reverse_iterator(begin()); } JSONIFIER_INLINE constexpr const_reverse_iterator rend() const noexcept { - return const_reverse_iterator{ begin() }; + return const_reverse_iterator(begin()); } - JSONIFIER_INLINE constexpr const_reference operator[](size_type index) const noexcept { - return values[index]; + JSONIFIER_INLINE constexpr const_iterator cbegin() const noexcept { + return begin(); } - JSONIFIER_INLINE constexpr reference operator[](size_type index) noexcept { - return values[index]; + JSONIFIER_INLINE constexpr const_iterator cend() const noexcept { + return end(); } - JSONIFIER_INLINE constexpr const value_type* data() const noexcept { - return values; + JSONIFIER_INLINE constexpr const_reverse_iterator crbegin() const noexcept { + return rbegin(); } - JSONIFIER_INLINE constexpr value_type* data() noexcept { - return values; - } - - constexpr void fill(const value_type& value) noexcept { - for (size_t i = 0; i < sizeNew; ++i) { - values[i] = value; - } + JSONIFIER_INLINE constexpr const_reverse_iterator crend() const noexcept { + return rend(); } JSONIFIER_INLINE constexpr size_type size() const noexcept { - return sizeNew; + return 0; } - value_type values[sizeNew]{}; - }; - - template struct array { - using value_type = value_type_new; - using reference = value_type&; - using const_reference = const value_type&; - using pointer = value_type*; - using const_pointer = const value_type*; - using const_iterator = const array_iterator; - using iterator = array_iterator; - using size_type = size_t; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using difference_type = std::ptrdiff_t; + JSONIFIER_INLINE constexpr size_type max_size() const noexcept { + return 0; + } - constexpr array(std::initializer_list) { + JSONIFIER_INLINE constexpr bool empty() const noexcept { + return true; } - JSONIFIER_INLINE constexpr const_pointer data() const noexcept { - return nullptr; + JSONIFIER_INLINE constexpr reference at(size_type) { + std::runtime_error{ "invalid array subscript" }; } - JSONIFIER_INLINE constexpr pointer data() noexcept { - return nullptr; + JSONIFIER_INLINE constexpr const_reference at(size_type) const { + std::runtime_error{ "invalid array subscript" }; } - JSONIFIER_INLINE constexpr size_type size() const noexcept { - return 0; + JSONIFIER_INLINE constexpr reference operator[](size_type) noexcept { + return *data(); } - JSONIFIER_INLINE constexpr const_reference operator[](size_type index) const noexcept { - return dataVal[index]; + JSONIFIER_INLINE constexpr const_reference operator[](size_type) const noexcept { + return *data(); } - JSONIFIER_INLINE constexpr reference operator[](size_type index) noexcept { - return dataVal[index]; + JSONIFIER_INLINE constexpr reference front() noexcept { + return *data(); } - JSONIFIER_INLINE constexpr iterator begin() noexcept { - return iterator{}; + JSONIFIER_INLINE constexpr const_reference front() const noexcept { + return *data(); } - JSONIFIER_INLINE constexpr iterator end() noexcept { - return iterator{}; + JSONIFIER_INLINE constexpr reference back() noexcept { + return *data(); } - JSONIFIER_INLINE constexpr const_iterator begin() const noexcept { - return const_iterator{}; + JSONIFIER_INLINE constexpr const_reference back() const noexcept { + return *data(); } - JSONIFIER_INLINE constexpr const_iterator end() const noexcept { - return const_iterator{}; + JSONIFIER_INLINE constexpr value_type* data() noexcept { + return nullptr; } - constexpr void fill(const value_type&) noexcept { + JSONIFIER_INLINE constexpr const value_type* data() const noexcept { + return nullptr; } - value_type* dataVal{}; + conditional_t, std::is_default_constructible>, value_type, empty_array_element> dataVal[1]{}; }; } \ No newline at end of file diff --git a/Include/jsonifier/Containers/Iterator.hpp b/Include/jsonifier/Containers/Iterator.hpp index 8bb5fb18a..8ca0c6ec4 100644 --- a/Include/jsonifier/Containers/Iterator.hpp +++ b/Include/jsonifier/Containers/Iterator.hpp @@ -137,4 +137,144 @@ namespace jsonifier::internal { pointer ptr; }; + template class array_iterator { + public: + using iterator_concept = std::contiguous_iterator_tag; + using iterator_category = std::random_access_iterator_tag; + using element_type = value_type_new; + using value_type = value_type_new; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + + JSONIFIER_INLINE constexpr array_iterator() noexcept : ptr() { + } + + JSONIFIER_INLINE constexpr array_iterator(pointer ptrNew) noexcept : ptr(ptrNew) { + } + + JSONIFIER_INLINE constexpr reference operator*() const noexcept { + return *ptr; + } + + JSONIFIER_INLINE constexpr pointer operator->() const noexcept { + return std::pointer_traits::pointer_to(**this); + } + + JSONIFIER_INLINE constexpr array_iterator& operator++() noexcept { + ++ptr; + return *this; + } + + JSONIFIER_INLINE constexpr array_iterator operator++(int32_t) noexcept { + array_iterator temp = *this; + ++*this; + return temp; + } + + JSONIFIER_INLINE constexpr array_iterator& operator--() noexcept { + --ptr; + return *this; + } + + JSONIFIER_INLINE constexpr array_iterator operator--(int32_t) noexcept { + array_iterator temp = *this; + --*this; + return temp; + } + + JSONIFIER_INLINE constexpr array_iterator& operator+=(const difference_type offSet) noexcept { + ptr += offSet; + return *this; + } + + JSONIFIER_INLINE constexpr array_iterator operator+(const difference_type offSet) const noexcept { + array_iterator temp = *this; + temp += offSet; + return temp; + } + + JSONIFIER_INLINE friend constexpr array_iterator operator+(const difference_type offSet, array_iterator _Next) noexcept { + _Next += offSet; + return _Next; + } + + JSONIFIER_INLINE constexpr array_iterator& operator-=(const difference_type offSet) noexcept { + return *this += -offSet; + } + + JSONIFIER_INLINE constexpr array_iterator operator-(const difference_type offSet) const noexcept { + array_iterator temp = *this; + temp -= offSet; + return temp; + } + + JSONIFIER_INLINE constexpr difference_type operator-(const array_iterator& other) const noexcept { + return static_cast(ptr - other.ptr); + } + + JSONIFIER_INLINE constexpr reference operator[](const difference_type offSet) const noexcept { + return *(*this + offSet); + } + + JSONIFIER_INLINE constexpr bool operator==(const array_iterator& other) const noexcept { + return ptr == other.ptr; + } + + JSONIFIER_INLINE constexpr std::strong_ordering operator<=>(const array_iterator& other) const noexcept { + return ptr <=> other.ptr; + } + + JSONIFIER_INLINE constexpr bool operator!=(const array_iterator& other) const noexcept { + return !(*this == other); + } + + JSONIFIER_INLINE constexpr bool operator<(const array_iterator& other) const noexcept { + return ptr < other.ptr; + } + + JSONIFIER_INLINE constexpr bool operator>(const array_iterator& other) const noexcept { + return other < *this; + } + + JSONIFIER_INLINE constexpr bool operator<=(const array_iterator& other) const noexcept { + return !(other < *this); + } + + JSONIFIER_INLINE constexpr bool operator>=(const array_iterator& other) const noexcept { + return !(*this < other); + } + + pointer ptr; + }; + + template class array_iterator { + public: + using iterator_concept = std::contiguous_iterator_tag; + using iterator_category = std::random_access_iterator_tag; + using element_type = value_type_new; + using value_type = value_type_new; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + + JSONIFIER_INLINE constexpr array_iterator() noexcept { + } + + JSONIFIER_INLINE constexpr array_iterator(std::nullptr_t ptrNew) noexcept { + } + + JSONIFIER_INLINE constexpr bool operator==(const array_iterator& other) const noexcept { + return true; + } + + JSONIFIER_INLINE constexpr bool operator!=(const array_iterator& other) const noexcept { + return !(*this == other); + } + + JSONIFIER_INLINE constexpr bool operator>=(const array_iterator& other) const noexcept { + return !(*this < other); + } + }; + }// namespace internal \ No newline at end of file diff --git a/Include/jsonifier/Containers/Tuple.hpp b/Include/jsonifier/Containers/Tuple.hpp index 37b838a02..f320c77ae 100644 --- a/Include/jsonifier/Containers/Tuple.hpp +++ b/Include/jsonifier/Containers/Tuple.hpp @@ -154,8 +154,7 @@ namespace jsonifier::internal { return (base_list_t>{} + ...); } - template - static constexpr auto tupleCatImpl(value_type tupleVal, type_list, type_list) + template static constexpr auto tupleCatImpl(value_type tupleVal, type_list, type_list) -> tuple...> { return { { { static_cast&&, inner>>(tupleVal.identity_t::value).value }... } }; } diff --git a/Include/jsonifier/Containers/Vector.hpp b/Include/jsonifier/Containers/Vector.hpp deleted file mode 100644 index a059efa3b..000000000 --- a/Include/jsonifier/Containers/Vector.hpp +++ /dev/null @@ -1,491 +0,0 @@ -/* - MIT License - - Copyright (c) 2024 RealTimeChris - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ -/// https://github.com/RealTimeChris/jsonifier -/// Feb 20, 2023 -#pragma once - -#include -#include -#include - -namespace jsonifier { - - template class vector; - - template class vector : protected std::equal_to, protected internal::alloc_wrapper { - public: - using value_type = value_type_new; - using pointer = value_type*; - using const_pointer = const pointer; - using reference = value_type&; - using const_reference = const value_type&; - using iterator = internal::basic_iterator; - using const_iterator = internal::basic_iterator; - using difference_type = std::ptrdiff_t; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using object_compare = std::equal_to; - using size_type = size_t; - using allocator = internal::alloc_wrapper; - - vector() noexcept { - if constexpr (sizeValNewer > 0) { - reserve(sizeValNewer); - } - } - - template vector(size_type sizeNew, value_type_newer&& values) : capacityVal{}, sizeVal{}, dataVal{} { - auto sizeValNew = sizeNew; - if (sizeValNew > 0 && sizeValNew < maxSize()) { - reserve(sizeValNew); - std::uninitialized_fill(data(), data() + sizeValNew, values); - sizeVal = sizeValNew; - } - } - - vector& operator=(vector&& other) noexcept { - if (this != &other && dataVal != other.dataVal) { - vector{ other }.swap(*this); - } - return *this; - } - - vector(vector&& other) noexcept : capacityVal{}, sizeVal{}, dataVal{} { - swap(other); - } - - vector& operator=(const vector& other) noexcept { - if (this != &other) { - vector{ other }.swap(*this); - } - return *this; - } - - vector(const vector& other) : capacityVal{}, sizeVal{}, dataVal{} { - auto sizeValNew = other.size(); - if (sizeValNew > 0 && sizeValNew < maxSize()) { - reserve(sizeValNew); - std::uninitialized_copy(other.data(), other.data() + sizeValNew, dataVal); - sizeVal = sizeValNew; - } - } - - vector& operator=(std::vector&& other) noexcept { - vector{ other }.swap(*this); - return *this; - } - - explicit vector(std::vector&& other) noexcept : capacityVal{}, sizeVal{}, dataVal{} { - auto sizeValNew = other.size(); - if (sizeValNew > 0 && sizeValNew < maxSize()) { - reserve(sizeValNew); - std::uninitialized_move(other.data(), other.data() + sizeValNew, dataVal); - sizeVal = sizeValNew; - } - } - - vector& operator=(const std::vector& other) noexcept { - vector{ other }.swap(*this); - return *this; - } - - explicit vector(const std::vector& other) : capacityVal{}, sizeVal{}, dataVal{} { - auto sizeValNew = other.size(); - if (sizeValNew > 0 && sizeValNew < maxSize()) { - reserve(sizeValNew); - std::uninitialized_copy(other.data(), other.data() + sizeValNew, dataVal); - sizeVal = sizeValNew; - } - } - - vector(iterator first, iterator last) noexcept { - difference_type insertCount = std::distance(first, last); - if (!first) { - return; - } - if (insertCount == 0) { - return; - } - - size_type insertPosIndex = 0; - size_type newSize = sizeVal + insertCount; - - if (newSize > capacityVal) { - reserve(newSize); - } - - pointer insertPos = dataVal + insertPosIndex; - - for (iterator iter = first; iter < last; ++iter) { - allocator::construct(insertPos++, *iter); - } - - sizeVal = newSize; - } - - vector& operator=(std::initializer_list other) noexcept { - vector{ other }.swap(*this); - return *this; - } - - explicit vector(std::initializer_list other) : capacityVal{}, sizeVal{}, dataVal{} { - auto sizeValNew = other.size(); - if (sizeValNew > 0 && sizeValNew < maxSize()) { - reserve(sizeValNew); - std::uninitialized_move(other.begin(), other.begin() + sizeValNew, dataVal); - sizeVal = sizeValNew; - } - } - - vector& operator=(const value_type& other) noexcept { - emplace_back(other); - return *this; - } - - vector(const value_type& other) : capacityVal{}, sizeVal{}, dataVal{} { - *this = other; - } - - template void assign(size_type count, arg_types&&... newValue) noexcept { - size_type newSize = sizeVal + count; - - if (newSize > capacityVal) { - reserve(newSize); - } - - pointer insertPos = dataVal + sizeVal; - std::uninitialized_fill(insertPos, insertPos + count, newValue...); - sizeVal = newSize; - } - - void insert(iterator where, iterator first, iterator last) noexcept { - size_type insertCount = std::distance(first, last); - - if (insertCount == 0) { - return; - } - - size_type insertPosIndex = where - begin(); - size_type newSize = sizeVal + insertCount; - - if (newSize > capacityVal) { - reserve(newSize); - } - - pointer insertPos = dataVal + insertPosIndex; - - for (iterator iter = first; iter != last; ++iter) { - allocator::construct(insertPos++, *iter); - } - - sizeVal = newSize; - } - - template void insert(iterator where, value_type_newer&& value) { - size_type insertCount = 1; - - if (insertCount == 0) { - return; - } - - size_type insertPosIndex = where - begin(); - size_type newSize = sizeVal + insertCount; - - if (newSize > capacityVal) { - reserve(newSize); - } - - pointer insertPos = dataVal + insertPosIndex; - - allocator::construct(insertPos++, value); - - sizeVal = newSize; - } - - iterator begin() noexcept { - return iterator{ dataVal }; - } - - iterator end() noexcept { - return iterator{ dataVal + sizeVal }; - } - - reverse_iterator rbegin() noexcept { - return reverse_iterator{ end() }; - } - - reverse_iterator rend() noexcept { - return reverse_iterator{ begin() }; - } - - const_iterator begin() const noexcept { - return const_iterator{ dataVal }; - } - - const_iterator end() const noexcept { - return const_iterator{ dataVal + sizeVal }; - } - - const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator{ end() }; - } - - const_reverse_iterator rend() const noexcept { - return const_reverse_iterator{ begin() }; - } - - reference front() noexcept { - return dataVal[0]; - } - - reference back() noexcept { - return dataVal[sizeVal - 1]; - } - - const_reference front() const { - return dataVal[0]; - } - - const_reference back() const { - return dataVal[sizeVal - 1]; - } - - reference at(size_type index) { - if (index >= sizeVal) { - throw std::out_of_range{ "Sorry, but that index is beyond the end of this vector's bounds." }; - } - return dataVal[index]; - } - - const_reference at(size_type index) const { - if (index >= sizeVal) { - throw std::out_of_range{ "Sorry, but that index is beyond the end of this vector's bounds." }; - } - return dataVal[index]; - } - - const_reference operator[](size_type index) const { - return dataVal[index]; - } - - reference operator[](size_type index) noexcept { - return dataVal[index]; - } - - size_type capacity() const { - return capacityVal; - } - - size_type size() const { - return sizeVal; - } - - pointer data() const { - return dataVal; - } - - bool empty() const { - return sizeVal == 0; - } - - pointer data() noexcept { - return dataVal; - } - - operator std::vector() const { - std::vector returnValue{}; - for (auto& value: *this) { - returnValue.emplace_back(value); - } - return returnValue; - } - - template reference emplace_back(value_types&&... c) noexcept { - if (sizeVal + 1 >= capacityVal) { - reserve(capacityVal * 2 + 2); - } - allocator::construct(&dataVal[sizeVal++], std::forward(c)...); - - return dataVal[sizeVal - 1]; - } - - reference emplace_back(value_type&& c) noexcept { - if (sizeVal + 1 >= capacityVal) { - reserve(capacityVal * 2 + 2); - } - allocator::construct(&dataVal[sizeVal++], internal::move(c)); - - return dataVal[sizeVal - 1]; - } - - reference emplace_back(const value_type& c) noexcept { - if (sizeVal + 1 >= capacityVal) { - reserve(capacityVal * 2 + 2); - } - allocator::construct(&dataVal[sizeVal++], c); - - return dataVal[sizeVal - 1]; - } - - void erase(size_type count) noexcept { - if (count >= sizeVal) { - return; - } - size_type newSize = sizeVal - count; - - std::destroy(dataVal, dataVal + count); - - std::uninitialized_move(dataVal + count, dataVal + count + newSize, dataVal); - - sizeVal = newSize; - } - - iterator erase(iterator iter) { - if (iter < begin() || iter > end()) { - return end(); - } - - size_type eraseIndex = static_cast(iter - begin()); - size_type newSize = sizeVal - 1; - - allocator::destroy(dataVal + eraseIndex); - - std::uninitialized_move(dataVal + eraseIndex + 1, dataVal + sizeVal, dataVal + eraseIndex); - - sizeVal = newSize; - return iterator{ dataVal + eraseIndex }; - } - - void shrink_to_fit() noexcept { - if (sizeVal == capacityVal) { - return; - } - - vector newVector{}; - newVector.reserve(sizeVal); - std::uninitialized_move(dataVal, dataVal + sizeVal, newVector.data()); - newVector.sizeVal = sizeVal; - swap(newVector); - } - - constexpr size_type maxSize() noexcept { - return (internal::min)(static_cast((std::numeric_limits::max)()), allocator::maxSize()); - } - - void resize(size_type newSize) { - if JSONIFIER_LIKELY (newSize > capacityVal) { - pointer newPtr = allocator::allocate(newSize); - try { - if (sizeVal > 0ull) { - if constexpr (std::is_copy_constructible_v) { - std::uninitialized_copy(dataVal, dataVal + sizeVal, newPtr); - } else if constexpr (std::is_move_constructible_v) { - std::uninitialized_move(dataVal, dataVal + sizeVal, newPtr); - } - } - if JSONIFIER_LIKELY (dataVal && capacityVal > 0) { - allocator::deallocate(dataVal); - } - } catch (...) { - allocator::deallocate(newPtr); - throw; - } - capacityVal = newSize; - dataVal = newPtr; - std::uninitialized_value_construct(dataVal + sizeVal, dataVal + capacityVal); - } else if JSONIFIER_UNLIKELY (newSize > sizeVal) { - std::uninitialized_value_construct(dataVal + sizeVal, dataVal + capacityVal); - } else if (newSize < sizeVal) { - std::destroy(dataVal + newSize, dataVal + sizeVal); - } - sizeVal = newSize; - } - - void reserve(size_type capacityNew) { - if JSONIFIER_LIKELY (capacityNew > capacityVal) { - pointer newPtr = allocator::allocate(capacityNew); - try { - if JSONIFIER_LIKELY (dataVal && capacityVal > 0) { - if (sizeVal > 0) { - std::uninitialized_move(dataVal, dataVal + sizeVal, newPtr); - } - allocator::deallocate(dataVal); - } - } catch (...) { - allocator::deallocate(newPtr); - throw; - } - capacityVal = capacityNew; - dataVal = newPtr; - } - } - - void clear() noexcept { - std::destroy(dataVal, dataVal + sizeVal); - sizeVal = 0; - } - - void swap(vector& other) noexcept { - std::swap(capacityVal, other.capacityVal); - std::swap(sizeVal, other.sizeVal); - std::swap(dataVal, other.dataVal); - } - - bool operator==(const vector& rhs) const { - if (rhs.size() != size()) { - return false; - } - if constexpr (!std::is_fundamental_v) { - for (size_type x = 0; x < sizeVal; ++x) { - if (!object_compare()(rhs.dataVal[x], dataVal[x])) { - return false; - } - } - return true; - } else { - return internal::comparison::compare(rhs.data(), data(), size()); - } - } - - ~vector() noexcept { - reset(); - }; - - protected: - size_type capacityVal{}; - size_type sizeVal{}; - pointer dataVal{}; - - void reset() noexcept { - if (dataVal && capacityVal) { - if (sizeVal) { - std::destroy(dataVal, dataVal + sizeVal); - sizeVal = 0; - } - allocator::deallocate(dataVal); - dataVal = nullptr; - capacityVal = 0; - } - } - }; - -}// namespace jsonifier \ No newline at end of file diff --git a/Include/jsonifier/Core/JsonifierCore.hpp b/Include/jsonifier/Core/JsonifierCore.hpp index d3d6525b6..2dd67686b 100644 --- a/Include/jsonifier/Core/JsonifierCore.hpp +++ b/Include/jsonifier/Core/JsonifierCore.hpp @@ -67,7 +67,7 @@ namespace jsonifier { *this = other; } - vector& getErrors() noexcept { + std::vector& getErrors() noexcept { return errors; } @@ -80,7 +80,9 @@ namespace jsonifier { using minifier = internal::minifier>; using parser = internal::parser>; - vector errors{}; + string_base stringBuffer{}; + internal::simd_string_reader section{}; + std::vector errors{}; }; } diff --git a/Include/jsonifier/Parsing/Parse_Impl.hpp b/Include/jsonifier/Parsing/Parse_Impl.hpp index 093f2e936..78a3f544b 100644 --- a/Include/jsonifier/Parsing/Parse_Impl.hpp +++ b/Include/jsonifier/Parsing/Parse_Impl.hpp @@ -234,7 +234,7 @@ namespace jsonifier::internal { } } else { if JSONIFIER_LIKELY (const auto indexNew = hash_map>::findIndex(context.iter, context.endIter); - indexNew < memberCount) { + indexNew < memberCount) { if JSONIFIER_LIKELY (functionPtrs[indexNew](value, context)) { if constexpr (options.knownOrder) { antiHashStates[json_entity_type::index] = indexNew; @@ -363,7 +363,7 @@ namespace jsonifier::internal { } } else { if JSONIFIER_LIKELY (const auto indexNew = hash_map>::findIndex(context.iter, context.endIter); - indexNew < memberCount) { + indexNew < memberCount) { if JSONIFIER_LIKELY (functionPtrs[indexNew](value, context)) { if constexpr (options.knownOrder) { antiHashStates[json_entity_type::index] = indexNew; @@ -486,7 +486,7 @@ namespace jsonifier::internal { } else { if JSONIFIER_LIKELY (const auto indexNew = hash_map>::findIndex((*context.iter) + 1, *context.endIter); - indexNew < memberCount) { + indexNew < memberCount) { if JSONIFIER_LIKELY (functionPtrs[indexNew](value, context)) { return; @@ -813,14 +813,52 @@ namespace jsonifier::internal { if JSONIFIER_LIKELY (*context.iter == lBracket) { ++context.currentArrayDepth; ++context.iter; + static constexpr bool newLines{ true }; if JSONIFIER_LIKELY (*context.iter != rBracket) { const auto wsStart = context.iter; JSONIFIER_SKIP_WS(); size_t wsSize{ static_cast(context.iter - wsStart) }; if (auto size = value.size(); size > 0) { - parseObjectsWithSize(value, context, size, wsStart, wsSize); + auto newIter = getBeginIterVec(value); + for (size_t i{}; i != size; ++i) { + parse::impl(newIter[static_cast(i)], context); + + if JSONIFIER_LIKELY (context.iter < context.endIter) { + if JSONIFIER_LIKELY (*context.iter == comma) { + ++context.iter; + JSONIFIER_SKIP_MATCHING_WS(); + } else { + if JSONIFIER_LIKELY (*context.iter == rBracket) { + ++context.iter; + JSONIFIER_SKIP_WS(); + --context.currentArrayDepth; + return (i + 1 < size) ? value.resize(i + 1) : noop(); + } else { + context.parserPtr->template reportError(context); + base::skipToNextValue(context); + return; + } + } + } + JSONIFIER_ELSE_UNLIKELY(else) { + context.parserPtr->template reportError(context); + base::skipToNextValue(context); + return; + } + } + } + parse::impl(value.emplace_back(), context); + + while (context.iter < context.endIter && *context.iter == comma) { + ++context.iter; + JSONIFIER_SKIP_MATCHING_WS() + parse::impl(value.emplace_back(), context); + } + if JSONIFIER_LIKELY (context.iter < context.endIter && *context.iter == rBracket) { } else { - parseObjects(value, context, wsStart, wsSize); + context.parserPtr->template reportError(context); + base::skipToNextValue(context); + return; } } ++context.iter; @@ -838,53 +876,6 @@ namespace jsonifier::internal { return; } } - - template - JSONIFIER_INLINE static void parseObjectsWithSize(value_type& value, context_type& context, size_t size, const auto wsStart = {}, size_t wsSize = {}) { - auto newIter = getBeginIterVec(value); - - for (size_t i{}; i != size; ++i) { - parse::impl(newIter[static_cast(i)], context); - - if JSONIFIER_LIKELY (context.iter < context.endIter) { - if JSONIFIER_LIKELY (*context.iter == comma) { - ++context.iter; - JSONIFIER_SKIP_MATCHING_WS(); - } else { - if JSONIFIER_LIKELY (*context.iter == rBracket) { - return (i + 1 < size) ? value.resize(i + 1) : noop(); - } else { - context.parserPtr->template reportError(context); - base::skipToNextValue(context); - return; - } - } - } - JSONIFIER_ELSE_UNLIKELY(else) { - context.parserPtr->template reportError(context); - base::skipToNextValue(context); - return; - } - } - parseObjects(value, context, wsStart, wsSize); - } - - template JSONIFIER_INLINE static void parseObjects(value_type& value, context_type& context, const auto wsStart = {}, size_t wsSize = {}) { - parse::impl(value.emplace_back(), context); - - while (context.iter < context.endIter && *context.iter == comma) { - ++context.iter; - JSONIFIER_SKIP_MATCHING_WS() - parse::impl(value.emplace_back(), context); - } - if JSONIFIER_LIKELY (context.iter < context.endIter && *context.iter == rBracket) { - return; - } else { - context.parserPtr->template reportError(context); - base::skipToNextValue(context); - return; - } - } }; template struct parse_impl { diff --git a/Include/jsonifier/Parsing/Parser.hpp b/Include/jsonifier/Parsing/Parser.hpp index 01ef08250..519d47aff 100644 --- a/Include/jsonifier/Parsing/Parser.hpp +++ b/Include/jsonifier/Parsing/Parser.hpp @@ -109,8 +109,7 @@ namespace jsonifier::internal { } template struct parse { - template - JSONIFIER_INLINE static void impl(value_type_new&& value, context_type&& context) noexcept { + template JSONIFIER_INLINE static void impl(value_type_new&& value, context_type&& context) noexcept { using value_type = remove_cvref_t; if constexpr (options.partialRead) { if constexpr (concepts::map_t || concepts::jsonifier_object_t) { @@ -140,6 +139,7 @@ namespace jsonifier::internal { template class parser { public: friend class jsonifier::raw_json_data; + template friend struct derailleur; using derived_type = derived_type_new; @@ -153,15 +153,15 @@ namespace jsonifier::internal { constexpr parse_context_partial context{ constEval(parse_context_partial{}) }; auto rootIter = getBeginIter(in); auto endIter = getEndIter(in); - section.reset(rootIter, static_cast(endIter - rootIter)); - context.rootIter = section.begin(); - context.iter = section.begin(); - context.endIter = section.end(); + derivedRef.section.template reset(rootIter, static_cast(endIter - rootIter)); + context.rootIter = derivedRef.section.begin(); + context.iter = derivedRef.section.begin(); + context.endIter = derivedRef.section.end(); context.remainingMemberCount = static_cast(countTotalNonRepeatedMembers()); context.parserPtr = this; auto newSize = static_cast((context.endIter - context.iter) / 2); - if (stringBuffer.size() < newSize) { - stringBuffer.resize(newSize); + if (derivedRef.stringBuffer.size() < newSize) { + derivedRef.stringBuffer.resize(newSize); } if constexpr (options.validateJson) { if (!derivedRef.validateJson(in)) { @@ -183,8 +183,8 @@ namespace jsonifier::internal { context.endIter = getEndIter(in); context.parserPtr = this; auto newSize = static_cast((context.endIter - context.iter) / 2); - if (stringBuffer.size() < newSize) { - stringBuffer.resize(newSize); + if (derivedRef.stringBuffer.size() < newSize) { + derivedRef.stringBuffer.resize(newSize); } if constexpr (options.validateJson) { if (!derivedRef.validateJson(in)) { @@ -214,8 +214,8 @@ namespace jsonifier::internal { context.endIter = getEndIter(in); context.parserPtr = this; auto newSize = static_cast((context.endIter - context.iter) / 2); - if (stringBuffer.size() < newSize) { - stringBuffer.resize(newSize); + if (derivedRef.stringBuffer.size() < newSize) { + derivedRef.stringBuffer.resize(newSize); } if constexpr (options.validateJson) { if (!derivedRef.validateJson(in)) { @@ -243,15 +243,15 @@ namespace jsonifier::internal { constexpr parse_context_partial context{ constEval(parse_context_partial{}) }; auto rootIter = getBeginIter(in); auto endIter = getEndIter(in); - section.reset(rootIter, static_cast(endIter - rootIter)); - context.rootIter = section.begin(); - context.iter = section.begin(); - context.endIter = section.end(); + derivedRef.section.template reset(rootIter, static_cast(endIter - rootIter)); + context.rootIter = derivedRef.section.begin(); + context.iter = derivedRef.section.begin(); + context.endIter = derivedRef.section.end(); context.remainingMemberCount = countTotalNonRepeatedMembers(); context.parserPtr = this; auto newSize = static_cast((context.endIter - context.iter) / 2); - if (stringBuffer.size() < newSize) { - stringBuffer.resize(newSize); + if (derivedRef.stringBuffer.size() < newSize) { + derivedRef.stringBuffer.resize(newSize); } if constexpr (options.validateJson) { if (!derivedRef.validateJson(in)) { @@ -274,8 +274,8 @@ namespace jsonifier::internal { context.endIter = getEndIter(in); context.parserPtr = this; auto newSize = static_cast((context.endIter - context.iter) / 2); - if (stringBuffer.size() < newSize) { - stringBuffer.resize(newSize); + if (derivedRef.stringBuffer.size() < newSize) { + derivedRef.stringBuffer.resize(newSize); } if constexpr (options.validateJson) { if (!derivedRef.validateJson(in)) { @@ -309,6 +309,10 @@ namespace jsonifier::internal { parser() noexcept : derivedRef{ initializeSelfRef() } {}; + JSONIFIER_INLINE auto& getStringBuffer() noexcept { + return derivedRef.stringBuffer; + } + derived_type& initializeSelfRef() noexcept { return *static_cast(this); } diff --git a/Include/jsonifier/Parsing/Validate_Impl.hpp b/Include/jsonifier/Parsing/Validate_Impl.hpp index af08b0470..94fb98b05 100644 --- a/Include/jsonifier/Parsing/Validate_Impl.hpp +++ b/Include/jsonifier/Parsing/Validate_Impl.hpp @@ -118,7 +118,8 @@ namespace jsonifier::internal { auto newPtr = *iter; ++iter; auto endPtr = *iter; - newPtr = string_parser::impl(newPtr, stringBuffer.data(), static_cast(endPtr - newPtr)); + newPtr = string_parser::impl(newPtr, validatorRef.getStringBuffer().data(), + static_cast(endPtr - newPtr)); if JSONIFIER_LIKELY (newPtr) { return true; } diff --git a/Include/jsonifier/Parsing/Validator.hpp b/Include/jsonifier/Parsing/Validator.hpp index 0458e94bb..ce32c97f6 100644 --- a/Include/jsonifier/Parsing/Validator.hpp +++ b/Include/jsonifier/Parsing/Validator.hpp @@ -25,10 +25,9 @@ #include #include -#include #include -namespace jsonifier::internal { +namespace jsonifier::internal { template struct validate_impl; @@ -41,11 +40,11 @@ namespace jsonifier::internal { template JSONIFIER_INLINE bool validateJson(string_type&& in) noexcept { derivedRef.errors.clear(); - section.reset(in.data(), in.size()); + derivedRef.section.template reset(in.data(), in.size()); rootIter = in.data(); endIter = in.data() + in.size(); - string_view_ptr* iter{ section.begin() }; - string_view_ptr* end{ section.end() }; + string_view_ptr* iter{ derivedRef.section.begin() }; + string_view_ptr* end{ derivedRef.section.end() }; if (!iter) { getErrors().emplace_back(error::constructError(0, 0, nullptr)); return false; @@ -93,11 +92,15 @@ namespace jsonifier::internal { } } + JSONIFIER_INLINE auto& getStringBuffer() noexcept { + return derivedRef.stringBuffer; + } + derived_type& initializeSelfRef() noexcept { return *static_cast(this); } - jsonifier::vector& getErrors() noexcept { + std::vector& getErrors() noexcept { return derivedRef.errors; } diff --git a/Include/jsonifier/Serializing/Minifier.hpp b/Include/jsonifier/Serializing/Minifier.hpp index dbfa2b3b8..26f87c936 100644 --- a/Include/jsonifier/Serializing/Minifier.hpp +++ b/Include/jsonifier/Serializing/Minifier.hpp @@ -52,7 +52,7 @@ namespace jsonifier::internal { returnValues['{'] = object_start; returnValues['}'] = object_end; return returnValues; - }(); + }(); template class minifier { public: @@ -60,23 +60,23 @@ namespace jsonifier::internal { JSONIFIER_INLINE minifier(const minifier& other) = delete; template JSONIFIER_INLINE auto minifyJson(string_type&& in) noexcept { - if JSONIFIER_UNLIKELY (stringBuffer.size() < in.size()) { - stringBuffer.resize(in.size()); + if JSONIFIER_UNLIKELY (derivedRef.stringBuffer.size() < in.size()) { + derivedRef.stringBuffer.resize(in.size()); } derivedRef.errors.clear(); rootIter = in.data(); endIter = rootIter + in.size(); - section.reset(rootIter, in.size()); - string_view_ptr* iter{ section.begin() }; + derivedRef.section.template reset(rootIter, in.size()); + string_view_ptr* iter{ derivedRef.section.begin() }; jsonifier::internal::remove_cvref_t newString{}; if (!*iter) { getErrors().emplace_back(error::constructError(*iter - rootIter, in.end() - in.begin(), rootIter)); return newString; } - auto index = impl(iter, stringBuffer); + auto index = impl(iter, derivedRef.stringBuffer); if (index != std::numeric_limits::max()) { newString.resize(index); - std::memcpy(newString.data(), stringBuffer.data(), index); + std::memcpy(newString.data(), derivedRef.stringBuffer.data(), index); return newString; } else { return jsonifier::internal::remove_cvref_t{}; @@ -84,24 +84,24 @@ namespace jsonifier::internal { } template JSONIFIER_INLINE bool minifyJson(string_type01&& in, string_type02&& buffer) noexcept { - if JSONIFIER_UNLIKELY (stringBuffer.size() < in.size()) { - stringBuffer.resize(in.size()); + if JSONIFIER_UNLIKELY (derivedRef.stringBuffer.size() < in.size()) { + derivedRef.stringBuffer.resize(in.size()); } derivedRef.errors.clear(); rootIter = in.data(); endIter = rootIter + in.size(); - section.reset(rootIter, in.size()); - string_view_ptr* iter{ section.begin() }; + derivedRef.section.template reset(rootIter, in.size()); + string_view_ptr* iter{ derivedRef.section.begin() }; if (!*iter) { getErrors().emplace_back(error::constructError(*iter - rootIter, in.end() - in.begin(), rootIter)); return false; } - auto index = impl(iter, stringBuffer); + auto index = impl(iter, derivedRef.stringBuffer); if JSONIFIER_LIKELY (index != std::numeric_limits::max()) { if JSONIFIER_LIKELY (buffer.size() != index) { buffer.resize(index); } - std::memcpy(buffer.data(), stringBuffer.data(), index); + std::memcpy(buffer.data(), derivedRef.stringBuffer.data(), index); return true; } else { return false; @@ -239,7 +239,7 @@ namespace jsonifier::internal { return *static_cast(this); } - JSONIFIER_INLINE jsonifier::vector& getErrors() noexcept { + JSONIFIER_INLINE std::vector& getErrors() noexcept { return derivedRef.errors; } diff --git a/Include/jsonifier/Serializing/Prettifier.hpp b/Include/jsonifier/Serializing/Prettifier.hpp index 6064ee89e..279b4c0e1 100644 --- a/Include/jsonifier/Serializing/Prettifier.hpp +++ b/Include/jsonifier/Serializing/Prettifier.hpp @@ -36,7 +36,7 @@ namespace jsonifier { } -namespace jsonifier::internal { +namespace jsonifier::internal { template class prettifier { public: @@ -44,26 +44,26 @@ namespace jsonifier::internal { inline prettifier(const prettifier& other) = delete; template inline auto prettifyJson(string_type&& in) noexcept { - if JSONIFIER_UNLIKELY (stringBuffer.size() < in.size() * 5) { - stringBuffer.resize(in.size() * 5); + if JSONIFIER_UNLIKELY (derivedRef.stringBuffer.size() < in.size() * 5) { + derivedRef.stringBuffer.resize(in.size() * 5); } static constexpr prettify_options optionsFinal{ options }; const auto* dataPtr = in.data(); derivedRef.errors.clear(); rootIter = dataPtr; endIter = dataPtr + in.size(); - section.reset(dataPtr, in.size()); - string_view_ptr* iter{ section.begin() }; + derivedRef.section.template reset(dataPtr, in.size()); + string_view_ptr* iter{ derivedRef.section.begin() }; if JSONIFIER_UNLIKELY (!*iter) { getErrors().emplace_back( error::constructError(getUnderlyingPtr(iter) - dataPtr, in.end() - in.begin(), dataPtr)); return jsonifier::internal::remove_cvref_t{}; } jsonifier::internal::remove_cvref_t newString{}; - auto index = impl(iter, stringBuffer); + auto index = impl(iter, derivedRef.stringBuffer); if JSONIFIER_LIKELY (index != std::numeric_limits::max()) { newString.resize(index); - std::memcpy(newString.data(), stringBuffer.data(), index); + std::memcpy(newString.data(), derivedRef.stringBuffer.data(), index); return newString; } else { return jsonifier::internal::remove_cvref_t{}; @@ -72,27 +72,27 @@ namespace jsonifier::internal { template inline bool prettifyJson(string_type01&& in, string_type02&& buffer) noexcept { - if JSONIFIER_UNLIKELY (stringBuffer.size() < in.size() * 5) { - stringBuffer.resize(in.size() * 5); + if JSONIFIER_UNLIKELY (derivedRef.stringBuffer.size() < in.size() * 5) { + derivedRef.stringBuffer.resize(in.size() * 5); } static constexpr prettify_options optionsFinal{ options }; derivedRef.errors.clear(); const auto* dataPtr = in.data(); rootIter = dataPtr; endIter = dataPtr + in.size(); - section.reset(dataPtr, in.size()); - string_view_ptr* iter{ section.begin() }; + derivedRef.section.template reset(dataPtr, in.size()); + string_view_ptr* iter{ derivedRef.section.begin() }; if JSONIFIER_UNLIKELY (!*iter) { getErrors().emplace_back( error::constructError(getUnderlyingPtr(iter) - dataPtr, in.end() - in.begin(), dataPtr)); return false; } - auto index = impl(iter, stringBuffer); + auto index = impl(iter, derivedRef.stringBuffer); if JSONIFIER_LIKELY (index != std::numeric_limits::max()) { if JSONIFIER_LIKELY (buffer.size() != index) { buffer.resize(index); } - std::memcpy(buffer.data(), stringBuffer.data(), index); + std::memcpy(buffer.data(), derivedRef.stringBuffer.data(), index); return true; } else { return false; @@ -101,7 +101,7 @@ namespace jsonifier::internal { protected: derived_type& derivedRef{ initializeSelfRef() }; - jsonifier::vector state{}; + std::vector state{}; string_view_ptr rootIter{}; string_view_ptr endIter{}; @@ -113,7 +113,7 @@ namespace jsonifier::internal { return *static_cast(this); } - inline jsonifier::vector& getErrors() noexcept { + inline std::vector& getErrors() noexcept { return derivedRef.errors; } diff --git a/Include/jsonifier/Serializing/Serializer.hpp b/Include/jsonifier/Serializing/Serializer.hpp index 95515318e..453aeb67c 100644 --- a/Include/jsonifier/Serializing/Serializer.hpp +++ b/Include/jsonifier/Serializing/Serializer.hpp @@ -28,7 +28,7 @@ #include #include -namespace jsonifier::internal { +namespace jsonifier::internal { template struct serialize_impl; @@ -40,7 +40,6 @@ namespace jsonifier::internal { }; template struct serialize_context { - JSONIFIER_INLINE serialize_context& operator=(const serialize_context& other) noexcept { bufferPtr = other.bufferPtr; buffer = other.buffer; @@ -52,10 +51,11 @@ namespace jsonifier::internal { JSONIFIER_INLINE serialize_context(const serialize_context& other) noexcept { *this = other; } - + JSONIFIER_INLINE serialize_context() noexcept = default; - JSONIFIER_INLINE serialize_context(string_buffer_ptr ptrNew, buffer_type& bufferNew) noexcept : bufferPtr{ ptrNew }, buffer{ bufferNew } {} + JSONIFIER_INLINE serialize_context(string_buffer_ptr ptrNew, buffer_type& bufferNew) noexcept : bufferPtr{ ptrNew }, buffer{ bufferNew } { + } string_buffer_ptr bufferPtr{}; buffer_type& buffer{}; @@ -71,20 +71,20 @@ namespace jsonifier::internal { template JSONIFIER_INLINE bool serializeJson(value_type&& object, buffer_type&& buffer) noexcept { static constexpr serialize_options options{ optionsNew }; - serialize_context context{ stringBuffer.data(), stringBuffer }; + serialize_context context{ derivedRef.stringBuffer.data(), derivedRef.stringBuffer }; serialize::impl(object, context); context.index = static_cast(context.bufferPtr - context.buffer.data()); buffer.resize(context.index); - std::copy(stringBuffer.data(), stringBuffer.data() + context.index, buffer.data()); + std::copy(derivedRef.stringBuffer.data(), derivedRef.stringBuffer.data() + context.index, buffer.data()); return true; } template JSONIFIER_INLINE string_view serializeJson(value_type&& object) noexcept { static constexpr serialize_options options{ optionsNew }; - serialize_context context{ stringBuffer.data(), stringBuffer }; + serialize_context context{ derivedRef.stringBuffer.data(), derivedRef.stringBuffer }; serialize::impl(object, context); context.index = static_cast(context.bufferPtr - context.buffer.data()); - return string_view{ stringBuffer.data(), context.index }; + return string_view{ derivedRef.stringBuffer.data(), context.index }; } protected: diff --git a/Include/jsonifier/Simd/AVX.hpp b/Include/jsonifier/Simd/AVX.hpp index 917da5561..9555aa2aa 100644 --- a/Include/jsonifier/Simd/AVX.hpp +++ b/Include/jsonifier/Simd/AVX.hpp @@ -71,11 +71,13 @@ namespace jsonifier::simd { return static_cast(_mm_movemask_epi8(_mm_cmpgt_epi8(_mm_add_epi8(other, offset), _mm_add_epi8(value, offset)))); } - template JSONIFIER_INLINE static auto opCmpEqRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpEqRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { return _mm_cmpeq_epi8(value, other); } - template JSONIFIER_INLINE static auto opCmpLtRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpLtRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { const jsonifier_simd_int_128 offset = _mm_set1_epi8(static_cast(0x80)); return _mm_cmpgt_epi8(_mm_add_epi8(other, offset), _mm_add_epi8(value, offset)); } @@ -84,7 +86,8 @@ namespace jsonifier::simd { return _mm_movemask_epi8(value); } - template JSONIFIER_INLINE static auto opCmpEqBitMask(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpEqBitMask(const simd_int_t01& value, const simd_int_t02& other) noexcept { return static_cast(_mm_movemask_epi8(_mm_cmpeq_epi8(value, other))); } @@ -169,11 +172,13 @@ namespace jsonifier::simd { return static_cast(_mm256_movemask_epi8(_mm256_cmpgt_epi8(_mm256_add_epi8(other, offset), _mm256_add_epi8(value, offset)))); } - template JSONIFIER_INLINE static auto opCmpEqRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpEqRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { return _mm256_cmpeq_epi8(value, other); } - template JSONIFIER_INLINE static auto opCmpLtRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpLtRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { const jsonifier_simd_int_256 offset = _mm256_set1_epi8(static_cast(0x80)); return _mm256_cmpgt_epi8(_mm256_add_epi8(other, offset), _mm256_add_epi8(value, offset)); } @@ -182,7 +187,8 @@ namespace jsonifier::simd { return _mm256_movemask_epi8(value); } - template JSONIFIER_INLINE static auto opCmpEqBitMask(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpEqBitMask(const simd_int_t01& value, const simd_int_t02& other) noexcept { return static_cast(_mm256_movemask_epi8(_mm256_cmpeq_epi8(value, other))); } @@ -266,11 +272,13 @@ namespace jsonifier::simd { return static_cast(_mm512_cmpgt_epi8_mask(other, value)); } - template JSONIFIER_INLINE static auto opCmpEqRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpEqRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { return _mm512_maskz_set1_epi8(_mm512_cmpeq_epi8_mask(value, other), 0xFF); } - template JSONIFIER_INLINE static auto opCmpLtRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpLtRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { return _mm512_maskz_set1_epi8(_mm512_cmpeq_epi8_mask(value, other), 0xFF); } @@ -278,7 +286,8 @@ namespace jsonifier::simd { return _mm512_movepi8_mask(value); } - template JSONIFIER_INLINE static auto opCmpEqBitMask(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpEqBitMask(const simd_int_t01& value, const simd_int_t02& other) noexcept { return static_cast(_mm512_cmpeq_epi8_mask(value, other)); } diff --git a/Include/jsonifier/Simd/CTimeSimdTypes.hpp b/Include/jsonifier/Simd/CTimeSimdTypes.hpp index aeb4b2d4a..a0f71ec9c 100644 --- a/Include/jsonifier/Simd/CTimeSimdTypes.hpp +++ b/Include/jsonifier/Simd/CTimeSimdTypes.hpp @@ -85,17 +85,18 @@ namespace jsonifier::simd { #endif }; - template constexpr uint16_t mm128MovemaskEpi8Impl(const simd_int_t01& a, jsonifier::internal::index_sequence&&) noexcept { + template + JSONIFIER_INLINE static constexpr uint16_t mm128MovemaskEpi8Impl(const simd_int_t01& a, jsonifier::internal::index_sequence&&) noexcept { uint16_t mask{}; ((mask |= (a.m128x_int8[indices] & 0x80) ? (1 << indices) : 0), ...); return mask; } - template constexpr uint16_t mm128MovemaskEpi8(const simd_int_t01& a) noexcept { + template JSONIFIER_INLINE static constexpr uint16_t mm128MovemaskEpi8(const simd_int_t01& a) noexcept { return mm128MovemaskEpi8Impl(a, jsonifier::internal::make_index_sequence<16>{}); } - constexpr __m128x mm128AddEpi8(const __m128x& a, const __m128x& b) noexcept { + JSONIFIER_INLINE static constexpr __m128x mm128AddEpi8(const __m128x& a, const __m128x& b) noexcept { __m128x result; for (int32_t i = 0; i < 16; ++i) { result.m128x_int8[i] = static_cast(a.m128x_int8[i] + b.m128x_int8[i]); @@ -103,7 +104,7 @@ namespace jsonifier::simd { return result; } - constexpr __m128x mm128CmpGtEpi8(const __m128x& a, const __m128x& b) noexcept { + JSONIFIER_INLINE static constexpr __m128x mm128CmpGtEpi8(const __m128x& a, const __m128x& b) noexcept { __m128x result; for (size_t i = 0; i < 16; ++i) { @@ -113,7 +114,7 @@ namespace jsonifier::simd { return result; } - constexpr __m128x mm128Set1Epi8(uint8_t value) noexcept { + JSONIFIER_INLINE static constexpr __m128x mm128Set1Epi8(uint8_t value) noexcept { __m128x result; size_t repeated_value = 0; @@ -128,7 +129,7 @@ namespace jsonifier::simd { return result; } - template constexpr __m128x mm128OrSi128(const simd_int_t01& valOne, const simd_int_t02& valTwo) noexcept { + template JSONIFIER_INLINE static constexpr __m128x mm128OrSi128(const simd_int_t01& valOne, const simd_int_t02& valTwo) noexcept { __m128x value{}; std::copy(valOne.m128x_uint64, valOne.m128x_uint64 + 2, value.m128x_uint64); value.m128x_uint64[0] |= valTwo.m128x_uint64[0]; @@ -136,7 +137,8 @@ namespace jsonifier::simd { return value; } - template constexpr __m128x mm128AndSi128(const simd_int_t01& valOne, const simd_int_t02& valTwo) noexcept { + template + JSONIFIER_INLINE static constexpr __m128x mm128AndSi128(const simd_int_t01& valOne, const simd_int_t02& valTwo) noexcept { __m128x value{}; std::copy(valOne.m128x_uint64, valOne.m128x_uint64 + 2, value.m128x_uint64); value.m128x_uint64[0] &= valTwo.m128x_uint64[0]; @@ -144,7 +146,8 @@ namespace jsonifier::simd { return value; } - template constexpr __m128x mm128AndNotSi128(const simd_int_t01& valOne, const simd_int_t02& valTwo) noexcept { + template + JSONIFIER_INLINE static constexpr __m128x mm128AndNotSi128(const simd_int_t01& valOne, const simd_int_t02& valTwo) noexcept { __m128x value{}; std::copy(valOne.m128x_uint64, valOne.m128x_uint64 + 2, value.m128x_uint64); value.m128x_uint64[0] &= ~valOne.m128x_uint64[0]; @@ -152,7 +155,8 @@ namespace jsonifier::simd { return value; } - template constexpr __m128x mm128XorSi128(const simd_int_t01& valOne, const simd_int_t02& valTwo) noexcept { + template + JSONIFIER_INLINE static constexpr __m128x mm128XorSi128(const simd_int_t01& valOne, const simd_int_t02& valTwo) noexcept { __m128x value{}; std::copy(valOne.m128x_uint64, valOne.m128x_uint64 + 2, value.m128x_uint64); value.m128x_uint64[0] ^= valTwo.m128x_uint64[0]; @@ -161,38 +165,38 @@ namespace jsonifier::simd { } template - constexpr __m128x mm128CmpEqEpi8Impl(const simd_int_t01& a, const simd_int_t02& b, jsonifier::internal::index_sequence&&) noexcept { + JSONIFIER_INLINE static constexpr __m128x mm128CmpEqEpi8Impl(const simd_int_t01& a, const simd_int_t02& b, jsonifier::internal::index_sequence&&) noexcept { __m128x result{}; ((result.m128x_int8[indices] = (a.m128x_int8[indices] == b.m128x_int8[indices]) ? 0xFF : 0), ...); return result; } - template constexpr __m128x mm128CmpEqEpi8(const simd_int_t01& a, const simd_int_t02& b) noexcept { + template JSONIFIER_INLINE static constexpr __m128x mm128CmpEqEpi8(const simd_int_t01& a, const simd_int_t02& b) noexcept { return mm128CmpEqEpi8Impl(a, b, jsonifier::internal::make_index_sequence<16>{}); } - template constexpr bool mm128TestzSi128(simd_int_t01& valOneNew, simd_int_t02& valTwo) noexcept { + template JSONIFIER_INLINE static constexpr bool mm128TestzSi128(simd_int_t01& valOneNew, simd_int_t02& valTwo) noexcept { std::remove_const_t valOne{ valOneNew }; valOne.m128x_uint64[0] &= valTwo.m128x_uint64[0]; valOne.m128x_uint64[1] &= valTwo.m128x_uint64[1]; return valOne.m128x_uint64[0] == 0 && valOne.m128x_uint64[1] == 0; } - constexpr __m128x mm128SetEpi64x(size_t argOne, size_t argTwo) noexcept { + JSONIFIER_INLINE static constexpr __m128x mm128SetEpi64x(size_t argOne, size_t argTwo) noexcept { __m128x returnValue{}; std::copy(&argOne, &argOne + 1, returnValue.m128x_uint64); std::copy(&argTwo, &argTwo + 1, returnValue.m128x_uint64 + 1); return returnValue; } - constexpr __m128x mm128Set1Epi64x(size_t argOne) noexcept { + JSONIFIER_INLINE static constexpr __m128x mm128Set1Epi64x(size_t argOne) noexcept { __m128x returnValue{}; std::copy(&argOne, &argOne + 1, returnValue.m128x_uint64); std::copy(&argOne, &argOne + 1, returnValue.m128x_uint64 + 1); return returnValue; } - constexpr void mm128StoreUSi128(uint8_t* ptr, const __m128x& data) noexcept { + JSONIFIER_INLINE static constexpr void mm128StoreUSi128(uint8_t* ptr, const __m128x& data) noexcept { for (int32_t i = 0; i < 8; ++i) { ptr[i] = static_cast(data.m128x_uint64[0] >> (i * 8)); } @@ -202,26 +206,26 @@ namespace jsonifier::simd { } } - template constexpr void mm128StoreUSi128(value_type* ptr, const __m128x& data) noexcept { + template JSONIFIER_INLINE static constexpr void mm128StoreUSi128(value_type* ptr, const __m128x& data) noexcept { for (int32_t i = 0; i < 2; ++i) { ptr[i] = static_cast(data.m128x_uint64[i]); } } - template constexpr uint32_t get32(const value_type* data, int32_t index) noexcept { + template JSONIFIER_INLINE static constexpr uint32_t get32(const value_type* data, int32_t index) noexcept { return (data[index / 2] >> (32 * (index % 2))) & 0xFFFFFFFF; } - template constexpr void set32(value_type* data, int32_t index, uint32_t value) noexcept { + template JSONIFIER_INLINE static constexpr void set32(value_type* data, int32_t index, uint32_t value) noexcept { data[index / 2] &= ~(0xFFFFFFFFull << (32 * (index % 2))); data[index / 2] |= (static_cast(value) << (32 * (index % 2))); } - template constexpr void set64(value_type* data, int32_t index, size_t value) noexcept { + template JSONIFIER_INLINE static constexpr void set64(value_type* data, int32_t index, size_t value) noexcept { data[index] = value; } - constexpr __m128x mm128ShuffleEpi32(const __m128x& a, int32_t imm8) noexcept { + JSONIFIER_INLINE static constexpr __m128x mm128ShuffleEpi32(const __m128x& a, int32_t imm8) noexcept { __m128x result{}; set32(result.m128x_uint64, 0, get32(a.m128x_uint64, (imm8 >> 0) & 0x3)); set32(result.m128x_uint64, 1, get32(a.m128x_uint64, (imm8 >> 2) & 0x3)); @@ -230,26 +234,26 @@ namespace jsonifier::simd { return result; } - template constexpr __m128x mm128LoadUSi128(const __m128x* ptr) noexcept { + template JSONIFIER_INLINE static constexpr __m128x mm128LoadUSi128(const __m128x* ptr) noexcept { return *ptr; } template requires(sizeof(value_type) == 8) - constexpr __m128x mm128LoadUSi128(const value_type* ptr) noexcept { + JSONIFIER_INLINE static constexpr __m128x mm128LoadUSi128(const value_type* ptr) noexcept { __m128x returnValues{}; returnValues.m128x_uint64[0] = ptr[0]; returnValues.m128x_uint64[1] = ptr[1]; return returnValues; } - constexpr __m128x mm128LoadUSi128(const __m128x* ptr) noexcept { + JSONIFIER_INLINE static constexpr __m128x mm128LoadUSi128(const __m128x* ptr) noexcept { __m128x returnValues{ *ptr }; return returnValues; } template - constexpr __m128x mm128ShuffleEpi8(const simd_int_t01& a, const simd_int_t02& b, jsonifier::internal::index_sequence) noexcept { + JSONIFIER_INLINE static constexpr __m128x mm128ShuffleEpi8(const simd_int_t01& a, const simd_int_t02& b, jsonifier::internal::index_sequence) noexcept { __m128x result{}; size_t index{}; (((index = b.m128x_uint8[indices] & 0x0F), (result.m128x_uint8[indices] = a.m128x_uint8[index])), ...); diff --git a/Include/jsonifier/Simd/Fallback.hpp b/Include/jsonifier/Simd/Fallback.hpp index d778efe15..34ab8e26f 100644 --- a/Include/jsonifier/Simd/Fallback.hpp +++ b/Include/jsonifier/Simd/Fallback.hpp @@ -73,16 +73,19 @@ namespace jsonifier::simd { return static_cast(mm128MovemaskEpi8(mm128CmpGtEpi8(mm128AddEpi8(other, offset), mm128AddEpi8(value, offset)))); } - template JSONIFIER_INLINE static auto opCmpEqRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpEqRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { return mm128CmpEqEpi8(value, other); } - template JSONIFIER_INLINE static auto opCmpLtRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpLtRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { jsonifier_simd_int_128 offset = mm128Set1Epi8(static_cast(0x80)); return mm128CmpEqEpi8(mm128AddEpi8(other, offset), mm128AddEpi8(value, offset)); } - template JSONIFIER_INLINE static auto opCmpEqBitMask(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpEqBitMask(const simd_int_t01& value, const simd_int_t02& other) noexcept { return static_cast(mm128MovemaskEpi8(mm128CmpEqEpi8(value, other))); } diff --git a/Include/jsonifier/Simd/JsonifierCPUInstructions.hpp b/Include/jsonifier/Simd/JsonifierCPUInstructions.hpp index 08939d0c5..87664e879 100644 --- a/Include/jsonifier/Simd/JsonifierCPUInstructions.hpp +++ b/Include/jsonifier/Simd/JsonifierCPUInstructions.hpp @@ -24,7 +24,7 @@ #pragma once #undef JSONIFIER_CPU_INSTRUCTIONS -#define JSONIFIER_CPU_INSTRUCTIONS 38 +#define JSONIFIER_CPU_INSTRUCTIONS 0 #if !defined(JSONIFIER_CHECK_FOR_INSTRUCTION) #define JSONIFIER_CHECK_FOR_INSTRUCTION(x) (JSONIFIER_CPU_INSTRUCTIONS & x) diff --git a/Include/jsonifier/Simd/Neon.hpp b/Include/jsonifier/Simd/Neon.hpp index f18ca213e..4d25f82b0 100644 --- a/Include/jsonifier/Simd/Neon.hpp +++ b/Include/jsonifier/Simd/Neon.hpp @@ -70,11 +70,13 @@ namespace jsonifier::simd { return vget_lane_u64(vreinterpret_u64_u8(vshrn_n_u16(vcgtq_u8(other, value), 4)), 0); } - template JSONIFIER_INLINE static auto opCmpEqRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpEqRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { return vceqq_u8(value, other); } - template JSONIFIER_INLINE static auto opCmpLtRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpLtRaw(const simd_int_t01& value, const simd_int_t02& other) noexcept { return vcgtq_u8(other, value); } @@ -91,7 +93,8 @@ namespace jsonifier::simd { return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0); } - template JSONIFIER_INLINE static auto opCmpEqBitMask(const simd_int_t01& value, const simd_int_t02& other) noexcept { + template + JSONIFIER_INLINE static auto opCmpEqBitMask(const simd_int_t01& value, const simd_int_t02& other) noexcept { return opBitMask(vceqq_u8(value, other)); } diff --git a/Include/jsonifier/Simd/SimdCommon.hpp b/Include/jsonifier/Simd/SimdCommon.hpp index e764be7ca..f71a7af13 100644 --- a/Include/jsonifier/Simd/SimdCommon.hpp +++ b/Include/jsonifier/Simd/SimdCommon.hpp @@ -50,7 +50,7 @@ namespace jsonifier::simd { #if defined(JSONIFIER_MAC) using avx_integer_list = - internal::type_list, internal::type_holder<16, internal::avx_type_wrapper, uint64_t, 16>, + internal::type_list, internal::type_holder<16, internal::avx_type_wrapper, uint64_t, 64>, internal::type_holder<32, internal::avx_type_wrapper, uint32_t, 32>, internal::type_holder<64, internal::avx_type_wrapper, uint64_t, 64>>; #else @@ -149,7 +149,7 @@ namespace jsonifier::simd { template JSONIFIER_INLINE static jsonifier_simd_int_t opFollows(const simd_int_t01& value, bool& overflow) noexcept { const bool oldOverflow = overflow; - overflow = opGetMSB(value); + overflow = opGetMSB(value); return opSetLSB(opShl<1>(value), oldOverflow); } @@ -161,7 +161,7 @@ namespace jsonifier::simd { }; template JSONIFIER_ALIGN(bytesPerStep) - constexpr internal::array escapeableArray00{ [] { + JSONIFIER_INLINE_VARIABLE internal::array escapeableArray00{ [] { constexpr const uint8_t values[]{ 0x00u, 0x00u, '"', 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, '\\', 0x00u, 0x00u, 0x00u }; internal::array returnValues{}; for (uint64_t x = 0; x < size; ++x) { @@ -171,7 +171,7 @@ namespace jsonifier::simd { }() }; template JSONIFIER_ALIGN(bytesPerStep) - constexpr internal::array escapeableArray01{ [] { + JSONIFIER_INLINE_VARIABLE internal::array escapeableArray01{ [] { constexpr const uint8_t values[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, '\b', 0x00u, 0x00u, 0x00u, 0x0Cu, '\r', 0x00u, 0x00u }; internal::array returnValues{}; for (uint64_t x = 0; x < size; ++x) { @@ -181,7 +181,7 @@ namespace jsonifier::simd { }() }; template JSONIFIER_ALIGN(bytesPerStep) - constexpr internal::array whitespaceArray{ [] { + JSONIFIER_INLINE_VARIABLE internal::array whitespaceArray{ [] { constexpr const uint8_t values[]{ 0x20u, 0x64u, 0x64u, 0x64u, 0x11u, 0x64u, 0x71u, 0x02u, 0x64u, '\t', '\n', 0x70u, 0x64u, '\r', 0x64u, 0x64u }; internal::array returnValues{}; for (uint64_t x = 0; x < size; ++x) { @@ -191,7 +191,7 @@ namespace jsonifier::simd { }() }; template JSONIFIER_ALIGN(bytesPerStep) - constexpr internal::array opArray{ [] { + JSONIFIER_INLINE_VARIABLE internal::array opArray{ [] { constexpr const uint8_t values[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, ':', '{', ',', '}', 0x00u, 0x00u }; internal::array returnValues{}; for (uint64_t x = 0; x < size; ++x) { @@ -233,7 +233,7 @@ namespace jsonifier::simd { template JSONIFIER_INLINE static jsonifier_simd_int_t collectValues(const jsonifier_simd_int_t* values) noexcept { static constexpr auto c{ cNew }; - JSONIFIER_ALIGN(bytesPerStep) jsonifier_string_parsing_type valuesNew[stridesPerStep]; + JSONIFIER_ALIGN(bytesPerStep) jsonifier_string_parsing_type valuesNew[stridesPerStep ]; const jsonifier_simd_int_t simdValue{ gatherValue(c) }; valuesNew[0] = opCmpEqBitMask(simdValue, values[0]); valuesNew[1] = opCmpEqBitMask(simdValue, values[1]); @@ -261,7 +261,7 @@ namespace jsonifier::simd { namespace jsonifier::internal { - constexpr array whitespaceTable{ [] { + JSONIFIER_INLINE_VARIABLE array whitespaceTable{ [] { array returnValues{}; returnValues['\t'] = true; returnValues[' '] = true; diff --git a/Include/jsonifier/Simd/SimdTypes.hpp b/Include/jsonifier/Simd/SimdTypes.hpp index 592770251..0a1d7585d 100644 --- a/Include/jsonifier/Simd/SimdTypes.hpp +++ b/Include/jsonifier/Simd/SimdTypes.hpp @@ -38,15 +38,15 @@ namespace jsonifier { using jsonifier_simd_int_512 = __m512i; #if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) - using jsonifier_simd_int_t = __m512i; + using jsonifier_simd_int_t = __m512i; using jsonifier_string_parsing_type = size_t; static constexpr size_t bitsPerStep{ 512 }; #elif JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) - using jsonifier_simd_int_t = __m256i; + using jsonifier_simd_int_t = __m256i; using jsonifier_string_parsing_type = uint32_t; static constexpr size_t bitsPerStep{ 256 }; #elif JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX) - using jsonifier_simd_int_t = __m128i; + using jsonifier_simd_int_t = __m128i; using jsonifier_string_parsing_type = uint16_t; static constexpr size_t bitsPerStep{ 128 }; #endif @@ -61,7 +61,7 @@ namespace jsonifier { using jsonifier_simd_int_256 = uint32_t; using jsonifier_simd_int_512 = size_t; - using jsonifier_simd_int_t = uint8x16_t; + using jsonifier_simd_int_t = uint8x16_t; using jsonifier_string_parsing_type = uint16_t; static constexpr size_t bitsPerStep{ 128 }; @@ -73,7 +73,7 @@ namespace jsonifier { using jsonifier_simd_int_256 = uint32_t; using jsonifier_simd_int_512 = size_t; - using jsonifier_simd_int_t = jsonifier::simd::__m128x; + using jsonifier_simd_int_t = jsonifier::simd::__m128x; using jsonifier_string_parsing_type = uint16_t; static constexpr size_t bitsPerStep{ 128 }; diff --git a/Include/jsonifier/Utilities/Compare.hpp b/Include/jsonifier/Utilities/Compare.hpp index ec469446d..d2d3c6c1a 100644 --- a/Include/jsonifier/Utilities/Compare.hpp +++ b/Include/jsonifier/Utilities/Compare.hpp @@ -286,13 +286,13 @@ namespace jsonifier::internal { template requires(string.length == 0) - constexpr auto packValues() { + static constexpr auto packValues() { return uint8_t{}; } template requires(string.length > 0 && string.length <= 8) - constexpr auto packValues() { + static constexpr auto packValues() { convert_length_to_int_t returnValues{}; for (size_t x = 0; x < string.length; ++x) { returnValues |= static_cast>(static_cast(string[x]) << ((x % 8) * 8)); @@ -300,7 +300,7 @@ namespace jsonifier::internal { return returnValues; } - template constexpr size_t getPackingSize() { + template static constexpr size_t getPackingSize() { if constexpr (size >= 64) { return 64; } else if constexpr (size >= 32) { @@ -312,7 +312,7 @@ namespace jsonifier::internal { template requires(string.length != 0 && string.length > 8) - constexpr auto packValues() { + static constexpr auto packValues() { JSONIFIER_ALIGN(16) array(getPackingSize())> returnValues{}; for (size_t x = 0; x < string.length; ++x) { if (x / 8 < (string.length / 8) + 1) { @@ -340,14 +340,14 @@ namespace jsonifier::internal { template concept gt_16 = value_type::length > 16 && !eq_16 && !eq_32 && !eq_64; - template constexpr auto stringLiteralFromView(string_type str) noexcept { + template static constexpr auto stringLiteralFromView(string_type str) noexcept { string_literal sl{}; std::copy_n(str.data(), str.size(), sl.values); sl[index] = '\0'; return sl; } - template constexpr auto offSetNewLiteral() noexcept { + template static constexpr auto offSetNewLiteral() noexcept { constexpr size_t originalSize = string.length; constexpr size_t newSize = (offset >= originalSize) ? 0 : originalSize - offset; string_literal sl{}; @@ -358,7 +358,7 @@ namespace jsonifier::internal { return sl; } - template constexpr auto offSetIntoLiteral() noexcept { + template static constexpr auto offSetIntoLiteral() noexcept { constexpr size_t originalSize = string.length; constexpr size_t newSize = (offset >= originalSize) ? originalSize : offset; string_literal sl{}; @@ -455,7 +455,7 @@ namespace jsonifier::internal { #endif #if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) - template struct string_literal_comparitor { + template struct string_literal_comparitor { JSONIFIER_INLINE static bool impl(string_view_ptr str) noexcept { static constexpr auto newLiteral{ stringNew }; JSONIFIER_ALIGN(64) static constexpr auto valuesNew{ packValues() }; @@ -466,7 +466,7 @@ namespace jsonifier::internal { }; #endif - constexpr auto getOffsetIntoLiteralSize(size_t inputSize) noexcept { + static constexpr auto getOffsetIntoLiteralSize(size_t inputSize) noexcept { if (inputSize >= 64 && bytesPerStep >= 64) { return 64; } else if (inputSize >= 32 && bytesPerStep >= 32) { diff --git a/Include/jsonifier/Utilities/DragonBox.hpp b/Include/jsonifier/Utilities/DragonBox.hpp index ec22b258c..28a58c841 100644 --- a/Include/jsonifier/Utilities/DragonBox.hpp +++ b/Include/jsonifier/Utilities/DragonBox.hpp @@ -982,8 +982,8 @@ namespace jsonifier_jkj { return { r.significand, r.exponent, is_negative }; } - template JSONIFIER_INLINE static constexpr signed_decimal_fp add_sign_to_unsigned_decimal_fp( - bool is_negative, unsigned_decimal_fp r) noexcept { + template JSONIFIER_INLINE static constexpr signed_decimal_fp + add_sign_to_unsigned_decimal_fp(bool is_negative, unsigned_decimal_fp r) noexcept { return { r.significand, r.exponent, r.may_have_trailing_zeros, is_negative }; } @@ -2211,7 +2211,7 @@ namespace jsonifier_jkj { template struct multiplication_traits, detail::wuint::uint128, 128> : public multiplication_traits_base, detail::wuint::uint128, 128> { - static constexpr compute_mul_result compute_mul(carrier_uint u, const cache_entry_type& cache) noexcept { + JSONIFIER_INLINE static constexpr compute_mul_result compute_mul(carrier_uint u, const cache_entry_type& cache) noexcept { const auto r = detail::wuint::umul192_upper128(u, cache); return { r.high(), r.low() == 0 }; } @@ -2306,7 +2306,7 @@ namespace jsonifier_jkj { template - JSONIFIER_SAFEBUFFERS static constexpr return_type compute_nearest( + JSONIFIER_INLINE JSONIFIER_SAFEBUFFERS static constexpr return_type compute_nearest( signed_significand_bits s, exponent_int exponent_bits) noexcept { using cache_holder_type = typename CachePolicy::template cache_holder_type; static_assert(min_k >= cache_holder_type::min_k && max_k <= cache_holder_type::max_k, ""); @@ -2547,7 +2547,8 @@ namespace jsonifier_jkj { } template - JSONIFIER_SAFEBUFFERS static constexpr return_type compute_left_closed_directed( + JSONIFIER_INLINE JSONIFIER_SAFEBUFFERS static constexpr return_type + compute_left_closed_directed( signed_significand_bits s, exponent_int exponent_bits) noexcept { using cache_holder_type = typename CachePolicy::template cache_holder_type; static_assert(min_k >= cache_holder_type::min_k && max_k <= cache_holder_type::max_k, ""); @@ -2664,7 +2665,7 @@ namespace jsonifier_jkj { } template - JSONIFIER_SAFEBUFFERS static constexpr return_type compute_right_closed_directed( + JSONIFIER_INLINE JSONIFIER_SAFEBUFFERS static constexpr return_type compute_right_closed_directed( signed_significand_bits s, exponent_int exponent_bits) noexcept { using cache_holder_type = typename CachePolicy::template cache_holder_type; static_assert(min_k >= cache_holder_type::min_k && max_k <= cache_holder_type::max_k, ""); @@ -2827,11 +2828,11 @@ namespace jsonifier_jkj { template struct detector_default_pair_list {}; // Check if a given policy belongs to one of the kinds specified by the library. - template constexpr bool check_policy_validity(dummy, detector_default_pair_list<>) noexcept { + template JSONIFIER_INLINE constexpr bool check_policy_validity(dummy, detector_default_pair_list<>) noexcept { return false; } - template - JSONIFIER_INLINE static constexpr bool check_policy_validity(dummy, detector_default_pair_list) noexcept { + template JSONIFIER_INLINE static constexpr bool check_policy_validity( + dummy, detector_default_pair_list) noexcept { return typename FirstDetectorDefaultPair::kind_detector{}(dummy{}) || check_policy_validity(dummy{}, detector_default_pair_list{}); } @@ -2840,8 +2841,8 @@ namespace jsonifier_jkj { template JSONIFIER_INLINE static constexpr bool check_policy_list_validity(DetectorDefaultPairList) noexcept { return true; } - template - JSONIFIER_INLINE static constexpr bool check_policy_list_validity(DetectorDefaultPairList, dummy first_policy, dummy... remaining_policies) { + template JSONIFIER_INLINE static constexpr bool check_policy_list_validity( + DetectorDefaultPairList, dummy first_policy, dummy... remaining_policies) { return check_policy_validity(first_policy, DetectorDefaultPairList{}) && check_policy_list_validity(DetectorDefaultPairList{}, remaining_policies...); } diff --git a/Include/jsonifier/Utilities/Error.hpp b/Include/jsonifier/Utilities/Error.hpp index da1c7ad80..ea0f027f7 100644 --- a/Include/jsonifier/Utilities/Error.hpp +++ b/Include/jsonifier/Utilities/Error.hpp @@ -194,10 +194,6 @@ namespace jsonifier::internal { return returnValues; }() }; - static bool isNumberType(uint8_t c) noexcept { - return numberTable[c]; - } - static string convertChar(char value) { switch (value) { [[unlikely]] case '\b': { return R"(\b)"; } diff --git a/Include/jsonifier/Utilities/FastFloat.hpp b/Include/jsonifier/Utilities/FastFloat.hpp index 0d641d678..4b31aa0f9 100644 --- a/Include/jsonifier/Utilities/FastFloat.hpp +++ b/Include/jsonifier/Utilities/FastFloat.hpp @@ -279,8 +279,8 @@ namespace jsonifier_fast_float { answer.low = _umul128(a, b, &answer.high);// _umul128 not available on ARM64 #elif defined(JSONIFIER_FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__) __uint128_t r = (( __uint128_t )a) * b; - answer.low = uint64_t(r); - answer.high = uint64_t(r >> 64); + answer.low = static_cast(r); + answer.high = static_cast(r >> 64); #else answer.low = umul128_generic(a, b, &answer.high); #endif @@ -319,7 +319,7 @@ namespace jsonifier_fast_float { inline static constexpr int32_t max_exponent_fast_path = (sizeof(value_type) == 4) ? 10 : 22; inline static constexpr int32_t max_exponent_round_to_even = (sizeof(value_type) == 4) ? 10 : 23; inline static constexpr int32_t min_exponent_round_to_even = (sizeof(value_type) == 4) ? -17 : -4; - inline static constexpr uint64_t max_mantissa_fast_path_value = uint64_t(2) << mantissa_explicit_bits; + inline static constexpr uint64_t max_mantissa_fast_path_value = 2ull << mantissa_explicit_bits; inline static constexpr int32_t largest_power_of_ten = (sizeof(value_type) == 4) ? 38 : 308; inline static constexpr int32_t smallest_power_of_ten = (sizeof(value_type) == 4) ? -64 : -342; inline static constexpr uint64_t max_digits = (sizeof(value_type) == 4) ? 114 : 769; @@ -368,7 +368,7 @@ namespace jsonifier_fast_float { 0x1000000 / (constant_55555 * 5 * 5 * 5 * 5), 0x1000000 / (constant_55555 * constant_55555), 0x1000000 / (constant_55555 * constant_55555 * 5) }; }; - template JSONIFIER_INLINE static constexpr void to_float(bool negative, adjusted_mantissa am, value_type& value) noexcept { + template inline static constexpr void to_float(bool negative, adjusted_mantissa am, value_type& value) noexcept { using fastfloat_uint = typename binary_format::equiv_uint; fastfloat_uint word = ( fastfloat_uint )am.mantissa; word |= fastfloat_uint(am.power2) << binary_format::mantissa_explicit_bits; @@ -377,8 +377,8 @@ namespace jsonifier_fast_float { } template inline static constexpr uint64_t int_cmp_zeros{ (sizeof(char_t) == 1) ? 0x3030303030303030 - : (sizeof(char_t) == 2) ? (uint64_t(char_t('0')) << 48 | uint64_t(char_t('0')) << 32 | uint64_t(char_t('0')) << 16 | char_t('0')) - : (uint64_t(char_t('0')) << 32 | char_t('0')) }; + : (sizeof(char_t) == 2) ? (static_cast(char_t('0')) << 48 | static_cast(char_t('0')) << 32 | static_cast(char_t('0')) << 16 | char_t('0')) + : (static_cast(char_t('0')) << 32 | char_t('0')) }; template inline static constexpr int32_t int_cmp_len{ sizeof(uint64_t) / sizeof(char_t) }; template struct int_luts { @@ -429,7 +429,7 @@ namespace jsonifier_fast_float { val -= 0x3030303030303030; val = (val * 10) + (val >> 8);// val = (val * 2561) >> 8; val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32; - return uint32_t(val); + return static_cast(val); } // Call this if chars are definitely 8 digits. @@ -456,7 +456,7 @@ namespace jsonifier_fast_float { constexpr uint64_t mul2 = 0x0000271000000001;// 1 + (10000ULL << 32) val = (val * 10) + (val >> 8);// val = (val * 2561) >> 8; val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32; - return uint32_t(val); + return static_cast(val); } JSONIFIER_INLINE static uint32_t parse_two_digits_unrolled_no_sub(uint64_t val) { @@ -682,7 +682,7 @@ namespace jsonifier_fast_float { // power_of_five_128[index]); gives the exact answer. value128 firstproduct = full_multiplication(w, powers::power_of_five_128[index]); static_assert((bit_precision >= 0) && (bit_precision <= 64), " precision should be in (0,64]"); - constexpr uint64_t precision_mask = (bit_precision < 64) ? (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision) : uint64_t(0xFFFFFFFFFFFFFFFF); + constexpr uint64_t precision_mask = (bit_precision < 64) ? (static_cast(0xFFFFFFFFFFFFFFFF) >> bit_precision) : static_cast(0xFFFFFFFFFFFFFFFF); if ((firstproduct.high & precision_mask) == precision_mask) {// could further guard with (lower + w < lower) // regarding the second product, we only need secondproduct.high, but our // expectation is that the compiler will optimize this extra work away if @@ -725,7 +725,7 @@ namespace jsonifier_fast_float { // packed. However, in some very rare cases, the computation will fail. In such // cases, we return an adjusted_mantissa with a negative power of 2: the caller // should recompute in such cases. - template JSONIFIER_INLINE static constexpr adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept { + template inline static constexpr adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept { adjusted_mantissa answer; if ((w == 0) || (q < binary::smallest_power_of_ten)) { answer.power2 = 0; @@ -769,8 +769,8 @@ namespace jsonifier_fast_float { answer.mantissa = product.high >> shift; answer.power2 = int32_t(power(int32_t(q)) + upperbit - lz - binary::minimum_exponent); - constexpr auto shifted1{ uint64_t(1) << binary::mantissa_explicit_bits }; - constexpr auto shifted2{ uint64_t(2) << binary::mantissa_explicit_bits }; + constexpr auto shifted1{ 1ull << binary::mantissa_explicit_bits }; + constexpr auto shifted2{ 2ull << binary::mantissa_explicit_bits }; if (answer.power2 <= 0) {// we have a subnormal? // Here have that answer.power2 <= 0 so -answer.power2 >= 0 if (-answer.power2 + 1 >= 64) {// if we have more than 64 bits below the minimum exponent, you @@ -808,7 +808,7 @@ namespace jsonifier_fast_float { // ... we dropped out only zeroes. But if this happened, then we can go // back!!! if ((answer.mantissa << shift) == product.high) { - answer.mantissa &= ~uint64_t(1);// flip it so that we do not round up + answer.mantissa &= ~1ull;// flip it so that we do not round up } } @@ -1034,12 +1034,12 @@ namespace jsonifier_fast_float { value128 z = full_multiplication(x, y); bool overflow; z.low = scalar_add(z.low, carry, overflow); - z.high += uint64_t(overflow);// cannot overflow + z.high += static_cast(overflow);// cannot overflow carry = z.high; return z.low; #endif #else - uint64_t z = uint64_t(x) * uint64_t(y) + uint64_t(carry); + uint64_t z = static_cast(x) * static_cast(y) + static_cast(carry); carry = limb(z >> limb_bits); return limb(z); #endif @@ -1210,8 +1210,8 @@ namespace jsonifier_fast_float { #ifdef JSONIFIER_FASTFLOAT_64BIT_LIMB vec.push_unchecked(value); #else - vec.push_unchecked(uint32_t(value)); - vec.push_unchecked(uint32_t(value >> 32)); + vec.push_unchecked(static_cast(value)); + vec.push_unchecked(static_cast(value >> 32)); #endif vec.normalize(); } @@ -1459,8 +1459,8 @@ namespace jsonifier_fast_float { // round an extended-precision float to the nearest machine float. template JSONIFIER_INLINE static constexpr void round(adjusted_mantissa& am, callback cb) noexcept { constexpr int32_t mantissa_shift = 64 - binary_format::mantissa_explicit_bits - 1; - constexpr auto shifted2{ uint64_t(2) << binary_format::mantissa_explicit_bits }; - constexpr auto shifted1{ uint64_t(1) << binary_format::mantissa_explicit_bits }; + constexpr auto shifted2{ 2ull << binary_format::mantissa_explicit_bits }; + constexpr auto shifted1{ 1ull << binary_format::mantissa_explicit_bits }; if (-am.power2 >= mantissa_shift) { int32_t shift = -am.power2 + 1; cb(am, std::min(shift, 64)); @@ -1485,8 +1485,8 @@ namespace jsonifier_fast_float { } template JSONIFIER_INLINE static constexpr void round_nearest_tie_even(adjusted_mantissa& am, int32_t shift, callback cb) noexcept { - const uint64_t mask = (shift == 64) ? UINT64_MAX : (uint64_t(1) << shift) - 1; - const uint64_t halfway = (shift == 0) ? 0 : uint64_t(1) << (shift - 1); + const uint64_t mask = (shift == 64) ? UINT64_MAX : (1ull << shift) - 1; + const uint64_t halfway = (shift == 0) ? 0 : 1ull << (shift - 1); uint64_t truncated_bits = am.mantissa & mask; bool is_above = truncated_bits > halfway; bool is_halfway = truncated_bits == halfway; @@ -1500,7 +1500,7 @@ namespace jsonifier_fast_float { am.power2 += shift; bool is_odd = (am.mantissa & 1) == 1; - am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above)); + am.mantissa += static_cast(cb(is_odd, is_halfway, is_above)); } JSONIFIER_INLINE static constexpr void round_down(adjusted_mantissa& am, int32_t shift) noexcept { @@ -1663,7 +1663,7 @@ namespace jsonifier_fast_float { } template JSONIFIER_INLINE static constexpr adjusted_mantissa positive_digit_comp(bigint& bigmant, int32_t exponent) noexcept { - bigmant.pow10(uint32_t(exponent)); + bigmant.pow10(static_cast(exponent)); adjusted_mantissa answer; bool truncated; answer.mantissa = bigmant.hi64(truncated); @@ -1703,14 +1703,14 @@ namespace jsonifier_fast_float { // scale real digits and theor digits to be same power. int32_t pow2_exp = theor_exp - real_exp; - uint32_t pow5_exp = uint32_t(-real_exp); + uint32_t pow5_exp = static_cast(-real_exp); if (pow5_exp != 0) { theor_digits.pow5(pow5_exp); } if (pow2_exp > 0) { - theor_digits.pow2(uint32_t(pow2_exp)); + theor_digits.pow2(static_cast(pow2_exp)); } else if (pow2_exp < 0) { - real_digits.pow2(uint32_t(-pow2_exp)); + real_digits.pow2(static_cast(-pow2_exp)); } // compare digits, and use it to director rounding @@ -1745,7 +1745,7 @@ namespace jsonifier_fast_float { // `b` as a big-integer type, scaled to the same binary exponent as // the actual digits. we then compare the big integer representations // of both, and use that to direct rounding. - template JSONIFIER_INLINE static constexpr adjusted_mantissa digit_comp(span& integer, span& fraction, + template inline static constexpr adjusted_mantissa digit_comp(span& integer, span& fraction, uint64_t mantissa, int64_t exponent, adjusted_mantissa am) noexcept { // remove the invalid exponent bias am.power2 -= invalid_am_bias; diff --git a/Include/jsonifier/Utilities/HashMap.hpp b/Include/jsonifier/Utilities/HashMap.hpp index d42eadcf0..55de99af3 100644 --- a/Include/jsonifier/Utilities/HashMap.hpp +++ b/Include/jsonifier/Utilities/HashMap.hpp @@ -177,8 +177,7 @@ namespace jsonifier::internal { struct first_byte_and_unique_index_data { static constexpr size_t storageSize{ 256 }; - constexpr first_byte_and_unique_index_data(const hash_map_construction_data& newData) noexcept - : uniqueIndices{ newData.uniqueIndices }, type{ newData.type } {}; + constexpr first_byte_and_unique_index_data(const hash_map_construction_data& newData) noexcept : uniqueIndices{ newData.uniqueIndices }, type{ newData.type } {}; array uniqueIndices{}; hash_map_type type{}; }; @@ -567,7 +566,7 @@ namespace jsonifier::internal { template constexpr static auto generateMappingsForLengths(const tuple_references& keys, const array& uniqueIndices) noexcept { std::array mappings{}; - std::fill(mappings.data(), mappings.data() + mappings.size(), std::numeric_limits::max()); + std::fill(mappings.data(), mappings.data() + mappings.size(), static_cast(mappings.size() - 1)); for (size_t x = 0; x < keys.count; ++x) { const auto& key = keys.rootPtr[x].key; @@ -584,11 +583,21 @@ namespace jsonifier::internal { return mappings; } - template + template constexpr char getMaxFirstByte(const array& keys) noexcept { + char returnValue{}; + for (size_t x = 0; x < firstCharCount; ++x) { + if (keys[x].value > returnValue) { + returnValue = keys[x].value; + } + } + return returnValue; + } + + template constexpr static auto generateMappingsForFirstBytes(const array& keys, const array& uniqueIndices) noexcept { - constexpr size_t flattenedSize = 256ull * 256ull; + constexpr size_t flattenedSize = (maxFirstByte + 1) * 256ull; std::array flattenedMappings{}; - std::fill(flattenedMappings.data(), flattenedMappings.data() + flattenedMappings.size(), flattenedMappings.size() - 1); + std::fill(flattenedMappings.data(), flattenedMappings.data() + flattenedMappings.size(), static_cast(flattenedMappings.size() - 1)); for (size_t x = 0; x < firstCharCount; ++x) { const auto& key = keys[x].rootPtr[0].key; @@ -599,7 +608,7 @@ namespace jsonifier::internal { const auto& keyNew = keys[x].rootPtr[y].key; if (uniqueIndex < keyNew.size()) { uint8_t keyChar = static_cast(keyNew[uniqueIndex]); - size_t flattenedIdx = firstByte * 256ull + keyChar; + size_t flattenedIdx = static_cast(firstByte * maxFirstByte + keyChar); flattenedMappings[flattenedIdx] = keys[x].rootPtr[y].oldIndex; } } @@ -653,8 +662,8 @@ namespace jsonifier::internal { return hashData.storageSize; } else if constexpr (hashData.type == hash_map_type::first_byte_and_unique_index) { static constexpr auto uniqueFirstByteCount{ countFirstBytes(tupleReferencesByFirstByte) }; - static constexpr auto mappings{ generateMappingsForFirstBytes(collectFirstBytes(tupleReferencesByFirstByte), - hashData.uniqueIndices) }; + static constexpr auto firstBytes{ collectFirstBytes(tupleReferencesByFirstByte) }; + static constexpr auto mappings{ generateMappingsForFirstBytes(firstBytes, hashData.uniqueIndices) }; const uint8_t firstByte = static_cast(iter[0]); const uint8_t uniqueIdx = hashData.uniqueIndices[firstByte]; if JSONIFIER_LIKELY (checkForEnd(iter, end, uniqueIdx)) { @@ -694,7 +703,7 @@ namespace jsonifier::internal { const auto newPtr = char_comparison<'"', jsonifier::internal::remove_cvref_t>::memchar(iter + subAmount01, subAmount02); if JSONIFIER_LIKELY (newPtr) { size_t length = static_cast(newPtr - iter); - length = (hashData.uniqueIndex > length) ? length : hashData.uniqueIndex; + length = (hashData.uniqueIndex > length) ? length : hashData.uniqueIndex; if JSONIFIER_LIKELY (checkForEnd(iter, end, length)) { const auto hash = hasher.hashKeyRt(iter, length); const size_t group = (hash >> 8) & (sizeMask); diff --git a/Include/jsonifier/Utilities/IToStr.hpp b/Include/jsonifier/Utilities/IToStr.hpp index 067843150..4833a81c5 100644 --- a/Include/jsonifier/Utilities/IToStr.hpp +++ b/Include/jsonifier/Utilities/IToStr.hpp @@ -33,10 +33,9 @@ namespace jsonifier::internal { template struct int_tables { - JSONIFIER_ALIGN(2ull) static constexpr char charTable1[] { 0x30u, 0x31u, 0x32u, 0x33u, 0x34u, 0x35u, 0x36u, 0x37u, 0x38u, 0x39u }; + static constexpr char charTable00[]{ 0x30u, 0x31u, 0x32u, 0x33u, 0x34u, 0x35u, 0x36u, 0x37u, 0x38u, 0x39u }; - JSONIFIER_ALIGN(2ull) - static constexpr char charTable01[200]{ 0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38, 0x30, 0x39, 0x31, 0x30, + static constexpr char charTable01[]{ 0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38, 0x30, 0x39, 0x31, 0x30, 0x31, 0x31, 0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x31, 0x35, 0x31, 0x36, 0x31, 0x37, 0x31, 0x38, 0x31, 0x39, 0x32, 0x30, 0x32, 0x31, 0x32, 0x32, 0x32, 0x33, 0x32, 0x34, 0x32, 0x35, 0x32, 0x36, 0x32, 0x37, 0x32, 0x38, 0x32, 0x39, 0x33, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x33, 0x33, 0x34, 0x33, 0x35, 0x33, 0x36, 0x33, 0x37, 0x33, 0x38, 0x33, 0x39, 0x34, 0x30, 0x34, 0x31, 0x34, 0x32, 0x34, 0x33, 0x34, 0x34, 0x34, 0x35, 0x34, 0x36, 0x34, 0x37, 0x34, 0x38, 0x34, 0x39, 0x35, 0x30, 0x35, 0x31, 0x35, 0x32, @@ -45,12 +44,12 @@ namespace jsonifier::internal { 0x38, 0x31, 0x38, 0x32, 0x38, 0x33, 0x38, 0x34, 0x38, 0x35, 0x38, 0x36, 0x38, 0x37, 0x38, 0x38, 0x38, 0x39, 0x39, 0x30, 0x39, 0x31, 0x39, 0x32, 0x39, 0x33, 0x39, 0x34, 0x39, 0x35, 0x39, 0x36, 0x39, 0x37, 0x39, 0x38, 0x39, 0x39 }; - static constexpr uint16_t charTable02[]{ 0x3030u, 0x3130u, 0x3230u, 0x3330u, 0x3430u, 0x3530u, 0x3630u, 0x3730u, 0x3830u, 0x3930u, 0x3031u, 0x3131u, 0x3231u, 0x3331u, - 0x3431u, 0x3531u, 0x3631u, 0x3731u, 0x3831u, 0x3931u, 0x3032u, 0x3132u, 0x3232u, 0x3332u, 0x3432u, 0x3532u, 0x3632u, 0x3732u, 0x3832u, 0x3932u, 0x3033u, 0x3133u, - 0x3233u, 0x3333u, 0x3433u, 0x3533u, 0x3633u, 0x3733u, 0x3833u, 0x3933u, 0x3034u, 0x3134u, 0x3234u, 0x3334u, 0x3434u, 0x3534u, 0x3634u, 0x3734u, 0x3834u, 0x3934u, - 0x3035u, 0x3135u, 0x3235u, 0x3335u, 0x3435u, 0x3535u, 0x3635u, 0x3735u, 0x3835u, 0x3935u, 0x3036u, 0x3136u, 0x3236u, 0x3336u, 0x3436u, 0x3536u, 0x3636u, 0x3736u, - 0x3836u, 0x3936u, 0x3037u, 0x3137u, 0x3237u, 0x3337u, 0x3437u, 0x3537u, 0x3637u, 0x3737u, 0x3837u, 0x3937u, 0x3038u, 0x3138u, 0x3238u, 0x3338u, 0x3438u, 0x3538u, - 0x3638u, 0x3738u, 0x3838u, 0x3938u, 0x3039u, 0x3139u, 0x3239u, 0x3339u, 0x3439u, 0x3539u, 0x3639u, 0x3739u, 0x3839u, 0x3939u }; + static constexpr uint16_t charTable02[]{ 0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 0x3630, 0x3730, 0x3830, 0x3930, 0x3031, 0x3131, 0x3231, 0x3331, 0x3431, 0x3531, + 0x3631, 0x3731, 0x3831, 0x3931, 0x3032, 0x3132, 0x3232, 0x3332, 0x3432, 0x3532, 0x3632, 0x3732, 0x3832, 0x3932, 0x3033, 0x3133, 0x3233, 0x3333, 0x3433, 0x3533, 0x3633, + 0x3733, 0x3833, 0x3933, 0x3034, 0x3134, 0x3234, 0x3334, 0x3434, 0x3534, 0x3634, 0x3734, 0x3834, 0x3934, 0x3035, 0x3135, 0x3235, 0x3335, 0x3435, 0x3535, 0x3635, 0x3735, + 0x3835, 0x3935, 0x3036, 0x3136, 0x3236, 0x3336, 0x3436, 0x3536, 0x3636, 0x3736, 0x3836, 0x3936, 0x3037, 0x3137, 0x3237, 0x3337, 0x3437, 0x3537, 0x3637, 0x3737, 0x3837, + 0x3937, 0x3038, 0x3138, 0x3238, 0x3338, 0x3438, 0x3538, 0x3638, 0x3738, 0x3838, 0x3938, 0x3039, 0x3139, 0x3239, 0x3339, 0x3439, 0x3539, 0x3639, 0x3739, 0x3839, + 0x3939 }; static constexpr uint8_t digitCounts[]{ 19, 19, 19, 19, 18, 18, 18, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 10, 9, 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1 }; @@ -64,417 +63,409 @@ namespace jsonifier::internal { 0, 0, 0 }; }; - JSONIFIER_INLINE static uint64_t umul128Generic(uint64_t ab, uint64_t cd, uint64_t& hi) noexcept { - uint64_t aHigh = ab >> 32; - uint64_t aLow = ab & 0xFFFFFFFF; - uint64_t bHigh = cd >> 32; - uint64_t bLow = cd & 0xFFFFFFFF; - uint64_t ad = aHigh * bLow; - uint64_t bd = aHigh * bLow; - uint64_t adbc = ad + aLow * bHigh; - uint64_t lo = bd + (adbc << 32); - uint64_t carry = (lo < bd); - hi = aHigh * bHigh + (adbc >> 32) + carry; - return lo; + JSONIFIER_INLINE static uint64_t fastDigitCount(const uint64_t inputValue) { + const uint64_t originalDigitCount{ int_tables::digitCounts[std::countl_zero(inputValue)] }; + return originalDigitCount + static_cast(inputValue > int_tables::digitCountThresholds[originalDigitCount]); } - JSONIFIER_INLINE static void multiply(uint64_t& value, uint64_t expValue) noexcept { -#if defined(__SIZEOF_INT128__) - const __uint128_t res = static_cast<__uint128_t>(value) * static_cast<__uint128_t>(expValue); - value = static_cast(res); - return; -#elif defined(_M_ARM64) && !defined(__MINGW32__) - uint64_t values; - values = __umulh(value, expValue); - value = value * expValue; - return; -#elif (defined(_WIN64) && !defined(__clang__)) - uint64_t values; - value = _umul128(value, expValue, &values); - return; -#else - uint64_t values; - value = umul128Generic(value, expValue, &values); - return; -#endif + template JSONIFIER_INLINE static char* toChars1(char* buf, const value_type value) noexcept { + buf[0] = int_tables::charTable00[value]; + return buf + 1ull; } - JSONIFIER_INLINE static uint64_t fastDigitCount(const uint64_t inputValue) { - const uint64_t originalDigitCount{ int_tables::digitCounts[simd::lzcnt(inputValue)] }; - return originalDigitCount + static_cast(inputValue > int_tables::digitCountThresholds[originalDigitCount]); + template JSONIFIER_INLINE static char* toChars2(char* buf, const value_type value) noexcept { + std::memcpy(buf, int_tables::charTable02 + value, 2ull); + return buf + 2ull; + } + + template JSONIFIER_INLINE static char* toChars3(char* buf, const value_type value) noexcept { + const uint32_t aa = (value * 5243u) >> 19ull; + buf[0] = int_tables::charTable00[aa]; + std::memcpy(buf + 1ull, int_tables::charTable02 + (value - aa * 100u), 2ull); + return buf + 3ull; + } + + template JSONIFIER_INLINE static char* toChars4(char* buf, const value_type value) noexcept { + const uint32_t aa = (value * 5243u) >> 19ull; + std::memcpy(buf, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 2ull, int_tables::charTable02 + (value - aa * 100u), 2ull); + return buf + 4ull; + } + + template JSONIFIER_INLINE static char* toChars5(char* buf, const value_type value) noexcept { + uint32_t aa = static_cast((value * 429497ull) >> 32ull); + buf[0] = int_tables::charTable00[aa]; + aa = value - aa * 10000u; + const uint32_t bb = (aa * 5243u) >> 19ull; + std::memcpy(buf + 1ull, int_tables::charTable02 + bb, 2ull); + std::memcpy(buf + 3ull, int_tables::charTable02 + (aa - bb * 100u), 2ull); + return buf + 5ull; + } + + template JSONIFIER_INLINE static char* toChars6(char* buf, const value_type value) noexcept { + uint32_t aa = static_cast((value * 429497ull) >> 32ull); + std::memcpy(buf, int_tables::charTable02 + aa, 2ull); + aa = value - aa * 10000u; + const uint32_t bb = (aa * 5243u) >> 19ull; + std::memcpy(buf + 2ull, int_tables::charTable02 + bb, 2ull); + std::memcpy(buf + 4ull, int_tables::charTable02 + (aa - bb * 100u), 2ull); + return buf + 6ull; + } + + template JSONIFIER_INLINE static char* toChars7(char* buf, const value_type value) noexcept { + uint32_t aabb = static_cast((value * 109951163ull) >> 40ull); + uint32_t aa = (aabb * 5243u) >> 19ull; + buf[0] = int_tables::charTable00[aa]; + std::memcpy(buf + 1ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = value - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 3ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 5ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + return buf + 7ull; + } + + template JSONIFIER_INLINE static char* toChars8(char* buf, const value_type value) noexcept { + uint32_t aabb = static_cast((value * 109951163ull) >> 40ull); + uint32_t aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 2ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = value - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 4ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 6ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + return buf + 8ull; + } + + template JSONIFIER_INLINE static char* toChars9(char* buf, const value_type value) noexcept { + uint32_t high = static_cast((value * 720575941ull) >> 56ull); + buf[0] = int_tables::charTable00[high]; + high = value - high * 100000000u; + uint32_t aabb = static_cast((high * 109951163ull) >> 40ull); + uint32_t aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 1ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 3ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = high - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 5ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 7ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + return buf + 9ull; + } + + template JSONIFIER_INLINE static char* toChars10(char* buf, const value_type value) noexcept { + const uint32_t high = static_cast((value * 1801439851ull) >> 54ull); + const uint32_t low = static_cast(value - high * 10000000ull); + uint32_t aa = (high * 5243u) >> 19ull; + buf[0] = int_tables::charTable00[aa]; + std::memcpy(buf + 1ull, int_tables::charTable02 + (high - aa * 100u), 2ull); + uint32_t aabb = static_cast((low * 109951163ull) >> 40ull); + aa = (aabb * 5243u) >> 19ull; + buf[3] = int_tables::charTable00[aa]; + std::memcpy(buf + 4ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 6ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 8ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + return buf + 10; + } + + template JSONIFIER_INLINE static char* toChars11(char* buf, const value_type value) noexcept { + const uint32_t high = static_cast(value / 10000000ull); + const uint32_t low = static_cast(value - high * 10000000ull); + uint32_t aa = (high * 5243u) >> 19ull; + std::memcpy(buf, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 2ull, int_tables::charTable02 + (high - aa * 100u), 2ull); + uint32_t aabb = static_cast((low * 109951163ull) >> 40ull); + aa = (aabb * 5243u) >> 19ull; + buf[4] = int_tables::charTable00[aa]; + std::memcpy(buf + 5ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 7ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 9ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + return buf + 11; + } + + template JSONIFIER_INLINE static char* toChars12(char* buf, const value_type value) noexcept { + const uint32_t high = static_cast(value / 100000000ull); + const uint32_t low = static_cast(value - high * 100000000ull); + uint32_t aa = (high * 5243u) >> 19ull; + std::memcpy(buf, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 2ull, int_tables::charTable02 + (high - aa * 100u), 2ull); + uint32_t aabb = static_cast((low * 109951163ull) >> 40ull); + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 4ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 6ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 8ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 10ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + return buf + 12; + } + + template JSONIFIER_INLINE static char* toChars13(char* buf, const value_type value) noexcept { + const uint32_t high = static_cast(value / 100000000ull); + const uint32_t low = static_cast(value - high * 100000000ull); + uint32_t aa = static_cast((high * 429497ull) >> 32ull); + const uint32_t bbcc = high - aa * 10000u; + const uint32_t bb = (bbcc * 5243u) >> 19ull; + uint32_t cc = bbcc - bb * 100u; + buf[0] = int_tables::charTable00[aa]; + std::memcpy(buf + 1ull, int_tables::charTable02 + bb, 2ull); + std::memcpy(buf + 3ull, int_tables::charTable02 + cc, 2ull); + const uint32_t aabb = static_cast((low * 109951163ull) >> 40ull); + const uint32_t ccdd = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + cc = (ccdd * 5243u) >> 19ull; + std::memcpy(buf + 5ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 7ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + std::memcpy(buf + 9ull, int_tables::charTable02 + cc, 2ull); + std::memcpy(buf + 11ull, int_tables::charTable02 + (ccdd - cc * 100u), 2ull); + return buf + 13ull; + } + + template JSONIFIER_INLINE static char* toChars14(char* buf, const value_type value) noexcept { + const uint32_t high = static_cast(value / 100000000ull); + const uint32_t low = static_cast(value - high * 100000000ull); + uint32_t aa = static_cast((high * 429497ull) >> 32ull); + const uint32_t bbcc = high - aa * 10000u; + const uint32_t bb = (bbcc * 5243u) >> 19ull; + uint32_t cc = bbcc - bb * 100u; + std::memcpy(buf, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 2ull, int_tables::charTable02 + bb, 2ull); + std::memcpy(buf + 4ull, int_tables::charTable02 + cc, 2ull); + const uint32_t aabb = static_cast((low * 109951163ull) >> 40ull); + const uint32_t ccdd = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + cc = (ccdd * 5243u) >> 19ull; + std::memcpy(buf + 6ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 8ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + std::memcpy(buf + 10ull, int_tables::charTable02 + cc, 2ull); + std::memcpy(buf + 12ull, int_tables::charTable02 + (ccdd - cc * 100u), 2ull); + return buf + 14ull; + } + + template JSONIFIER_INLINE static char* toChars15(char* buf, const value_type value) noexcept { + const uint32_t high = static_cast(value / 100000000ull); + const uint32_t low = static_cast(value - high * 100000000ull); + uint32_t aabb = static_cast((high * 109951163ull) >> 40ull); + uint32_t ccdd = static_cast(high - aabb * 10000u); + uint32_t aa = (aabb * 5243u) >> 19ull; + uint32_t cc = (ccdd * 5243u) >> 19ull; + const uint32_t bb = aabb - aa * 100u; + const uint32_t dd = ccdd - cc * 100u; + buf[0] = int_tables::charTable00[aa]; + std::memcpy(buf + 1ull, int_tables::charTable02 + bb, 2ull); + std::memcpy(buf + 3ull, int_tables::charTable02 + cc, 2ull); + std::memcpy(buf + 5ull, int_tables::charTable02 + dd, 2ull); + aabb = static_cast((low * 109951163ull) >> 40ull); + ccdd = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + cc = (ccdd * 5243u) >> 19ull; + std::memcpy(buf + 7ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 9ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + std::memcpy(buf + 11ull, int_tables::charTable02 + cc, 2ull); + std::memcpy(buf + 13ull, int_tables::charTable02 + (ccdd - cc * 100u), 2ull); + return buf + 15ull; + } + + template JSONIFIER_INLINE static char* toChars16(char* buf, const value_type value) noexcept { + const uint32_t high = static_cast(value / 100000000ull); + const uint32_t low = static_cast(value - high * 100000000ull); + uint32_t aabb = static_cast((high * 109951163ull) >> 40ull); + uint32_t ccdd = static_cast(high - aabb * 10000u); + uint32_t aa = (aabb * 5243u) >> 19ull; + uint32_t cc = (ccdd * 5243u) >> 19ull; + const uint32_t bb = aabb - aa * 100u; + const uint32_t dd = ccdd - cc * 100u; + std::memcpy(buf, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 2ull, int_tables::charTable02 + bb, 2ull); + std::memcpy(buf + 4ull, int_tables::charTable02 + cc, 2ull); + std::memcpy(buf + 6ull, int_tables::charTable02 + dd, 2ull); + aabb = static_cast((low * 109951163ull) >> 40ull); + ccdd = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + cc = (ccdd * 5243u) >> 19ull; + std::memcpy(buf + 8ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 10ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + std::memcpy(buf + 12ull, int_tables::charTable02 + cc, 2ull); + std::memcpy(buf + 14ull, int_tables::charTable02 + (ccdd - cc * 100u), 2ull); + return buf + 16ull; + } + + template JSONIFIER_INLINE static char* toChars17(char* buf, const value_type value) noexcept { + const uint64_t high = value / 100000000ull; + const uint64_t low = value - high * 100000000ull; + const uint64_t high9 = (high * 720575941ull) >> 56ull; + const uint64_t low9 = high - high9 * 100000000ull; + buf[0] = int_tables::charTable00[high9]; + uint64_t aabb = (low9 * 109951163ull) >> 40ull; + uint64_t aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 1ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 3ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low9 - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 5ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 7ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = (low * 109951163ull) >> 40ull; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 9ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 11ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 13ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 15ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + return buf + 17; + } + + template JSONIFIER_INLINE static char* toChars18(char* buf, const value_type value) noexcept { + const uint64_t high = value / 100000000ull; + const uint64_t low = value - high * 100000000ull; + const uint64_t high10 = (high * 1801439851ull) >> 54; + const uint64_t low10 = high - high10 * 10000000ull; + uint64_t aa = (high10 * 5243u) >> 19ull; + buf[0] = int_tables::charTable00[aa]; + std::memcpy(buf + 1ull, int_tables::charTable02 + (high10 - aa * 100u), 2ull); + uint64_t aabb = (low10 * 109951163ull) >> 40ull; + aa = (aabb * 5243u) >> 19ull; + buf[3] = int_tables::charTable00[aa]; + std::memcpy(buf + 4ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low10 - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 6ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 8ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = (low * 109951163ull) >> 40ull; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 10ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 12ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 14ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 16ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + return buf + 18; + } + + template JSONIFIER_INLINE static char* toChars19(char* buf, const value_type value) noexcept { + const uint64_t high = value / 100000000ull; + const uint64_t low = value - high * 100000000ull; + const uint64_t high11 = high / 10000000ull; + const uint64_t low11 = high - high11 * 10000000ull; + uint64_t aa = (high11 * 5243u) >> 19ull; + std::memcpy(buf, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 2ull, int_tables::charTable02 + (high11 - aa * 100u), 2ull); + uint64_t aabb = (low11 * 109951163ull) >> 40ull; + aa = (aabb * 5243u) >> 19ull; + buf[4] = int_tables::charTable00[aa]; + std::memcpy(buf + 5ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low11 - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 7ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 9ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = (low * 109951163ull) >> 40ull; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 11ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 13ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 15ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 17ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + return buf + 19; + } + + template JSONIFIER_INLINE static char* toChars20(char* buf, const value_type value) noexcept { + const uint64_t high = value / 100000000ull; + const uint64_t low = value - high * 100000000ull; + const uint64_t high12 = high / 100000000ull; + const uint64_t low12 = high - high12 * 100000000ull; + uint64_t aa = (high12 * 5243u) >> 19ull; + std::memcpy(buf, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 2ull, int_tables::charTable02 + (high12 - aa * 100u), 2ull); + uint64_t aabb = (low12 * 109951163ull) >> 40ull; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 4ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 6ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low12 - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 8ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 10ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = (low * 109951163ull) >> 40ull; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 12ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 14ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + aabb = low - aabb * 10000u; + aa = (aabb * 5243u) >> 19ull; + std::memcpy(buf + 16ull, int_tables::charTable02 + aa, 2ull); + std::memcpy(buf + 18ull, int_tables::charTable02 + (aabb - aa * 100u), 2ull); + return buf + 20; } - template JSONIFIER_INLINE static char* toChars(char* buf, value_type value) noexcept { + template JSONIFIER_INLINE char* toChars(char* buf, const value_type value) noexcept { switch (fastDigitCount(value)) { case 20: { - static constexpr uint64_t multiplier01{ 109951163ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - const uint64_t tmp = value / 100000000ull; - const uint64_t low = value - tmp * 100000000ull; - const uint64_t high = tmp / 10000ull; - const uint64_t mid = tmp - high * 10000ull; - uint64_t aabb = (high * multiplier01) >> 40ull; - uint64_t ccdd = high - aabb * 10000ull; - uint64_t aa = (aabb * multiplier02) >> 19ull; - uint64_t cc = (ccdd * multiplier02) >> 19ull; - uint64_t bb = aabb - aa * 100ull; - uint64_t dd = ccdd - cc * 100ull; - std::memcpy(buf, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 2ull, int_tables::charTable02 + bb, 2ull); - std::memcpy(buf + 4ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 6ull, int_tables::charTable02 + dd, 2ull); - aa = (mid * multiplier02) >> 19ull; - bb = mid - aa * 100ull; - std::memcpy(buf + 8ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 10ull, int_tables::charTable02 + bb, 2ull); - aabb = (low * multiplier01) >> 40ull; - ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier02) >> 19ull; - cc = (ccdd * multiplier02) >> 19ull; - std::memcpy(buf + 12ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 14ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 16ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 18ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 20ull; + return toChars20(buf, value); } case 19: { - static constexpr uint64_t multiplier01{ 109951163ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - const uint64_t tmp = value / 100000000ull; - const uint64_t low = value - tmp * 100000000ull; - const uint64_t high = tmp / 10000ull; - const uint64_t mid = tmp - high * 10000ull; - uint64_t aabb = (high * multiplier01) >> 40ull; - uint64_t ccdd = high - aabb * 10000ull; - uint64_t aa = (aabb * multiplier02) >> 19ull; - uint64_t cc = (ccdd * multiplier02) >> 19ull; - uint64_t bb = aabb - aa * 100ull; - uint64_t dd = ccdd - cc * 100ull; - buf[0] = int_tables::charTable1[aa]; - std::memcpy(buf + 1ull, int_tables::charTable02 + bb, 2ull); - std::memcpy(buf + 3ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 5ull, int_tables::charTable02 + dd, 2ull); - aa = (mid * multiplier02) >> 19ull; - bb = mid - aa * 100ull; - std::memcpy(buf + 7ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 9ull, int_tables::charTable02 + bb, 2ull); - aabb = (low * multiplier01) >> 40ull; - ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier02) >> 19ull; - cc = (ccdd * multiplier02) >> 19ull; - std::memcpy(buf + 11ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 13ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 15ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 17ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 19ull; + return toChars19(buf, value); } case 18: { - static constexpr uint64_t multiplier01{ 429497ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - static constexpr uint64_t multiplier03{ 109951163ull }; - const uint64_t tmp = value / 100000000ull; - const uint64_t low = value - tmp * 100000000ull; - const uint64_t high = tmp / 10000ull; - const uint64_t mid = tmp - high * 10000ull; - uint64_t aa = (high * multiplier01) >> 32ull; - const uint64_t bbcc = high - aa * 10000ull; - uint64_t bb = (bbcc * multiplier02) >> 19ull; - uint64_t cc = bbcc - bb * 100ull; - std::memcpy(buf, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 2ull, int_tables::charTable02 + bb, 2ull); - std::memcpy(buf + 4ull, int_tables::charTable02 + cc, 2ull); - aa = (mid * 5243ull) >> 19ull; - bb = mid - aa * 100ull; - std::memcpy(buf + 6ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 8ull, int_tables::charTable02 + bb, 2ull); - const uint64_t aabb = (low * multiplier03) >> 40ull; - const uint64_t ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier02) >> 19ull; - cc = (ccdd * multiplier02) >> 19ull; - std::memcpy(buf + 10ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 12ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 14ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 16ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 18ull; + return toChars18(buf, value); } case 17: { - static constexpr uint64_t multiplier01{ 429497ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - static constexpr uint64_t multiplier03{ 109951163ull }; - const uint64_t tmp = value / 100000000ull; - const uint64_t low = value - tmp * 100000000ull; - const uint64_t high = tmp / 10000ull; - const uint64_t mid = tmp - high * 10000ull; - uint64_t aa = (high * multiplier01) >> 32ull; - const uint64_t bbcc = high - aa * 10000ull; - uint64_t bb = (bbcc * multiplier02) >> 19ull; - uint64_t cc = bbcc - bb * 100ull; - buf[0] = int_tables::charTable1[aa]; - std::memcpy(buf + 1ull, int_tables::charTable02 + bb, 2ull); - std::memcpy(buf + 3ull, int_tables::charTable02 + cc, 2ull); - aa = (mid * 5243ull) >> 19ull; - bb = mid - aa * 100ull; - std::memcpy(buf + 5ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 7ull, int_tables::charTable02 + bb, 2ull); - const uint64_t aabb = (low * multiplier03) >> 40ull; - const uint64_t ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier02) >> 19ull; - cc = (ccdd * multiplier02) >> 19ull; - std::memcpy(buf + 9ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 11ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 13ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 15ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 17ull; + return toChars17(buf, value); } case 16: { - static constexpr uint64_t multiplier01{ 109951163ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - const uint64_t high = value / 100000000ull; - const uint64_t low = value - high * 100000000ull; - uint64_t aabb = (high * multiplier01) >> 40ull; - uint64_t ccdd = high - aabb * 10000ull; - uint64_t aa = (aabb * multiplier02) >> 19ull; - uint64_t cc = (ccdd * multiplier02) >> 19ull; - const uint64_t bb = aabb - aa * 100ull; - const uint64_t dd = ccdd - cc * 100ull; - std::memcpy(buf, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 2ull, int_tables::charTable02 + bb, 2ull); - std::memcpy(buf + 4ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 6ull, int_tables::charTable02 + dd, 2ull); - aabb = (low * multiplier01) >> 40ull; - ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier02) >> 19ull; - cc = (ccdd * multiplier02) >> 19ull; - std::memcpy(buf + 8ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 10ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 12ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 14ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 16ull; + return toChars16(buf, value); } case 15: { - static constexpr uint64_t multiplier01{ 109951163ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - const uint64_t high = value / 100000000ull; - const uint64_t low = value - high * 100000000ull; - uint64_t aabb = (high * multiplier01) >> 40ull; - uint64_t ccdd = high - aabb * 10000ull; - uint64_t aa = (aabb * multiplier02) >> 19ull; - uint64_t cc = (ccdd * multiplier02) >> 19ull; - const uint64_t bb = aabb - aa * 100ull; - const uint64_t dd = ccdd - cc * 100ull; - buf[0] = int_tables::charTable1[aa]; - std::memcpy(buf + 1ull, int_tables::charTable02 + bb, 2ull); - std::memcpy(buf + 3ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 5ull, int_tables::charTable02 + dd, 2ull); - aabb = (low * multiplier01) >> 40ull; - ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier02) >> 19ull; - cc = (ccdd * multiplier02) >> 19ull; - std::memcpy(buf + 7ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 9ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 11ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 13ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 15ull; + return toChars15(buf, value); } case 14: { - static constexpr uint64_t multiplier01{ 429497ull }; - static constexpr uint64_t multiplier02{ 109951163ull }; - static constexpr uint64_t multiplier03{ 5243ull }; - const uint64_t high = value / 100000000ull; - const uint64_t low = value - high * 100000000ull; - uint64_t aa = (high * multiplier01) >> 32ull; - const uint64_t bbcc = high - aa * 10000ull; - const uint64_t bb = (bbcc * multiplier03) >> 19ull; - uint64_t cc = bbcc - bb * 100ull; - std::memcpy(buf, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 2ull, int_tables::charTable02 + bb, 2ull); - std::memcpy(buf + 4ull, int_tables::charTable02 + cc, 2ull); - const uint64_t aabb = (low * multiplier02) >> 40ull; - const uint64_t ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier03) >> 19ull; - cc = (ccdd * multiplier03) >> 19ull; - std::memcpy(buf + 6ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 8ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 10ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 12ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 14ull; + return toChars14(buf, value); } case 13: { - static constexpr uint64_t multiplier01{ 429497ull }; - static constexpr uint64_t multiplier02{ 109951163ull }; - static constexpr uint64_t multiplier03{ 5243ull }; - const uint64_t high = value / 100000000ull; - const uint64_t low = value - high * 100000000ull; - uint64_t aa = (high * multiplier01) >> 32ull; - const uint64_t bbcc = high - aa * 10000ull; - const uint64_t bb = (bbcc * multiplier03) >> 19ull; - uint64_t cc = bbcc - bb * 100ull; - buf[0] = int_tables::charTable1[aa]; - std::memcpy(buf + 1ull, int_tables::charTable02 + bb, 2ull); - std::memcpy(buf + 3ull, int_tables::charTable02 + cc, 2ull); - const uint64_t aabb = (low * multiplier02) >> 40ull; - const uint64_t ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier03) >> 19ull; - cc = (ccdd * multiplier03) >> 19ull; - std::memcpy(buf + 5ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 7ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 9ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 11ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 13ull; + return toChars13(buf, value); } case 12: { - static constexpr uint64_t multiplier01{ 109951163ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - const uint64_t high = value / 100000000ull; - const uint64_t low = value - high * 100000000ull; - uint64_t aa = (high * multiplier02) >> 19ull; - std::memcpy(buf, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 2ull, int_tables::charTable02 + high - aa * 100ull, 2ull); - const uint64_t aabb = (low * multiplier01) >> 40ull; - const uint64_t ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier02) >> 19ull; - const uint64_t cc = (ccdd * multiplier02) >> 19ull; - std::memcpy(buf + 4, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 6ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 8ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 10ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 12; + return toChars12(buf, value); } case 11: { - static constexpr uint64_t multiplier01{ 180143985ull }; - static constexpr uint64_t multiplier02{ 109951163ull }; - static constexpr uint64_t multiplier03{ 5243ull }; - uint64_t high{ value }; - multiply(high, multiplier01); - high = high >> 54; - const uint64_t low = value - high * 100000000ull; - uint64_t aa = (high * multiplier03) >> 19ull; - buf[0] = int_tables::charTable1[aa]; - std::memcpy(buf + 1ull, int_tables::charTable02 + high - aa * 100ull, 2ull); - const uint64_t aabb = (low * multiplier02) >> 40ull; - const uint64_t ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier03) >> 19ull; - const uint64_t cc = (ccdd * multiplier03) >> 19ull; - std::memcpy(buf + 3, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 5ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 7ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 9ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 11; + return toChars11(buf, value); } case 10: { - static constexpr uint64_t multiplier01{ 1801439851ull }; - static constexpr uint64_t multiplier02{ 109951163ull }; - static constexpr uint64_t multiplier03{ 5243ull }; - uint64_t high{ value }; - multiply(high, multiplier01); - high = high >> 54; - const uint64_t low = value - high * 10000000ull; - uint64_t aa = (high * multiplier03) >> 19ull; - buf[0] = int_tables::charTable1[aa]; - std::memcpy(buf + 1ull, int_tables::charTable02 + high - aa * 100ull, 2ull); - const uint64_t aabb = (low * multiplier02) >> 40ull; - const uint64_t ccdd = low - aabb * 10000ull; - aa = (aabb * multiplier03) >> 19ull; - const uint64_t cc = (ccdd * multiplier03) >> 19ull; - buf[3] = int_tables::charTable1[aa]; - std::memcpy(buf + 4ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 6ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 8ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 10; + return toChars10(buf, value); } case 9: { - static constexpr uint64_t multiplier01{ 720575941ull }; - static constexpr uint64_t multiplier02{ 109951163ull }; - static constexpr uint64_t multiplier03{ 5243ull }; - const uint64_t high = (value * multiplier01) >> 56ull; - const uint64_t low = value - high * 100000000ull; - buf[0] = int_tables::charTable1[high]; - const uint64_t aabb = (low * multiplier02) >> 40ull; - const uint64_t ccdd = low - aabb * 10000ull; - const uint64_t aa = (aabb * multiplier03) >> 19ull; - const uint64_t cc = (ccdd * multiplier03) >> 19ull; - std::memcpy(buf + 1ull, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 3ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 5ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 7ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 9ull; + return toChars9(buf, static_cast(value)); } case 8: { - static constexpr uint64_t multiplier01{ 109951163ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - const uint64_t aabb = (value * multiplier01) >> 40ull; - const uint64_t ccdd = value - aabb * 10000ull; - const uint64_t aa = (aabb * multiplier02) >> 19ull; - const uint64_t cc = (ccdd * multiplier02) >> 19ull; - std::memcpy(buf, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 2ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 4ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 6ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 8ull; + return toChars8(buf, static_cast(value)); } case 7: { - static constexpr uint64_t multiplier01{ 109951163ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - const uint64_t aabb = (value * multiplier01) >> 40ull; - const uint64_t ccdd = value - aabb * 10000ull; - const uint64_t aa = (aabb * multiplier02) >> 19ull; - const uint64_t cc = (ccdd * multiplier02) >> 19ull; - buf[0] = int_tables::charTable1[aa]; - std::memcpy(buf + 1ull, int_tables::charTable02 + aabb - aa * 100ull, 2ull); - std::memcpy(buf + 3ull, int_tables::charTable02 + cc, 2ull); - std::memcpy(buf + 5ull, int_tables::charTable02 + ccdd - cc * 100ull, 2ull); - return buf + 7ull; + return toChars7(buf, static_cast(value)); } case 6: { - static constexpr uint64_t multiplier01{ 429497ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - const uint64_t aa = (value * multiplier01) >> 32ull; - const uint64_t bbcc = value - aa * 10000ull; - const uint64_t bb = (bbcc * multiplier02) >> 19ull; - std::memcpy(buf, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 2ull, int_tables::charTable02 + bb, 2ull); - std::memcpy(buf + 4ull, int_tables::charTable02 + bbcc - bb * 100ull, 2ull); - return buf + 6ull; + return toChars6(buf, static_cast(value)); } case 5: { - static constexpr uint64_t multiplier01{ 429497ull }; - static constexpr uint64_t multiplier02{ 5243ull }; - const uint64_t aa = (value * multiplier01) >> 32ull; - const uint64_t bbcc = value - aa * 10000ull; - const uint64_t bb = (bbcc * multiplier02) >> 19ull; - buf[0] = int_tables::charTable1[aa]; - std::memcpy(buf + 1ull, int_tables::charTable02 + bb, 2ull); - std::memcpy(buf + 3ull, int_tables::charTable02 + bbcc - bb * 100ull, 2ull); - return buf + 5ull; + return toChars5(buf, static_cast(value)); } case 4: { - static constexpr uint64_t multiplier{ 5243ull }; - const uint64_t aa = (value * multiplier) >> 19ull; - std::memcpy(buf, int_tables::charTable02 + aa, 2ull); - std::memcpy(buf + 2ull, int_tables::charTable02 + value - aa * 100ull, 2ull); - return buf + 4ull; + return toChars4(buf, static_cast(value)); } case 3: { - static constexpr uint64_t multiplier{ 5243ull }; - const uint64_t aa = (value * multiplier) >> 19ull; - buf[0] = int_tables::charTable1[aa]; - std::memcpy(buf + 1ull, int_tables::charTable02 + value - aa * 100ull, 2ull); - return buf + 3ull; + return toChars3(buf, static_cast(value)); } case 2: { - std::memcpy(buf, int_tables::charTable02 + value, 2ull); - return buf + 2ull; + return toChars2(buf, static_cast(value)); } default: { - buf[0] = int_tables::charTable1[value]; - return buf + 1ull; + return toChars1(buf, static_cast(value)); } } } - template JSONIFIER_INLINE static char* toChars(char* buf, value_type x) noexcept { + template JSONIFIER_INLINE static char* toChars(char* buf, const value_type value) noexcept { *buf = '-'; - return toChars(buf + (x < 0), uint64_t(x ^ (x >> 63ull)) - (x >> 63ull)); + return toChars(buf + (value < 0), static_cast(value ^ (value >> 63ull)) - (value >> 63ull)); } }// namespace internal \ No newline at end of file diff --git a/Include/jsonifier/Utilities/RawJsonData.hpp b/Include/jsonifier/Utilities/RawJsonData.hpp index add119610..5dd30bf8f 100644 --- a/Include/jsonifier/Utilities/RawJsonData.hpp +++ b/Include/jsonifier/Utilities/RawJsonData.hpp @@ -62,7 +62,7 @@ namespace jsonifier { public: using object_type = std::unordered_map; using string_type = string; - using array_type = vector; + using array_type = std::vector; using number_type = json_number; using bool_type = bool; using null_type = std::nullptr_t; @@ -193,7 +193,7 @@ namespace jsonifier { return jsonData; } - JSONIFIER_INLINE const vector& getErrors() const noexcept { + JSONIFIER_INLINE const std::vector& getErrors() const noexcept { return errors; } @@ -202,7 +202,7 @@ namespace jsonifier { } protected: - vector errors{}; + std::vector errors{}; value_type value{}; string jsonData{}; diff --git a/Include/jsonifier/Utilities/Simd.hpp b/Include/jsonifier/Utilities/Simd.hpp index da3f15f23..1bfcab7d3 100644 --- a/Include/jsonifier/Utilities/Simd.hpp +++ b/Include/jsonifier/Utilities/Simd.hpp @@ -150,28 +150,28 @@ namespace jsonifier::internal { template JSONIFIER_INLINE size_type rollValuesIntoTape(size_type currentIndex, size_type newBitsNew) noexcept { static constexpr size_type bitTotal{ index * 64ull }; - const auto dataPtr = currentParseBuffer.data(); + const auto dataPtr = currentParseBuffer.data(); structuralIndices[0 + (currentIndex * 8) + tapeIndex] = dataPtr + static_cast(simd::tzcnt(newBitsNew) + bitTotal + stringIndex); - newBitsNew = blsr(newBitsNew); + newBitsNew = blsr(newBitsNew); structuralIndices[1 + (currentIndex * 8) + tapeIndex] = dataPtr + static_cast(simd::tzcnt(newBitsNew) + bitTotal + stringIndex); - newBitsNew = blsr(newBitsNew); + newBitsNew = blsr(newBitsNew); structuralIndices[2 + (currentIndex * 8) + tapeIndex] = dataPtr + static_cast(simd::tzcnt(newBitsNew) + bitTotal + stringIndex); - newBitsNew = blsr(newBitsNew); + newBitsNew = blsr(newBitsNew); structuralIndices[3 + (currentIndex * 8) + tapeIndex] = dataPtr + static_cast(simd::tzcnt(newBitsNew) + bitTotal + stringIndex); - newBitsNew = blsr(newBitsNew); + newBitsNew = blsr(newBitsNew); structuralIndices[4 + (currentIndex * 8) + tapeIndex] = dataPtr + static_cast(simd::tzcnt(newBitsNew) + bitTotal + stringIndex); - newBitsNew = blsr(newBitsNew); + newBitsNew = blsr(newBitsNew); structuralIndices[5 + (currentIndex * 8) + tapeIndex] = dataPtr + static_cast(simd::tzcnt(newBitsNew) + bitTotal + stringIndex); - newBitsNew = blsr(newBitsNew); + newBitsNew = blsr(newBitsNew); structuralIndices[6 + (currentIndex * 8) + tapeIndex] = dataPtr + static_cast(simd::tzcnt(newBitsNew) + bitTotal + stringIndex); - newBitsNew = blsr(newBitsNew); + newBitsNew = blsr(newBitsNew); structuralIndices[7 + (currentIndex * 8) + tapeIndex] = dataPtr + static_cast(simd::tzcnt(newBitsNew) + bitTotal + stringIndex); - newBitsNew = blsr(newBitsNew); + newBitsNew = blsr(newBitsNew); return newBitsNew; } template JSONIFIER_INLINE void prefetchStringValues(string_view_ptr values) noexcept { - if constexpr (currentIndex < sixtyFourBitsPerStep / 2) { + if constexpr (currentIndex < sixtyFourBitsPerStep / 4) { jsonifierPrefetchImpl(values + (currentIndex * 64)); prefetchStringValues(values); } @@ -220,7 +220,7 @@ namespace jsonifier::internal { if JSONIFIER_UNLIKELY (!newBits[index]) { return addTapeValues(); } - const auto cnt = popcnt(newBits[index]); + const auto cnt = popcnt(newBits[index]); const size_type rollsAmount = static_cast(std::ceil(static_cast(cnt) / 8.0f)); for (size_type y = 0; y < rollsAmount; ++y) { newBits[index] = rollValuesIntoTape(y, newBits[index]); @@ -231,11 +231,11 @@ namespace jsonifier::internal { } JSONIFIER_INLINE void collectEscaped(jsonifier_simd_int_t& escaped, jsonifier_simd_int_t& nextIsEscaped, simd::simd_int_t_holder& rawStructurals) noexcept { - const jsonifier_simd_int_t simdValue{ simd::gatherValue(static_cast(0xAA)) }; - const jsonifier_simd_int_t potentialEscape = simd::opAndNot(rawStructurals.backslashes, nextIsEscaped); + const jsonifier_simd_int_t simdValue = simd::gatherValue(static_cast(0xAA)); + const jsonifier_simd_int_t potentialEscape = simd::opAndNot(rawStructurals.backslashes, nextIsEscaped); const jsonifier_simd_int_t escapeAndTerminalCode = simd::opXor(simd::opSub(simd::opOr(simd::opShl<1>(potentialEscape), simdValue), potentialEscape), simdValue); - escaped = simd::opXor(escapeAndTerminalCode, simd::opOr(rawStructurals.backslashes, nextIsEscaped)); - nextIsEscaped = simd::opSetLSB(nextIsEscaped, simd::opGetMSB(simd::opAnd(escapeAndTerminalCode, rawStructurals.backslashes))); + escaped = simd::opXor(escapeAndTerminalCode, simd::opOr(rawStructurals.backslashes, nextIsEscaped)); + nextIsEscaped = simd::opSetLSB(nextIsEscaped, simd::opGetMSB(simd::opAnd(escapeAndTerminalCode, rawStructurals.backslashes))); } JSONIFIER_INLINE void collectEmptyEscaped(jsonifier_simd_int_t& escaped, jsonifier_simd_int_t& nextIsEscaped) noexcept { @@ -263,6 +263,4 @@ namespace jsonifier::internal { } }; - inline static thread_local simd_string_reader section{}; - }; \ No newline at end of file diff --git a/Include/jsonifier/Utilities/StrToD.hpp b/Include/jsonifier/Utilities/StrToD.hpp index f72c8e5f6..6feeae8df 100644 --- a/Include/jsonifier/Utilities/StrToD.hpp +++ b/Include/jsonifier/Utilities/StrToD.hpp @@ -59,7 +59,7 @@ namespace jsonifier::internal { JSONIFIER_INLINE_VARIABLE char zero{ '0' }; JSONIFIER_INLINE_VARIABLE char nine{ '9' }; - template inline static bool parseFloat(value_type& value, char_t const*& iter, char_t const* end = nullptr) noexcept { + template JSONIFIER_INLINE static bool parseFloat(value_type& value, char_t const*& iter, char_t const* end = nullptr) noexcept { using namespace jsonifier_fast_float; span fraction; diff --git a/Include/jsonifier/Utilities/StrToI.hpp b/Include/jsonifier/Utilities/StrToI.hpp index a01fd5350..1c1baf36d 100644 --- a/Include/jsonifier/Utilities/StrToI.hpp +++ b/Include/jsonifier/Utilities/StrToI.hpp @@ -60,7 +60,7 @@ namespace jsonifier::internal { }() }; static constexpr array rawCompValsNeg{ [] { - constexpr auto maxValue{ uint64_t((std::numeric_limits::max)()) + 1 }; + constexpr auto maxValue{ static_cast((std::numeric_limits::max)()) + 1 }; array returnValues{}; returnValues['0'] = (maxValue - 0) / 10; returnValues['1'] = (maxValue - 1) / 10; diff --git a/Include/jsonifier/Utilities/String.hpp b/Include/jsonifier/Utilities/String.hpp index a197ac36b..613732910 100644 --- a/Include/jsonifier/Utilities/String.hpp +++ b/Include/jsonifier/Utilities/String.hpp @@ -23,7 +23,9 @@ /// Feb 20, 2023 #pragma once -#include +#include +#include +#include namespace jsonifier::internal { @@ -611,9 +613,3 @@ namespace jsonifier { return os; } }// namespace jsonifier - -namespace jsonifier::internal { - - static thread_local string_base stringBuffer{}; - -} \ No newline at end of file diff --git a/Include/jsonifier/Utilities/StringUtils.hpp b/Include/jsonifier/Utilities/StringUtils.hpp index 68a7ea4cc..19a03bf33 100644 --- a/Include/jsonifier/Utilities/StringUtils.hpp +++ b/Include/jsonifier/Utilities/StringUtils.hpp @@ -270,7 +270,7 @@ namespace jsonifier::internal { template JSONIFIER_INLINE static bool hasByteLessThanValue(string_view_ptr values) noexcept { JSONIFIER_ALIGN(16) - uint8_t valuesNew[16]{ constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), + char valuesNew[16]{ constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1), constEval(threshold + 1) }; std::memcpy(valuesNew, values, 8); @@ -335,7 +335,7 @@ namespace jsonifier::internal { } } - constexpr array escapeMap{ [] { + JSONIFIER_INLINE_VARIABLE array escapeMap{ [] { array returnValues{}; returnValues['"'] = '\"'; returnValues['\\'] = '\\'; @@ -396,7 +396,9 @@ namespace jsonifier::internal { string1Start += bytesProcessed; } } - return string2; + if constexpr (index > 0) { + return string_parser_impl::impl(string1Start, string1End, string2); + } } }; @@ -449,7 +451,7 @@ namespace jsonifier::internal { string1Start += bytesProcessed; } } - return string2; + return string_parser::shortImpl(string1Start, string1End, string2); } }; @@ -489,23 +491,24 @@ namespace jsonifier::internal { JSONIFIER_INLINE static basic_iterator02 impl(basic_iterator01& string1, basic_iterator02 string2, uint64_t lengthNew) noexcept { const basic_iterator01 string1End = string1 + lengthNew; #if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) - string2 = string_parser_impl<3, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); + return string_parser_impl<3, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); +#elif JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) + return string_parser_impl<2, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); +#elif JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX) + return string_parser_impl<1, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); +#else + return string_parser_impl<0, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); #endif -#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) || JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) - string2 = string_parser_impl<2, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); -#endif - string2 = string_parser_impl<1, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); - return shortImpl(string1, string1End, string2); } }; - constexpr array escapeTable{ R"()", R"(\u0001)", R"(\u0002)", R"(\u0003)", R"(\u0004)", R"(\u0005)", R"(\u0006)", R"(\a)", R"(\b)", R"(\t)", - R"(\n)", R"(\v)", R"(\f)", R"(\r)", R"(\u000E)", R"(\u000F)", R"(\u0010)", R"(\u0011)", R"(\u0012)", R"(\u0013)", R"(\u0014)", R"(\u0015)", R"(\u0016)", R"(\u0017)", - R"(\u0018)", R"(\u0019)", R"(\u001A)", R"(\u001B)", R"(\u001C)", R"(\u001D)", R"(\u001E)", R"(\u001F)", "", "", R"(\")", "", "", "", "", "", "", "", "", "", "", "", "", "", + JSONIFIER_INLINE_VARIABLE array escapeTable{ R"()", R"(\u0001)", R"(\u0002)", R"(\u0003)", R"(\u0004)", R"(\u0005)", R"(\u0006)", R"(\a)", R"(\b)", + R"(\t)", R"(\n)", R"(\v)", R"(\f)", R"(\r)", R"(\u000E)", R"(\u000F)", R"(\u0010)", R"(\u0011)", R"(\u0012)", R"(\u0013)", R"(\u0014)", R"(\u0015)", R"(\u0016)", + R"(\u0017)", R"(\u0018)", R"(\u0019)", R"(\u001A)", R"(\u001B)", R"(\u001C)", R"(\u001D)", R"(\u001E)", R"(\u001F)", "", "", R"(\")", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", R"(\\)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }; + "", "", "", "", "", R"(\\)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }; - constexpr array escapeTablePtrs{ [] { + JSONIFIER_INLINE_VARIABLE array escapeTablePtrs{ [] { array returnValues{}; for (size_t x = 0; x < 256; ++x) { returnValues[x] = escapeTable[x].data(); @@ -513,7 +516,7 @@ namespace jsonifier::internal { return returnValues; }() }; - constexpr array escapeTableSizes{ [] { + JSONIFIER_INLINE_VARIABLE array escapeTableSizes{ [] { array returnValues{}; for (size_t x = 0; x < 256; ++x) { returnValues[x] = escapeTable[x].size(); @@ -532,6 +535,7 @@ namespace jsonifier::internal { const simd_type simdValues03 = simd::gatherValue(static_cast(32)); simd_type simdValue; size_t nextSize; + uint8_t nextChar; integer_type nextEscapeable; const char* escapeChar; const auto stringEndNew = string1End - bytesProcessed; @@ -540,8 +544,9 @@ namespace jsonifier::internal { simd::storeu(simdValue, string2); nextEscapeable = findSerialize(simdValue, simdValues01, simdValues02, simdValues03); if JSONIFIER_LIKELY (nextEscapeable != mask) { - nextSize = escapeTableSizes[static_cast(string1Start[nextEscapeable])]; - escapeChar = escapeTablePtrs[static_cast(string1Start[nextEscapeable])]; + nextChar = static_cast(string1Start[nextEscapeable]); + nextSize = escapeTableSizes[nextChar]; + escapeChar = escapeTablePtrs[nextChar]; string2 += nextEscapeable; string1Start += nextEscapeable; std::memcpy(string2, escapeChar, nextSize); @@ -552,7 +557,9 @@ namespace jsonifier::internal { string1Start += bytesProcessed; } } - return string2; + if constexpr (index > 0) { + return string_serializer_impl::impl(string1Start, string1End, string2); + } } }; @@ -568,15 +575,16 @@ namespace jsonifier::internal { size_t nextSize; integer_type nextEscapeable; const char* escapeChar; + uint8_t nextChar; const auto stringEndNew = string1End - bytesProcessed; while (string1Start < stringEndNew) { std::memcpy(string2, string1Start, bytesProcessed); std::memcpy(&simdValue, string1Start, bytesProcessed); nextEscapeable = findSerialize(simdValue); if JSONIFIER_LIKELY (nextEscapeable != mask) { - nextSize = escapeTableSizes[static_cast(string1Start[nextEscapeable])]; - escapeChar = escapeTablePtrs[static_cast(string1Start[nextEscapeable])]; - string1Start += nextEscapeable; + nextChar = static_cast(string1Start[nextEscapeable]); + nextSize = escapeTableSizes[nextChar]; + escapeChar = escapeTablePtrs[nextChar]; string2 += nextEscapeable; string1Start += nextEscapeable; std::memcpy(string2, escapeChar, nextSize); @@ -587,18 +595,20 @@ namespace jsonifier::internal { string1Start += bytesProcessed; } } - return string2; + return string_serializer::shortImpl(string1Start, string1End, string2); } }; template struct string_serializer { JSONIFIER_INLINE static basic_iterator02 shortImpl(basic_iterator01& string1Start, const basic_iterator01 string1End, basic_iterator02 string2) noexcept { const char* escapeChar; + uint8_t nextChar; size_t escapeSize; for (; string1Start < string1End; ++string1Start) { - escapeSize = escapeTableSizes[static_cast(*string1Start)]; + nextChar = static_cast(*string1Start); + escapeSize = escapeTableSizes[nextChar]; if (escapeSize > 0) { - escapeChar = escapeTablePtrs[static_cast(*string1Start)]; + escapeChar = escapeTablePtrs[nextChar]; std::memcpy(string2, escapeChar, escapeSize); string2 += escapeSize; } else { @@ -612,13 +622,14 @@ namespace jsonifier::internal { JSONIFIER_INLINE static basic_iterator02 impl(basic_iterator01 string1, basic_iterator02 string2, uint64_t lengthNew) noexcept { const basic_iterator01 string1End = string1 + lengthNew; #if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) - string2 = string_serializer_impl<3, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); -#endif -#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) || JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) - string2 = string_serializer_impl<2, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); + return string_serializer_impl<3, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); +#elif JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) + return string_serializer_impl<2, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); +#elif JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX) + return string_serializer_impl<1, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); +#else + return string_serializer_impl<0, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); #endif - string2 = string_serializer_impl<1, options, basic_iterator01, basic_iterator02>::impl(string1, string1End, string2); - return shortImpl(string1, string1End, string2); } }; @@ -679,7 +690,7 @@ namespace jsonifier::internal { } } - static constexpr array numericTable = [] { + JSONIFIER_INLINE_VARIABLE array numericTable = [] { array returnValues{}; returnValues['0'] = true; returnValues['1'] = true; @@ -704,16 +715,16 @@ namespace jsonifier::internal { if constexpr (options.partialRead) { if JSONIFIER_LIKELY ((context.iter < context.endIter) && **context.iter == '"') { auto newerPtr = (*context.iter) + 1; - const auto newPtr = string_parser::impl(newerPtr, stringBuffer.data(), - static_cast(*context.endIter - *context.iter)); + const auto newPtr = string_parsergetStringBuffer().data())>::impl(newerPtr, + context.parserPtr->getStringBuffer().data(), static_cast(*context.endIter - *context.iter)); if JSONIFIER_LIKELY (newPtr) { - const auto newSize = static_cast(newPtr - stringBuffer.data()); + const auto newSize = static_cast(newPtr - context.parserPtr->getStringBuffer().data()); if constexpr (concepts::has_resize) { if JSONIFIER_UNLIKELY (value.size() != newSize) { value.resize(newSize); } } - std::memcpy(value.data(), stringBuffer.data(), newSize); + std::memcpy(value.data(), context.parserPtr->getStringBuffer().data(), newSize); ++context.iter; } JSONIFIER_ELSE_UNLIKELY(else) { @@ -729,16 +740,16 @@ namespace jsonifier::internal { } else { if JSONIFIER_LIKELY ((context.iter < context.endIter) && *context.iter == '"') { ++context.iter; - const auto newPtr = string_parser::impl(context.iter, stringBuffer.data(), - static_cast(context.endIter - context.iter)); + const auto newPtr = string_parsergetStringBuffer().data())>::impl(context.iter, + context.parserPtr->getStringBuffer().data(), static_cast(context.endIter - context.iter)); if JSONIFIER_LIKELY (newPtr) { - const auto newSize = static_cast(newPtr - stringBuffer.data()); + const auto newSize = static_cast(newPtr - context.parserPtr->getStringBuffer().data()); if constexpr (concepts::has_resize) { if JSONIFIER_UNLIKELY (value.size() != newSize) { value.resize(newSize); } } - std::memcpy(value.data(), stringBuffer.data(), newSize); + std::memcpy(value.data(), context.parserPtr->getStringBuffer().data(), newSize); ++context.iter; } JSONIFIER_ELSE_UNLIKELY(else) { diff --git a/Include/jsonifier/Utilities/TypeEntities.hpp b/Include/jsonifier/Utilities/TypeEntities.hpp index a006193dd..35c459e68 100644 --- a/Include/jsonifier/Utilities/TypeEntities.hpp +++ b/Include/jsonifier/Utilities/TypeEntities.hpp @@ -54,10 +54,6 @@ namespace jsonifier::internal { return os; } - static void printLocation(const std::source_location& location = std::source_location::current()) { - std::cout << location; - } - template class parser; template class vector;