Skip to content

Commit 4dc2adf

Browse files
committed
Update README, add README examples
1 parent da34f9a commit 4dc2adf

5 files changed

Lines changed: 137 additions & 96 deletions

File tree

.drone.yml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ steps:
126126
environment:
127127
CC: clang
128128
CXX: clang++
129-
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_GOOGLE_BENCHMARKS=OFF
129+
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
130130
commands:
131131
- apt-get update -qq
132132
- apt-get install -y clang make cmake
@@ -149,7 +149,7 @@ steps:
149149
environment:
150150
CC: clang
151151
CXX: clang++
152-
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_GOOGLE_BENCHMARKS=OFF
152+
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON
153153
commands:
154154
- apt-get update -qq
155155
- apt-get install -y clang make cmake
@@ -218,7 +218,7 @@ steps:
218218
environment:
219219
CC: clang
220220
CXX: clang++
221-
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_GOOGLE_BENCHMARKS=OFF
221+
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
222222
commands:
223223
- apt-get update -qq
224224
- apt-get install -y clang make cmake
@@ -264,7 +264,7 @@ steps:
264264
environment:
265265
CC: clang
266266
CXX: clang++
267-
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_GOOGLE_BENCHMARKS=OFF
267+
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON
268268
commands:
269269
- apt-get update -qq
270270
- apt-get install -y clang make cmake
@@ -311,7 +311,7 @@ steps:
311311
environment:
312312
CC: clang
313313
CXX: clang++
314-
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=OFF
314+
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON
315315
commands:
316316
- apt-get update -qq
317317
- apt-get install -y clang make cmake
@@ -334,7 +334,7 @@ steps:
334334
environment:
335335
CC: gcc
336336
CXX: g++
337-
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=OFF
337+
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON
338338
commands:
339339
- apt-get update -qq
340340
- apt-get install -y cmake
@@ -358,7 +358,7 @@ steps:
358358
environment:
359359
CC: clang
360360
CXX: clang++
361-
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=OFF
361+
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON
362362
commands:
363363
- apt-get update -y
364364
- apt-get install -y make $CC g++ cmake
@@ -381,7 +381,7 @@ steps:
381381
environment:
382382
CC: gcc
383383
CXX: g++
384-
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=OFF
384+
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON
385385
commands:
386386
- apt-get update -qq
387387
- apt-get install -y cmake
@@ -405,7 +405,7 @@ steps:
405405
environment:
406406
CC: clang
407407
CXX: clang++
408-
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_DISABLE_AVX=ON -DSIMDJSON_GOOGLE_BENCHMARKS=OFF
408+
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_DISABLE_AVX=ON
409409
commands:
410410
- apt-get update -qq
411411
- apt-get install -y clang make cmake
@@ -428,7 +428,7 @@ steps:
428428
environment:
429429
CC: gcc
430430
CXX: g++
431-
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_DISABLE_AVX=ON -DSIMDJSON_GOOGLE_BENCHMARKS=OFF
431+
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_DISABLE_AVX=ON
432432
commands:
433433
- apt-get update -qq
434434
- apt-get install -y cmake

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ objs
9595
/parsingcompetition
9696
/perfdiff
9797
/pointercheck
98+
/readme_examples
9899
/statisticalmodel
99100
/stringparsingcheck
100101
/submodules
@@ -108,9 +109,10 @@ objs
108109
/tests/jsoncheck
109110
/tests/pointercheck
110111
/tests/integer_tests
112+
/tests/jsonstream_test
113+
/tests/readme_examples
111114
/tools/json2json
112115
/tools/jsonstats
113-
/tests/jsonstream_test
114116
/tools/minify
115117

116118
# Don't check in generated examples

Makefile

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ benchmark:
105105
run_basictests: basictests
106106
./basictests
107107

108+
run_readme_examples: readme_examples
109+
./readme_examples
110+
108111
run_numberparsingcheck: numberparsingcheck
109112
./numberparsingcheck
110113

@@ -138,12 +141,12 @@ $(FEATURE_JSON_FILES): benchmark/genfeaturejson.rb
138141
run_benchfeatures: benchfeatures $(FEATURE_JSON_FILES)
139142
./benchfeatures -n 1000
140143

141-
test: run_basictests run_jsoncheck run_numberparsingcheck run_integer_tests run_stringparsingcheck run_jsonstream_test run_pointercheck run_testjson2json_sh run_issue150_sh run_jsoncheck_noavx
144+
test: run_basictests run_readme_examples run_jsoncheck run_numberparsingcheck run_integer_tests run_stringparsingcheck run_jsonstream_test run_pointercheck run_testjson2json_sh run_issue150_sh run_jsoncheck_noavx
142145
@echo "It looks like the code is good!"
143146

144-
quiettest: run_basictests run_jsoncheck run_numberparsingcheck run_integer_tests run_stringparsingcheck run_jsoncheck run_jsonstream_test run_pointercheck run_testjson2json_sh run_issue150_sh run_jsoncheck_noavx
147+
quiettest: run_basictests run_readme_examples run_jsoncheck run_numberparsingcheck run_integer_tests run_stringparsingcheck run_jsoncheck run_jsonstream_test run_pointercheck run_testjson2json_sh run_issue150_sh run_jsoncheck_noavx
145148

146-
quicktests: run_basictests run_jsoncheck run_numberparsingcheck run_integer_tests run_stringparsingcheck run_jsoncheck run_jsonstream_test run_pointercheck run_jsoncheck_noavx
149+
quicktests: run_basictests run_readme_examples run_jsoncheck run_numberparsingcheck run_integer_tests run_stringparsingcheck run_jsoncheck run_jsonstream_test run_pointercheck run_jsoncheck_noavx
147150

148151
slowtests: run_testjson2json_sh run_issue150_sh
149152

@@ -163,7 +166,6 @@ parse: benchmark/parse.cpp benchmark/json_parser.h benchmark/event_counter.h ben
163166
get_corpus_benchmark: benchmark/get_corpus_benchmark.cpp $(HEADERS) $(LIBFILES)
164167
$(CXX) $(CXXFLAGS) -o get_corpus_benchmark $(LIBFILES) benchmark/get_corpus_benchmark.cpp $(LIBFLAGS)
165168

166-
167169
parse_stream: benchmark/parse_stream.cpp benchmark/json_parser.h benchmark/event_counter.h benchmark/benchmarker.h $(HEADERS) $(LIBFILES)
168170
$(CXX) $(CXXFLAGS) -o parse_stream $(LIBFILES) benchmark/parse_stream.cpp $(LIBFLAGS)
169171

@@ -203,6 +205,9 @@ jsoncheck_noavx:tests/jsoncheck.cpp $(HEADERS) $(LIBFILES)
203205
basictests:tests/basictests.cpp $(HEADERS) $(LIBFILES)
204206
$(CXX) $(CXXFLAGS) -o basictests $(LIBFILES) tests/basictests.cpp -I. $(LIBFLAGS)
205207

208+
readme_examples: tests/readme_examples.cpp $(HEADERS) $(LIBFILES)
209+
$(CXX) $(CXXFLAGS) -o readme_examples $(LIBFILES) tests/readme_examples.cpp -I. $(LIBFLAGS)
210+
206211

207212
numberparsingcheck:tests/numberparsingcheck.cpp $(HEADERS) $(LIBFILES)
208213
$(CXX) $(CXXFLAGS) -o numberparsingcheck src/jsonioutil.cpp src/jsonparser.cpp src/error.cpp src/stage1_find_marks.cpp src/document.cpp src/document_parser.cpp tests/numberparsingcheck.cpp -I. $(LIBFLAGS) -DJSON_TEST_NUMBERS

README.md

Lines changed: 55 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ be concerned with computed gotos.
103103

104104
## Thread safety
105105

106-
The simdjson library is mostly single-threaded. Thread safety is the responsability of the caller: it is unsafe to reuse a ParsedJson object between different threads.
106+
The simdjson library is mostly single-threaded. Thread safety is the responsability of the caller: it is unsafe to reuse a document::parser object between different threads.
107107

108108
If you are on an x64 processor, the runtime dispatching assigns the right code path the first time that parsing is attempted. The runtime dispatching is thread-safe.
109109

@@ -117,89 +117,63 @@ You will get best performance with large or huge pages. Under Linux, you can ena
117117

118118
Another strategy is to reuse pre-allocated buffers. That is, you avoid reallocating memory. You just allocate memory once and reuse the blocks of memory.
119119

120-
## Code usage and example
120+
## Including simdjson
121121

122-
The main API involves populating a `ParsedJson` object which hosts a fully navigable document-object-model (DOM) view of the JSON document. The DOM can be accessed using [JSON Pointer](https://tools.ietf.org/html/rfc6901) paths, for example. The main function is `json_parse` which takes a string containing the JSON document as well as a reference to pre-allocated `ParsedJson` object (which can be reused multiple time). Once you have populated the `ParsedJson` object you can navigate through the DOM with an iterator (e.g., created by `ParsedJson::Iterator pjh(pj)`, see 'Navigating the parsed document').
123122

124-
// Samples:
125-
// Load a document from a file
126-
// Read a particular key / value from the document
127-
// Iterate over an array of things
123+
## Code usage and example
128124

129-
```c++
130-
#include "simdjson.h"
131-
auto doc = simdjson::document::load("myfile.json");
132-
cout << doc;
133-
for (auto i=doc.begin(); i<doc.end(); i++) {
134-
cout << doc[i];
135-
}
136-
```
125+
The main API involves allocating a `document::parser`, and calling `parser.parse()` to create a fully navigable document-object-model (DOM) view of a JSON document. The DOM can be accessed via [JSON Pointer](https://tools.ietf.org/html/rfc6901) paths, or as an iterator (`document::iterator(doc)`). See 'Navigating the parsed document' for more.
137126

138-
A slightly simpler API is available if you don't mind having the overhead
139-
of memory allocation with each new JSON document:
127+
All examples below use use `#include "simdjson.h"`, `#include "simdjson.cpp"` and `using namespace simdjson;`.
140128

141-
```C
142-
#include "simdjson/jsonparser.h"
143-
using namespace simdjson;
129+
The simplest API to get started is `document::parse()`, which allocates a new parser, parses a string, and returns the DOM. This is less efficient if you're going to read multiple documents, but as long as you're only parsing a single document, this will do just fine.
144130

145-
document doc = document::parse("myfile.json");
146-
cout << doc;
147-
/...
148-
149-
const char * filename = ... //
150-
padded_string p = get_corpus(filename);
151-
ParsedJson pj = build_parsed_json(p); // do the parsing
152-
if( ! pj.is_valid() ) {
153-
// something went wrong
154-
std::cout << pj.get_error_message() << std::endl;
155-
}
131+
```c++
132+
auto [doc, error] = document::parse(string("[ 1, 2, 3 ]"));
133+
if (error) { cerr << "Error: " << error_meesage(error) << endl; exit(1); }
134+
doc.print_json(cout);
156135
```
157136
158-
Though the `padded_string` class is recommended for best performance, you can call `json_parse` and `build_parsed_json`, passing a standard `std::string` object.
137+
If you're using exceptions, it gets even simpler (simdjson won't use exceptions internally, so you'll only pay the performance cost of exceptions in your own calling code):
159138
139+
```c++
140+
document doc = document::parse(string("[ 1, 2, 3 ]"));
141+
doc.print_json(cout);
142+
```
160143

161-
```C
162-
#include "simdjson/jsonparser.h"
163-
using namespace simdjson;
144+
simdjson requires SIMDJSON_PADDING extra bytes at the end of a string (it doesn't matter if the bytes are initialized). The `padded_string` class is an easy way to ensure this is accomplished up front and prevent the extra allocation:
164145

165-
/...
166-
std::string mystring = ... //
167-
ParsedJson pj;
168-
pj.allocate_capacity(mystring.size()); // allocate memory for parsing up to p.size() bytes
169-
// std::string may not overallocate so a copy will be needed
170-
const int res = json_parse(mystring, pj); // do the parsing, return 0 on success
171-
// parsing is done!
172-
if (res != 0) {
173-
// You can use the "simdjson/simdjson.h" header to access the error message
174-
std::cout << "Error parsing:" << simdjson::error_message(res) << std::endl;
175-
}
176-
// pj can be reused with other json_parse calls.
146+
```c++
147+
document doc = document::parse(padded_string(string("[ 1, 2, 3 ]")));
148+
doc.print_json(cout);
177149
```
178150

179-
or
151+
You can also load from a file with `get_corpus`:
180152

181-
```C
182-
#include "simdjson/jsonparser.h"
183-
using namespace simdjson;
153+
```c++
154+
document doc = document::parse(get_corpus(filename));
155+
doc.print_json(cout);
156+
```
184157

185-
/...
158+
If you're using simdjson to parse multiple documents, or in a loop, you should allocate a parser once and reuse it (allocation is slow, do it as little as possible!):
186159

187-
std::string mystring = ... //
188-
// std::string may not overallocate so a copy will be needed
189-
ParsedJson pj = build_parsed_json(mystring); // do the parsing
190-
if( ! pj.is_valid() ) {
191-
// something went wrong
192-
std::cout << pj.get_error_message() << std::endl;
160+
```c++
161+
// Allocate a parser big enough for all files
162+
document::parser parser;
163+
if (!parser.allocate_capacity(1024*1024)) { exit(1); }
164+
165+
// Read files with the parser, one by one
166+
for (padded_string json : { string("[1, 2, 3]"), string("true"), string("[ true, false ]") }) {
167+
cout << "Parsing " << json.data() << " ..." << endl;
168+
auto [doc, error] = parser.parse(json);
169+
if (error) { cerr << "Error: " << error_message(error) << endl; exit(1); }
170+
doc.print_json(cout);
171+
cout << endl;
193172
}
194173
```
195174

196-
As needed, the `json_parse` and `build_parsed_json` functions copy the input data to a temporary buffer readable up to SIMDJSON_PADDING bytes beyond the end of the data.
197-
198175
## Newline-Delimited JSON (ndjson) and JSON lines
199176

200-
201-
202-
203177
The simdjson library also support multithreaded JSON streaming through a large file containing many smaller JSON documents in either [ndjson](http://ndjson.org) or [JSON lines](http://jsonlines.org) format. We support files larger than 4GB.
204178

205179
**API and detailed documentation found [here](doc/JsonStream.md).**
@@ -212,14 +186,14 @@ Here is a simple example, using single header simdjson:
212186

213187
int parse_file(const char *filename) {
214188
simdjson::padded_string p = simdjson::get_corpus(filename);
215-
simdjson::ParsedJson pj;
189+
simdjson::document::parser parser;
216190
simdjson::JsonStream js{p};
217191
int parse_res = simdjson::SUCCESS_AND_HAS_MORE;
218192

219193
while (parse_res == simdjson::SUCCESS_AND_HAS_MORE) {
220-
parse_res = js.json_parse(pj);
194+
parse_res = js.json_parse(parser);
221195

222-
//Do something with pj...
196+
//Do something with parser...
223197
}
224198
}
225199
```
@@ -230,18 +204,18 @@ See the "singleheader" repository for a single header version. See the included
230204
file "amalgamation_demo.cpp" for usage. This requires no specific build system: just
231205
copy the files in your project in your include path. You can then include them quite simply:
232206
233-
```C
207+
```c++
234208
#include <iostream>
235209
#include "simdjson.h"
236210
#include "simdjson.cpp"
237211
using namespace simdjson;
238212
int main(int argc, char *argv[]) {
239213
const char * filename = argv[1];
240214
padded_string p = get_corpus(filename);
241-
ParsedJson pj = build_parsed_json(p); // do the parsing
242-
if( ! pj.is_valid() ) {
215+
document::parser parser = build_parsed_json(p); // do the parsing
216+
if( ! parser.is_valid() ) {
243217
std::cout << "not valid" << std::endl;
244-
std::cout << pj.get_error_message() << std::endl;
218+
std::cout << parser.get_error_message() << std::endl;
245219
} else {
246220
std::cout << "valid" << std::endl;
247221
}
@@ -427,21 +401,21 @@ make jsonpointer
427401
./jsonpointer jsonexamples/twitter.json /statuses/0/id /statuses/1/id /statuses/2/id /statuses/3/id /statuses/4/id /statuses/5/id
428402
```
429403

430-
In C++, given a `ParsedJson`, we can move to a node with the `move_to` method, passing a `std::string` representing the JSON Pointer query.
404+
In C++, given a `document::parser`, we can move to a node with the `move_to` method, passing a `std::string` representing the JSON Pointer query.
431405

432406
## Navigating the parsed document
433407

434408

435409

436-
From a `simdjson::ParsedJson` instance, you can create an iterator (of type `simdjson::ParsedJson::Iterator` which is in fact `simdjson::ParsedJson::BasicIterator<DEFAULT_MAX_DEPTH>` ) via a constructor:
410+
From a `simdjson::document::parser` instance, you can create an iterator (of type `simdjson::document::parser::Iterator` which is in fact `simdjson::document::parser::BasicIterator<DEFAULT_MAX_DEPTH>` ) via a constructor:
437411

438412
```
439-
ParsedJson::Iterator pjh(pj); // pj is a ParsedJSON
413+
document::parser::Iterator pjh(parser); // parser is a ParsedJSON
440414
```
441415

442-
You then have access to the following methods on the resulting `simdjson::ParsedJson::Iterator` instance:
416+
You then have access to the following methods on the resulting `simdjson::document::parser::Iterator` instance:
443417

444-
* `bool is_ok() const`: whether you have a valid iterator, will be false if your parent parsed ParsedJson is not a valid JSON.
418+
* `bool is_ok() const`: whether you have a valid iterator, will be false if your parent parsed document::parser is not a valid JSON.
445419
* `size_t get_depth() const`: returns the current depth (start at 1 with 0 reserved for the fictitious root node)
446420
* `int8_t get_scope_type() const`: a scope is a series of nodes at the same depth, typically it is either an object (`{`) or an array (`[`). The root node has type 'r'.
447421
* `bool move_forward()`: move forward in document order
@@ -482,17 +456,17 @@ You then have access to the following methods on the resulting `simdjson::Parsed
482456

483457
Here is a code sample to dump back the parsed JSON to a string:
484458

485-
```c
486-
ParsedJson::Iterator pjh(pj);
459+
```c++
460+
document::parser::Iterator pjh(parser);
487461
if (!pjh.is_ok()) {
488462
std::cerr << " Could not iterate parsed result. " << std::endl;
489463
return EXIT_FAILURE;
490464
}
491-
compute_dump(pj);
465+
compute_dump(parser);
492466
//
493467
// where compute_dump is :
494468

495-
void compute_dump(ParsedJson::Iterator &pjh) {
469+
void compute_dump(document::parser::Iterator &pjh) {
496470
if (pjh.is_object()) {
497471
std::cout << "{";
498472
if (pjh.down()) {
@@ -529,8 +503,8 @@ void compute_dump(ParsedJson::Iterator &pjh) {
529503
530504
The following function will find all user.id integers:
531505
532-
```C
533-
void simdjson_scan(std::vector<int64_t> &answer, ParsedJson::Iterator &i) {
506+
```c++
507+
void simdjson_scan(std::vector<int64_t> &answer, document::parser::Iterator &i) {
534508
while(i.move_forward()) {
535509
if(i.get_scope_type() == '{') {
536510
bool found_user = (i.get_string_length() == 4) && (memcmp(i.get_string(), "user", 4) == 0);

0 commit comments

Comments
 (0)