1#include "simdjson/jsonparser.h"
2#include "simdjson/isadetection.h"
3#include "simdjson/portability.h"
4#include "simdjson/simdjson.h"
5#include <atomic>
6
7namespace simdjson {
8
9// The function that users are expected to call is json_parse.
10// We have more than one such function because we want to support several
11// instruction sets.
12
13// function pointer type for json_parse
14using json_parse_functype = int(const uint8_t *buf, size_t len, ParsedJson &pj,
15 bool realloc);
16
17// Pointer that holds the json_parse implementation corresponding to the
18// available SIMD instruction set
19extern std::atomic<json_parse_functype *> json_parse_ptr;
20
21int json_parse(const uint8_t *buf, size_t len, ParsedJson &pj,
22 bool realloc) {
23 return json_parse_ptr.load(std::memory_order_relaxed)(buf, len, pj, realloc);
24}
25
26int json_parse(const char *buf, size_t len, ParsedJson &pj,
27 bool realloc) {
28 return json_parse_ptr.load(std::memory_order_relaxed)(reinterpret_cast<const uint8_t *>(buf), len, pj,
29 realloc);
30}
31
32Architecture find_best_supported_architecture() {
33 constexpr uint32_t haswell_flags =
34 instruction_set::AVX2 | instruction_set::PCLMULQDQ |
35 instruction_set::BMI1 | instruction_set::BMI2;
36 constexpr uint32_t westmere_flags =
37 instruction_set::SSE42 | instruction_set::PCLMULQDQ;
38
39 uint32_t supports = detect_supported_architectures();
40 // Order from best to worst (within architecture)
41 if ((haswell_flags & supports) == haswell_flags)
42 return Architecture::HASWELL;
43 if ((westmere_flags & supports) == westmere_flags)
44 return Architecture::WESTMERE;
45 if (supports & instruction_set::NEON)
46 return Architecture::ARM64;
47
48 return Architecture::UNSUPPORTED;
49}
50
51Architecture parse_architecture(char *architecture) {
52 if (!strcmp(architecture, "HASWELL")) { return Architecture::HASWELL; }
53 if (!strcmp(architecture, "WESTMERE")) { return Architecture::WESTMERE; }
54 if (!strcmp(architecture, "ARM64")) { return Architecture::ARM64; }
55 return Architecture::UNSUPPORTED;
56}
57
58// Responsible to select the best json_parse implementation
59int json_parse_dispatch(const uint8_t *buf, size_t len, ParsedJson &pj,
60 bool realloc) {
61 Architecture best_implementation = find_best_supported_architecture();
62 // Selecting the best implementation
63 switch (best_implementation) {
64#ifdef IS_X86_64
65 case Architecture::HASWELL:
66 json_parse_ptr.store(&json_parse_implementation<Architecture::HASWELL>, std::memory_order_relaxed);
67 break;
68 case Architecture::WESTMERE:
69 json_parse_ptr.store(&json_parse_implementation<Architecture::WESTMERE>, std::memory_order_relaxed);
70 break;
71#endif
72#ifdef IS_ARM64
73 case Architecture::ARM64:
74 json_parse_ptr.store(&json_parse_implementation<Architecture::ARM64>, std::memory_order_relaxed);
75 break;
76#endif
77 default:
78 std::cerr << "The processor is not supported by simdjson." << std::endl;
79 return simdjson::UNEXPECTED_ERROR;
80 }
81
82 return json_parse_ptr.load(std::memory_order_relaxed)(buf, len, pj, realloc);
83}
84
85std::atomic<json_parse_functype *> json_parse_ptr{&json_parse_dispatch};
86
87WARN_UNUSED
88ParsedJson build_parsed_json(const uint8_t *buf, size_t len,
89 bool realloc) {
90 ParsedJson pj;
91 bool ok = pj.allocate_capacity(len);
92 if (ok) {
93 json_parse(buf, len, pj, realloc);
94 } else {
95 std::cerr << "failure during memory allocation " << std::endl;
96 }
97 return pj;
98}
99} // namespace simdjson
100