simdjson 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-format +5 -0
  3. data/.gitignore +14 -0
  4. data/.gitmodules +3 -0
  5. data/.rubocop.yml +9 -0
  6. data/.travis.yml +7 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +39 -0
  10. data/Rakefile +32 -0
  11. data/benchmark/apache_builds.json +4421 -0
  12. data/benchmark/demo.json +15 -0
  13. data/benchmark/github_events.json +1390 -0
  14. data/benchmark/run_benchmark.rb +30 -0
  15. data/ext/simdjson/extconf.rb +22 -0
  16. data/ext/simdjson/simdjson.cpp +76 -0
  17. data/ext/simdjson/simdjson.hpp +6 -0
  18. data/lib/simdjson/version.rb +3 -0
  19. data/lib/simdjson.rb +2 -0
  20. data/simdjson.gemspec +35 -0
  21. data/vendor/.gitkeep +0 -0
  22. data/vendor/simdjson/AUTHORS +3 -0
  23. data/vendor/simdjson/CMakeLists.txt +63 -0
  24. data/vendor/simdjson/CONTRIBUTORS +27 -0
  25. data/vendor/simdjson/Dockerfile +10 -0
  26. data/vendor/simdjson/LICENSE +201 -0
  27. data/vendor/simdjson/Makefile +203 -0
  28. data/vendor/simdjson/Notes.md +85 -0
  29. data/vendor/simdjson/README.md +581 -0
  30. data/vendor/simdjson/amalgamation.sh +158 -0
  31. data/vendor/simdjson/benchmark/CMakeLists.txt +8 -0
  32. data/vendor/simdjson/benchmark/benchmark.h +223 -0
  33. data/vendor/simdjson/benchmark/distinctuseridcompetition.cpp +347 -0
  34. data/vendor/simdjson/benchmark/linux/linux-perf-events.h +93 -0
  35. data/vendor/simdjson/benchmark/minifiercompetition.cpp +181 -0
  36. data/vendor/simdjson/benchmark/parse.cpp +393 -0
  37. data/vendor/simdjson/benchmark/parseandstatcompetition.cpp +305 -0
  38. data/vendor/simdjson/benchmark/parsingcompetition.cpp +298 -0
  39. data/vendor/simdjson/benchmark/statisticalmodel.cpp +208 -0
  40. data/vendor/simdjson/dependencies/jsoncppdist/json/json-forwards.h +344 -0
  41. data/vendor/simdjson/dependencies/jsoncppdist/json/json.h +2366 -0
  42. data/vendor/simdjson/dependencies/jsoncppdist/jsoncpp.cpp +5418 -0
  43. data/vendor/simdjson/doc/apache_builds.jsonparseandstat.png +0 -0
  44. data/vendor/simdjson/doc/gbps.png +0 -0
  45. data/vendor/simdjson/doc/github_events.jsonparseandstat.png +0 -0
  46. data/vendor/simdjson/doc/twitter.jsonparseandstat.png +0 -0
  47. data/vendor/simdjson/doc/update-center.jsonparseandstat.png +0 -0
  48. data/vendor/simdjson/images/halvarflake.png +0 -0
  49. data/vendor/simdjson/images/logo.png +0 -0
  50. data/vendor/simdjson/include/simdjson/common_defs.h +102 -0
  51. data/vendor/simdjson/include/simdjson/isadetection.h +152 -0
  52. data/vendor/simdjson/include/simdjson/jsoncharutils.h +301 -0
  53. data/vendor/simdjson/include/simdjson/jsonformatutils.h +202 -0
  54. data/vendor/simdjson/include/simdjson/jsonioutil.h +32 -0
  55. data/vendor/simdjson/include/simdjson/jsonminifier.h +30 -0
  56. data/vendor/simdjson/include/simdjson/jsonparser.h +250 -0
  57. data/vendor/simdjson/include/simdjson/numberparsing.h +587 -0
  58. data/vendor/simdjson/include/simdjson/padded_string.h +70 -0
  59. data/vendor/simdjson/include/simdjson/parsedjson.h +544 -0
  60. data/vendor/simdjson/include/simdjson/portability.h +172 -0
  61. data/vendor/simdjson/include/simdjson/simdjson.h +44 -0
  62. data/vendor/simdjson/include/simdjson/simdjson_version.h +13 -0
  63. data/vendor/simdjson/include/simdjson/simdprune_tables.h +35074 -0
  64. data/vendor/simdjson/include/simdjson/simdutf8check_arm64.h +180 -0
  65. data/vendor/simdjson/include/simdjson/simdutf8check_haswell.h +198 -0
  66. data/vendor/simdjson/include/simdjson/simdutf8check_westmere.h +169 -0
  67. data/vendor/simdjson/include/simdjson/stage1_find_marks.h +121 -0
  68. data/vendor/simdjson/include/simdjson/stage1_find_marks_arm64.h +210 -0
  69. data/vendor/simdjson/include/simdjson/stage1_find_marks_flatten.h +93 -0
  70. data/vendor/simdjson/include/simdjson/stage1_find_marks_flatten_haswell.h +95 -0
  71. data/vendor/simdjson/include/simdjson/stage1_find_marks_haswell.h +210 -0
  72. data/vendor/simdjson/include/simdjson/stage1_find_marks_macros.h +239 -0
  73. data/vendor/simdjson/include/simdjson/stage1_find_marks_westmere.h +194 -0
  74. data/vendor/simdjson/include/simdjson/stage2_build_tape.h +85 -0
  75. data/vendor/simdjson/include/simdjson/stringparsing.h +105 -0
  76. data/vendor/simdjson/include/simdjson/stringparsing_arm64.h +56 -0
  77. data/vendor/simdjson/include/simdjson/stringparsing_haswell.h +43 -0
  78. data/vendor/simdjson/include/simdjson/stringparsing_macros.h +88 -0
  79. data/vendor/simdjson/include/simdjson/stringparsing_westmere.h +41 -0
  80. data/vendor/simdjson/jsonexamples/small/jsoniter_scala/README.md +4 -0
  81. data/vendor/simdjson/scripts/dumpsimplestats.sh +11 -0
  82. data/vendor/simdjson/scripts/issue150.sh +14 -0
  83. data/vendor/simdjson/scripts/javascript/README.md +3 -0
  84. data/vendor/simdjson/scripts/javascript/generatelargejson.js +19 -0
  85. data/vendor/simdjson/scripts/minifier.sh +11 -0
  86. data/vendor/simdjson/scripts/parseandstat.sh +24 -0
  87. data/vendor/simdjson/scripts/parser.sh +11 -0
  88. data/vendor/simdjson/scripts/parsingcompdata.sh +26 -0
  89. data/vendor/simdjson/scripts/plotparse.sh +98 -0
  90. data/vendor/simdjson/scripts/selectparser.sh +11 -0
  91. data/vendor/simdjson/scripts/setupfortesting/disablehyperthreading.sh +15 -0
  92. data/vendor/simdjson/scripts/setupfortesting/powerpolicy.sh +32 -0
  93. data/vendor/simdjson/scripts/setupfortesting/setupfortesting.sh +6 -0
  94. data/vendor/simdjson/scripts/setupfortesting/turboboost.sh +51 -0
  95. data/vendor/simdjson/scripts/testjson2json.sh +99 -0
  96. data/vendor/simdjson/scripts/transitions/Makefile +10 -0
  97. data/vendor/simdjson/scripts/transitions/generatetransitions.cpp +20 -0
  98. data/vendor/simdjson/singleheader/README.md +1 -0
  99. data/vendor/simdjson/singleheader/amalgamation_demo.cpp +20 -0
  100. data/vendor/simdjson/singleheader/simdjson.cpp +1652 -0
  101. data/vendor/simdjson/singleheader/simdjson.h +39692 -0
  102. data/vendor/simdjson/src/CMakeLists.txt +67 -0
  103. data/vendor/simdjson/src/jsonioutil.cpp +35 -0
  104. data/vendor/simdjson/src/jsonminifier.cpp +285 -0
  105. data/vendor/simdjson/src/jsonparser.cpp +91 -0
  106. data/vendor/simdjson/src/parsedjson.cpp +323 -0
  107. data/vendor/simdjson/src/parsedjsoniterator.cpp +272 -0
  108. data/vendor/simdjson/src/simdjson.cpp +30 -0
  109. data/vendor/simdjson/src/stage1_find_marks.cpp +41 -0
  110. data/vendor/simdjson/src/stage2_build_tape.cpp +567 -0
  111. data/vendor/simdjson/style/clang-format-check.sh +25 -0
  112. data/vendor/simdjson/style/clang-format.sh +25 -0
  113. data/vendor/simdjson/style/run-clang-format.py +326 -0
  114. data/vendor/simdjson/tape.md +134 -0
  115. data/vendor/simdjson/tests/CMakeLists.txt +25 -0
  116. data/vendor/simdjson/tests/allparserscheckfile.cpp +192 -0
  117. data/vendor/simdjson/tests/basictests.cpp +75 -0
  118. data/vendor/simdjson/tests/jsoncheck.cpp +136 -0
  119. data/vendor/simdjson/tests/numberparsingcheck.cpp +224 -0
  120. data/vendor/simdjson/tests/pointercheck.cpp +38 -0
  121. data/vendor/simdjson/tests/singleheadertest.cpp +22 -0
  122. data/vendor/simdjson/tests/stringparsingcheck.cpp +408 -0
  123. data/vendor/simdjson/tools/CMakeLists.txt +3 -0
  124. data/vendor/simdjson/tools/cmake/FindCTargets.cmake +15 -0
  125. data/vendor/simdjson/tools/cmake/FindOptions.cmake +52 -0
  126. data/vendor/simdjson/tools/json2json.cpp +112 -0
  127. data/vendor/simdjson/tools/jsonpointer.cpp +93 -0
  128. data/vendor/simdjson/tools/jsonstats.cpp +143 -0
  129. data/vendor/simdjson/tools/minify.cpp +21 -0
  130. data/vendor/simdjson/tools/release.py +125 -0
  131. data/vendor/simdjson/windows/dirent_portable.h +1043 -0
  132. metadata +273 -0
@@ -0,0 +1,67 @@
1
+ if(${CMAKE_C_COMPILER_ID} MATCHES "Intel") # icc / icpc
2
+ # prevent shared libraries from depending on Intel provided libraries
3
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel")
4
+ endif()
5
+
6
+ include(GNUInstallDirs)
7
+
8
+ # we default on a shared library.
9
+ if(SIMDJSON_BUILD_STATIC)
10
+ set(SIMDJSON_LIB_TYPE STATIC)
11
+ MESSAGE( STATUS "Building a static library." )
12
+ else()
13
+ MESSAGE( STATUS "Building a dynamic library (default)." )
14
+ set(SIMDJSON_LIB_TYPE SHARED)
15
+ endif()
16
+
17
+ MESSAGE( STATUS "SIMDJSON_LIB_TYPE: " ${SIMDJSON_LIB_TYPE})
18
+ set(SIMDJSON_SRC
19
+ jsonioutil.cpp
20
+ jsonminifier.cpp
21
+ jsonparser.cpp
22
+ stage1_find_marks.cpp
23
+ stage2_build_tape.cpp
24
+ parsedjson.cpp
25
+ parsedjsoniterator.cpp
26
+ simdjson.cpp
27
+ )
28
+
29
+ add_library(${SIMDJSON_LIB_NAME} ${SIMDJSON_LIB_TYPE} ${SIMDJSON_SRC})
30
+
31
+ target_include_directories(${SIMDJSON_LIB_NAME}
32
+ PUBLIC
33
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
34
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
35
+ )
36
+
37
+ install(TARGETS ${SIMDJSON_LIB_NAME}
38
+ EXPORT ${SIMDJSON_LIB_NAME}-config
39
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
40
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
41
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
42
+ )
43
+
44
+ install(EXPORT ${SIMDJSON_LIB_NAME}-config
45
+ FILE ${SIMDJSON_LIB_NAME}-config.cmake
46
+ NAMESPACE ${SIMDJSON_LIB_NAME}::
47
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${SIMDJSON_LIB_NAME}
48
+ )
49
+
50
+ if(NOT MSVC)
51
+ ## We output the library at the root of the current directory where cmake is invoked
52
+ ## This is handy but Visual Studio will happily ignore us
53
+ set_target_properties(${SIMDJSON_LIB_NAME} PROPERTIES
54
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
55
+ VERSION ${SIMDJSON_LIB_VERSION}
56
+ SOVERSION ${SIMDJSON_LIB_SOVERSION})
57
+ MESSAGE( STATUS "Library output directory (does not apply to Visual Studio): " ${CMAKE_BINARY_DIR})
58
+ endif()
59
+
60
+ if(MSVC AND (SIMDJSON_LIB_TYPE STREQUAL "SHARED"))
61
+ if (CMAKE_VERSION VERSION_LESS 3.4)
62
+ MESSAGE( STATUS "To build a Windows DLL using Visual Studio, you may need cmake 3.4 or better." )
63
+ endif()
64
+ MESSAGE( STATUS "Building a Windows DLL using Visual Studio, exporting all symbols automatically." )
65
+ set_target_properties(${SIMDJSON_LIB_NAME}
66
+ PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS 1)
67
+ endif()
@@ -0,0 +1,35 @@
1
+ #include "simdjson/jsonioutil.h"
2
+ #include <cstdlib>
3
+ #include <cstring>
4
+
5
+ namespace simdjson {
6
+ char *allocate_padded_buffer(size_t length) {
7
+ // we could do a simple malloc
8
+ // return (char *) malloc(length + SIMDJSON_PADDING);
9
+ // However, we might as well align to cache lines...
10
+ size_t totalpaddedlength = length + SIMDJSON_PADDING;
11
+ char *padded_buffer = aligned_malloc_char(64, totalpaddedlength);
12
+ return padded_buffer;
13
+ }
14
+
15
+ padded_string get_corpus(const std::string &filename) {
16
+ std::FILE *fp = std::fopen(filename.c_str(), "rb");
17
+ if (fp != nullptr) {
18
+ std::fseek(fp, 0, SEEK_END);
19
+ size_t len = std::ftell(fp);
20
+ padded_string s(len);
21
+ if (s.data() == nullptr) {
22
+ std::fclose(fp);
23
+ throw std::runtime_error("could not allocate memory");
24
+ }
25
+ std::rewind(fp);
26
+ size_t readb = std::fread(s.data(), 1, len, fp);
27
+ std::fclose(fp);
28
+ if (readb != len) {
29
+ throw std::runtime_error("could not read the data");
30
+ }
31
+ return s;
32
+ }
33
+ throw std::runtime_error("could not load corpus");
34
+ }
35
+ } // namespace simdjson
@@ -0,0 +1,285 @@
1
+ #include "simdjson/portability.h"
2
+ #include <cstdint>
3
+
4
+ #ifndef __AVX2__
5
+
6
+ namespace simdjson {
7
+ static uint8_t jump_table[256 * 3] = {
8
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
9
+ 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1,
10
+ 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
11
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0,
12
+ 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1,
13
+ 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
14
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
15
+ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1,
16
+ 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
17
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
18
+ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1,
19
+ 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
20
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
21
+ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1,
22
+ 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
23
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
24
+ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1,
25
+ 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
26
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
27
+ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1,
28
+ 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
29
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
30
+ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1,
31
+ 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
32
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
33
+ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1,
34
+ 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
35
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0,
36
+ 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1,
37
+ 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
38
+ 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
39
+ };
40
+
41
+ size_t json_minify(const unsigned char *bytes, size_t how_many,
42
+ unsigned char *out) {
43
+ size_t i = 0, pos = 0;
44
+ uint8_t quote = 0;
45
+ uint8_t nonescape = 1;
46
+
47
+ while (i < how_many) {
48
+ unsigned char c = bytes[i];
49
+ uint8_t *meta = jump_table + 3 * c;
50
+
51
+ quote = quote ^ (meta[0] & nonescape);
52
+ out[pos] = c;
53
+ pos += meta[2] | quote;
54
+
55
+ i += 1;
56
+ nonescape = (~nonescape) | (meta[1]);
57
+ }
58
+ return pos;
59
+ }
60
+ } // namespace simdjson
61
+ #else
62
+ #include "simdjson/simdprune_tables.h"
63
+ #include <cstring>
64
+
65
+ namespace simdjson {
66
+
67
+ // some intrinsics are missing under GCC?
68
+ #ifndef __clang__
69
+ #ifndef _MSC_VER
70
+ static __m256i inline _mm256_loadu2_m128i(__m128i const *__addr_hi,
71
+ __m128i const *__addr_lo) {
72
+ __m256i __v256 = _mm256_castsi128_si256(_mm_loadu_si128(__addr_lo));
73
+ return _mm256_insertf128_si256(__v256, _mm_loadu_si128(__addr_hi), 1);
74
+ }
75
+
76
+ static inline void _mm256_storeu2_m128i(__m128i *__addr_hi, __m128i *__addr_lo,
77
+ __m256i __a) {
78
+ __m128i __v128;
79
+ __v128 = _mm256_castsi256_si128(__a);
80
+ _mm_storeu_si128(__addr_lo, __v128);
81
+ __v128 = _mm256_extractf128_si256(__a, 1);
82
+ _mm_storeu_si128(__addr_hi, __v128);
83
+ }
84
+ #endif
85
+ #endif
86
+
87
+ // a straightforward comparison of a mask against input.
88
+ static uint64_t cmp_mask_against_input_mini(__m256i input_lo, __m256i input_hi,
89
+ __m256i mask) {
90
+ __m256i cmp_res_0 = _mm256_cmpeq_epi8(input_lo, mask);
91
+ uint64_t res_0 = static_cast<uint32_t>(_mm256_movemask_epi8(cmp_res_0));
92
+ __m256i cmp_res_1 = _mm256_cmpeq_epi8(input_hi, mask);
93
+ uint64_t res_1 = _mm256_movemask_epi8(cmp_res_1);
94
+ return res_0 | (res_1 << 32);
95
+ }
96
+
97
+ // take input from buf and remove useless whitespace, input and output can be
98
+ // the same, result is null terminated, return the string length (minus the null
99
+ // termination)
100
+ size_t json_minify(const uint8_t *buf, size_t len, uint8_t *out) {
101
+ // Useful constant masks
102
+ const uint64_t even_bits = 0x5555555555555555ULL;
103
+ const uint64_t odd_bits = ~even_bits;
104
+ uint8_t *initout(out);
105
+ uint64_t prev_iter_ends_odd_backslash =
106
+ 0ULL; // either 0 or 1, but a 64-bit value
107
+ uint64_t prev_iter_inside_quote = 0ULL; // either all zeros or all ones
108
+ size_t idx = 0;
109
+ if (len >= 64) {
110
+ size_t avx_len = len - 63;
111
+
112
+ for (; idx < avx_len; idx += 64) {
113
+ __m256i input_lo =
114
+ _mm256_loadu_si256(reinterpret_cast<const __m256i *>(buf + idx + 0));
115
+ __m256i input_hi =
116
+ _mm256_loadu_si256(reinterpret_cast<const __m256i *>(buf + idx + 32));
117
+ uint64_t bs_bits = cmp_mask_against_input_mini(input_lo, input_hi,
118
+ _mm256_set1_epi8('\\'));
119
+ uint64_t start_edges = bs_bits & ~(bs_bits << 1);
120
+ uint64_t even_start_mask = even_bits ^ prev_iter_ends_odd_backslash;
121
+ uint64_t even_starts = start_edges & even_start_mask;
122
+ uint64_t odd_starts = start_edges & ~even_start_mask;
123
+ uint64_t even_carries = bs_bits + even_starts;
124
+ uint64_t odd_carries;
125
+ bool iter_ends_odd_backslash =
126
+ add_overflow(bs_bits, odd_starts, &odd_carries);
127
+ odd_carries |= prev_iter_ends_odd_backslash;
128
+ prev_iter_ends_odd_backslash = iter_ends_odd_backslash ? 0x1ULL : 0x0ULL;
129
+ uint64_t even_carry_ends = even_carries & ~bs_bits;
130
+ uint64_t odd_carry_ends = odd_carries & ~bs_bits;
131
+ uint64_t even_start_odd_end = even_carry_ends & odd_bits;
132
+ uint64_t odd_start_even_end = odd_carry_ends & even_bits;
133
+ uint64_t odd_ends = even_start_odd_end | odd_start_even_end;
134
+ uint64_t quote_bits = cmp_mask_against_input_mini(input_lo, input_hi,
135
+ _mm256_set1_epi8('"'));
136
+ quote_bits = quote_bits & ~odd_ends;
137
+ uint64_t quote_mask = _mm_cvtsi128_si64(_mm_clmulepi64_si128(
138
+ _mm_set_epi64x(0ULL, quote_bits), _mm_set1_epi8(0xFF), 0));
139
+ quote_mask ^= prev_iter_inside_quote;
140
+ prev_iter_inside_quote = static_cast<uint64_t>(
141
+ static_cast<int64_t>(quote_mask) >>
142
+ 63); // might be undefined behavior, should be fully defined in C++20,
143
+ // ok according to John Regher from Utah University
144
+ const __m256i low_nibble_mask = _mm256_setr_epi8(
145
+ // 0 9 a b c d
146
+ 16, 0, 0, 0, 0, 0, 0, 0, 0, 8, 12, 1, 2, 9, 0, 0, 16, 0, 0, 0, 0, 0,
147
+ 0, 0, 0, 8, 12, 1, 2, 9, 0, 0);
148
+ const __m256i high_nibble_mask = _mm256_setr_epi8(
149
+ // 0 2 3 5 7
150
+ 8, 0, 18, 4, 0, 1, 0, 1, 0, 0, 0, 3, 2, 1, 0, 0, 8, 0, 18, 4, 0, 1, 0,
151
+ 1, 0, 0, 0, 3, 2, 1, 0, 0);
152
+ __m256i whitespace_shufti_mask = _mm256_set1_epi8(0x18);
153
+ __m256i v_lo = _mm256_and_si256(
154
+ _mm256_shuffle_epi8(low_nibble_mask, input_lo),
155
+ _mm256_shuffle_epi8(high_nibble_mask,
156
+ _mm256_and_si256(_mm256_srli_epi32(input_lo, 4),
157
+ _mm256_set1_epi8(0x7f))));
158
+
159
+ __m256i v_hi = _mm256_and_si256(
160
+ _mm256_shuffle_epi8(low_nibble_mask, input_hi),
161
+ _mm256_shuffle_epi8(high_nibble_mask,
162
+ _mm256_and_si256(_mm256_srli_epi32(input_hi, 4),
163
+ _mm256_set1_epi8(0x7f))));
164
+ __m256i tmp_ws_lo = _mm256_cmpeq_epi8(
165
+ _mm256_and_si256(v_lo, whitespace_shufti_mask), _mm256_set1_epi8(0));
166
+ __m256i tmp_ws_hi = _mm256_cmpeq_epi8(
167
+ _mm256_and_si256(v_hi, whitespace_shufti_mask), _mm256_set1_epi8(0));
168
+
169
+ uint64_t ws_res_0 =
170
+ static_cast<uint32_t>(_mm256_movemask_epi8(tmp_ws_lo));
171
+ uint64_t ws_res_1 = _mm256_movemask_epi8(tmp_ws_hi);
172
+ uint64_t whitespace = ~(ws_res_0 | (ws_res_1 << 32));
173
+ whitespace &= ~quote_mask;
174
+ int mask1 = whitespace & 0xFFFF;
175
+ int mask2 = (whitespace >> 16) & 0xFFFF;
176
+ int mask3 = (whitespace >> 32) & 0xFFFF;
177
+ int mask4 = (whitespace >> 48) & 0xFFFF;
178
+ int pop1 = hamming((~whitespace) & 0xFFFF);
179
+ int pop2 = hamming((~whitespace) & UINT64_C(0xFFFFFFFF));
180
+ int pop3 = hamming((~whitespace) & UINT64_C(0xFFFFFFFFFFFF));
181
+ int pop4 = hamming((~whitespace));
182
+ __m256i vmask1 = _mm256_loadu2_m128i(
183
+ reinterpret_cast<const __m128i *>(mask128_epi8) + (mask2 & 0x7FFF),
184
+ reinterpret_cast<const __m128i *>(mask128_epi8) + (mask1 & 0x7FFF));
185
+ __m256i vmask2 = _mm256_loadu2_m128i(
186
+ reinterpret_cast<const __m128i *>(mask128_epi8) + (mask4 & 0x7FFF),
187
+ reinterpret_cast<const __m128i *>(mask128_epi8) + (mask3 & 0x7FFF));
188
+ __m256i result1 = _mm256_shuffle_epi8(input_lo, vmask1);
189
+ __m256i result2 = _mm256_shuffle_epi8(input_hi, vmask2);
190
+ _mm256_storeu2_m128i(reinterpret_cast<__m128i *>(out + pop1),
191
+ reinterpret_cast<__m128i *>(out), result1);
192
+ _mm256_storeu2_m128i(reinterpret_cast<__m128i *>(out + pop3),
193
+ reinterpret_cast<__m128i *>(out + pop2), result2);
194
+ out += pop4;
195
+ }
196
+ }
197
+ // we finish off the job... copying and pasting the code is not ideal here,
198
+ // but it gets the job done.
199
+ if (idx < len) {
200
+ uint8_t buffer[64];
201
+ memset(buffer, 0, 64);
202
+ memcpy(buffer, buf + idx, len - idx);
203
+ __m256i input_lo =
204
+ _mm256_loadu_si256(reinterpret_cast<const __m256i *>(buffer));
205
+ __m256i input_hi =
206
+ _mm256_loadu_si256(reinterpret_cast<const __m256i *>(buffer + 32));
207
+ uint64_t bs_bits =
208
+ cmp_mask_against_input_mini(input_lo, input_hi, _mm256_set1_epi8('\\'));
209
+ uint64_t start_edges = bs_bits & ~(bs_bits << 1);
210
+ uint64_t even_start_mask = even_bits ^ prev_iter_ends_odd_backslash;
211
+ uint64_t even_starts = start_edges & even_start_mask;
212
+ uint64_t odd_starts = start_edges & ~even_start_mask;
213
+ uint64_t even_carries = bs_bits + even_starts;
214
+ uint64_t odd_carries;
215
+ // bool iter_ends_odd_backslash =
216
+ add_overflow(bs_bits, odd_starts, &odd_carries);
217
+ odd_carries |= prev_iter_ends_odd_backslash;
218
+ // prev_iter_ends_odd_backslash = iter_ends_odd_backslash ? 0x1ULL : 0x0ULL;
219
+ // // we never use it
220
+ uint64_t even_carry_ends = even_carries & ~bs_bits;
221
+ uint64_t odd_carry_ends = odd_carries & ~bs_bits;
222
+ uint64_t even_start_odd_end = even_carry_ends & odd_bits;
223
+ uint64_t odd_start_even_end = odd_carry_ends & even_bits;
224
+ uint64_t odd_ends = even_start_odd_end | odd_start_even_end;
225
+ uint64_t quote_bits =
226
+ cmp_mask_against_input_mini(input_lo, input_hi, _mm256_set1_epi8('"'));
227
+ quote_bits = quote_bits & ~odd_ends;
228
+ uint64_t quote_mask = _mm_cvtsi128_si64(_mm_clmulepi64_si128(
229
+ _mm_set_epi64x(0ULL, quote_bits), _mm_set1_epi8(0xFF), 0));
230
+ quote_mask ^= prev_iter_inside_quote;
231
+ // prev_iter_inside_quote = (uint64_t)((int64_t)quote_mask >> 63);// we
232
+ // don't need this anymore
233
+
234
+ __m256i mask_20 = _mm256_set1_epi8(0x20); // c==32
235
+ __m256i mask_70 =
236
+ _mm256_set1_epi8(0x70); // adding 0x70 does not check low 4-bits
237
+ // but moves any value >= 16 above 128
238
+
239
+ __m256i lut_cntrl = _mm256_setr_epi8(
240
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00,
241
+ 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00);
243
+
244
+ __m256i tmp_ws_lo = _mm256_or_si256(
245
+ _mm256_cmpeq_epi8(mask_20, input_lo),
246
+ _mm256_shuffle_epi8(lut_cntrl, _mm256_adds_epu8(mask_70, input_lo)));
247
+ __m256i tmp_ws_hi = _mm256_or_si256(
248
+ _mm256_cmpeq_epi8(mask_20, input_hi),
249
+ _mm256_shuffle_epi8(lut_cntrl, _mm256_adds_epu8(mask_70, input_hi)));
250
+ uint64_t ws_res_0 = static_cast<uint32_t>(_mm256_movemask_epi8(tmp_ws_lo));
251
+ uint64_t ws_res_1 = _mm256_movemask_epi8(tmp_ws_hi);
252
+ uint64_t whitespace = (ws_res_0 | (ws_res_1 << 32));
253
+ whitespace &= ~quote_mask;
254
+
255
+ if (len - idx < 64) {
256
+ whitespace |= UINT64_C(0xFFFFFFFFFFFFFFFF) << (len - idx);
257
+ }
258
+ int mask1 = whitespace & 0xFFFF;
259
+ int mask2 = (whitespace >> 16) & 0xFFFF;
260
+ int mask3 = (whitespace >> 32) & 0xFFFF;
261
+ int mask4 = (whitespace >> 48) & 0xFFFF;
262
+ int pop1 = hamming((~whitespace) & 0xFFFF);
263
+ int pop2 = hamming((~whitespace) & UINT64_C(0xFFFFFFFF));
264
+ int pop3 = hamming((~whitespace) & UINT64_C(0xFFFFFFFFFFFF));
265
+ int pop4 = hamming((~whitespace));
266
+ __m256i vmask1 = _mm256_loadu2_m128i(
267
+ reinterpret_cast<const __m128i *>(mask128_epi8) + (mask2 & 0x7FFF),
268
+ reinterpret_cast<const __m128i *>(mask128_epi8) + (mask1 & 0x7FFF));
269
+ __m256i vmask2 = _mm256_loadu2_m128i(
270
+ reinterpret_cast<const __m128i *>(mask128_epi8) + (mask4 & 0x7FFF),
271
+ reinterpret_cast<const __m128i *>(mask128_epi8) + (mask3 & 0x7FFF));
272
+ __m256i result1 = _mm256_shuffle_epi8(input_lo, vmask1);
273
+ __m256i result2 = _mm256_shuffle_epi8(input_hi, vmask2);
274
+ _mm256_storeu2_m128i(reinterpret_cast<__m128i *>(buffer + pop1),
275
+ reinterpret_cast<__m128i *>(buffer), result1);
276
+ _mm256_storeu2_m128i(reinterpret_cast<__m128i *>(buffer + pop3),
277
+ reinterpret_cast<__m128i *>(buffer + pop2), result2);
278
+ memcpy(out, buffer, pop4);
279
+ out += pop4;
280
+ }
281
+ *out = '\0'; // NULL termination
282
+ return out - initout;
283
+ }
284
+ } // namespace simdjson
285
+ #endif
@@ -0,0 +1,91 @@
1
+ #include "simdjson/jsonparser.h"
2
+ #include "simdjson/isadetection.h"
3
+ #include "simdjson/portability.h"
4
+ #include "simdjson/simdjson.h"
5
+
6
+ namespace simdjson {
7
+
8
+ // The function that users are expected to call is json_parse.
9
+ // We have more than one such function because we want to support several
10
+ // instruction sets.
11
+
12
+ // function pointer type for json_parse
13
+ using json_parse_functype = int(const uint8_t *buf, size_t len, ParsedJson &pj,
14
+ bool realloc_if_needed);
15
+
16
+ // Pointer that holds the json_parse implementation corresponding to the
17
+ // available SIMD instruction set
18
+ extern json_parse_functype *json_parse_ptr;
19
+
20
+ int json_parse(const uint8_t *buf, size_t len, ParsedJson &pj,
21
+ bool realloc_if_needed) {
22
+ return json_parse_ptr(buf, len, pj, realloc_if_needed);
23
+ }
24
+
25
+ int json_parse(const char *buf, size_t len, ParsedJson &pj,
26
+ bool realloc_if_needed) {
27
+ return json_parse_ptr(reinterpret_cast<const uint8_t *>(buf), len, pj,
28
+ realloc_if_needed);
29
+ }
30
+
31
+ Architecture find_best_supported_implementation() {
32
+ constexpr uint32_t haswell_flags =
33
+ instruction_set::AVX2 | instruction_set::PCLMULQDQ |
34
+ instruction_set::BMI1 | instruction_set::BMI2;
35
+ constexpr uint32_t westmere_flags =
36
+ instruction_set::SSE42 | instruction_set::PCLMULQDQ;
37
+
38
+ uint32_t supports = detect_supported_architectures();
39
+ // Order from best to worst (within architecture)
40
+ if ((haswell_flags & supports) == haswell_flags)
41
+ return Architecture::HASWELL;
42
+ if ((westmere_flags & supports) == westmere_flags)
43
+ return Architecture::WESTMERE;
44
+ if (instruction_set::NEON)
45
+ return Architecture::ARM64;
46
+
47
+ return Architecture::NONE;
48
+ }
49
+
50
+ // Responsible to select the best json_parse implementation
51
+ int json_parse_dispatch(const uint8_t *buf, size_t len, ParsedJson &pj,
52
+ bool realloc_if_needed) {
53
+ Architecture best_implementation = find_best_supported_implementation();
54
+ // Selecting the best implementation
55
+ switch (best_implementation) {
56
+ #ifdef IS_X86_64
57
+ case Architecture::HASWELL:
58
+ json_parse_ptr = &json_parse_implementation<Architecture::HASWELL>;
59
+ break;
60
+ case Architecture::WESTMERE:
61
+ json_parse_ptr = &json_parse_implementation<Architecture::WESTMERE>;
62
+ break;
63
+ #endif
64
+ #ifdef IS_ARM64
65
+ case Architecture::ARM64:
66
+ json_parse_ptr = &json_parse_implementation<Architecture::ARM64>;
67
+ break;
68
+ #endif
69
+ default:
70
+ std::cerr << "The processor is not supported by simdjson." << std::endl;
71
+ return simdjson::UNEXPECTED_ERROR;
72
+ }
73
+
74
+ return json_parse_ptr(buf, len, pj, realloc_if_needed);
75
+ }
76
+
77
+ json_parse_functype *json_parse_ptr = &json_parse_dispatch;
78
+
79
+ WARN_UNUSED
80
+ ParsedJson build_parsed_json(const uint8_t *buf, size_t len,
81
+ bool realloc_if_needed) {
82
+ ParsedJson pj;
83
+ bool ok = pj.allocate_capacity(len);
84
+ if (ok) {
85
+ json_parse(buf, len, pj, realloc_if_needed);
86
+ } else {
87
+ std::cerr << "failure during memory allocation " << std::endl;
88
+ }
89
+ return pj;
90
+ }
91
+ } // namespace simdjson