Skip to content

Commit 47859f3

Browse files
authored
Merge pull request simdjson#628 from simdjson/jkeiser/remove-simdjson-move-result
Remove simdjson_move_result and remove deprecation warnings
2 parents 56d1b9a + 90a7503 commit 47859f3

16 files changed

+249
-388
lines changed

.circleci/config.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ executors:
77
- image: gcc:7
88
environment:
99
CXX: g++
10+
gcc8:
11+
docker:
12+
- image: gcc:8
13+
environment:
14+
CXX: g++
15+
gcc9:
16+
docker:
17+
- image: gcc:9
18+
environment:
19+
CXX: g++
1020
clang6:
1121
docker:
1222
- image: ubuntu:18.04
@@ -31,6 +41,14 @@ commands:
3141
- run: ARCHFLAGS=-march=haswell make test # this breaks runtime dispatch, but see https://github.com/lemire/simdjson/issues/444... this is a code robustness test
3242
- run: make clean
3343
- run: EXTRAFLAGS=-DSIMDJSON_NO_COMPUTED_GOTO=true make test # this should run tests with computed gotos disabled
44+
make_test_strict:
45+
steps:
46+
- checkout
47+
- run: EXTRAFLAGS=-Werror make
48+
- run: EXTRAFLAGS=-Werror make amalgamate
49+
- run: ARCHFLAGS=-march=haswell make amalgamate # some users do this: https://github.com/lemire/simdjson/issues/444
50+
- run: EXTRAFLAGS=-Werror make quicktests
51+
- run: make clean
3452

3553
cmake_test:
3654
steps:
@@ -65,6 +83,14 @@ jobs:
6583
environment: { CMAKE_TEST_FLAGS: -DSIMDJSON_ENABLE_THREADS=ON }
6684
steps: [ init_clang6, cmake_test ]
6785

86+
gcc9-avx:
87+
description: Build, run tests and check performance on GCC 9 and AVX 2
88+
executor: gcc9
89+
steps: [ make_test_strict ]
90+
gcc8-avx:
91+
description: Build, run tests and check performance on GCC 8 and AVX 2
92+
executor: gcc9
93+
steps: [ make_test_strict ]
6894
gcc-avx:
6995
description: Build, run tests and check performance on GCC 7 and AVX 2
7096
executor: gcc7
@@ -161,6 +187,8 @@ workflows:
161187
version: 2.1
162188
build_and_test:
163189
jobs:
190+
- gcc9-avx
191+
- gcc8-avx
164192
- gcc-avx
165193
- gcc-avx-dynamic
166194
- gcc-avx-static

include/simdjson/common_defs.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,12 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
7373
#define unlikely(x) x
7474
#endif
7575

76+
#define SIMDJSON_PUSH_DISABLE_WARNINGS __pragma(warning( push ))
77+
#define SIMDJSON_DISABLE_VS_WARNING(WARNING_NUMBER) __pragma(warning( disable : WARNING_NUMBER ))
78+
#define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_VS_WARNING(4996)
79+
#define SIMDJSON_POP_DISABLE_WARNINGS __pragma(warning( pop ))
7680

77-
#else
81+
#else // MSC_VER
7882

7983

8084
#define really_inline inline __attribute__((always_inline, unused))
@@ -90,6 +94,12 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
9094
#define unlikely(x) __builtin_expect(!!(x), 0)
9195
#endif
9296

97+
#define SIMDJSON_PUSH_DISABLE_WARNINGS _Pragma("GCC diagnostic push")
98+
#define SIMDJSON_PRAGMA(P) _Pragma(#P)
99+
#define SIMDJSON_DISABLE_GCC_WARNING(WARNING) SIMDJSON_PRAGMA(GCC diagnostic ignored #WARNING)
100+
#define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wdeprecated-declarations)
101+
#define SIMDJSON_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop")
102+
93103
#endif // MSC_VER
94104

95105
#endif // SIMDJSON_COMMON_DEFS_H

include/simdjson/document.h

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,11 @@ class document::doc_result : public simdjson_result<document&> {
256256
*/
257257
inline array_result as_array() const noexcept;
258258

259+
/**
260+
* Get the root element of this document.
261+
*/
262+
inline element_result root() const noexcept;
263+
259264
/**
260265
* Get the value associated with the given JSON pointer.
261266
*
@@ -413,6 +418,11 @@ class document::element : protected internal::tape_ref {
413418
really_inline bool is_number() const noexcept;
414419
/** Whether this is a JSON integer (e.g. 1 or -1, but *not* 1.0 or 1e2) */
415420
really_inline bool is_integer() const noexcept;
421+
/** Whether this is a JSON integer in [9223372036854775808, 18446744073709551616)
422+
* that is, a value too large for a signed 64-bit integer, but that still fits
423+
* in a 64-bit word. Note that is_integer() is true when is_unsigned_integer()
424+
* is true.*/
425+
really_inline bool is_unsigned_integer() const noexcept;
416426
/** Whether this is a JSON number but not an integer */
417427
really_inline bool is_float() const noexcept;
418428
/** Whether this is a JSON string (e.g. "abc") */
@@ -889,17 +899,33 @@ class document::object : protected internal::tape_ref {
889899
/**
890900
* Get the value associated with the given key.
891901
*
892-
* Note: The key will be matched against **unescaped** JSON:
893-
*
894-
* document::parser parser;
895-
* parser.parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
896-
* parser.parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
902+
* Note: The key will be matched against **unescaped** JSON.
897903
*
898904
* @return The value associated with this field, or:
899905
* - NO_SUCH_FIELD if the field does not exist in the object
900906
*/
901907
inline element_result at_key(const char *s) const noexcept;
902908

909+
/**
910+
* Get the value associated with the given key, the provided key is
911+
* considered to have length characters.
912+
*
913+
* Note: The key will be matched against **unescaped** JSON.
914+
*
915+
* @return The value associated with this field, or:
916+
* - NO_SUCH_FIELD if the field does not exist in the object
917+
*/
918+
inline element_result at_key(const char *s, size_t length) const noexcept;
919+
/**
920+
* Get the value associated with the given key in a case-insensitive manner.
921+
*
922+
* Note: The key will be matched against **unescaped** JSON.
923+
*
924+
* @return The value associated with this field, or:
925+
* - NO_SUCH_FIELD if the field does not exist in the object
926+
*/
927+
inline element_result at_key_case_insensitive(const char *s) const noexcept;
928+
903929
private:
904930
really_inline object(const document *_doc, size_t _json_index) noexcept;
905931
friend class document::element;
@@ -926,7 +952,7 @@ class document::key_value_pair {
926952
class document::element_result : public simdjson_result<document::element> {
927953
public:
928954
really_inline element_result() noexcept;
929-
really_inline element_result(element value) noexcept;
955+
really_inline element_result(element &&value) noexcept;
930956
really_inline element_result(error_code error) noexcept;
931957

932958
/** Whether this is a JSON `null` */

include/simdjson/error.h

Lines changed: 14 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,12 @@ struct simdjson_result : public std::pair<T, error_code> {
8585
/**
8686
* Move the value and the error to the provided variables.
8787
*/
88-
void tie(T& t, error_code & e) {
88+
void tie(T& t, error_code & e) && noexcept {
8989
// on the clang compiler that comes with current macOS (Apple clang version 11.0.0),
9090
// tie(width, error) = size["w"].as_uint64_t();
9191
// fails with "error: no viable overloaded '='""
92-
t = std::move(this->first);
93-
e = std::move(this->second);
92+
t = std::forward<simdjson_result<T>>(*this).first;
93+
e = this->second;
9494
}
9595

9696
/**
@@ -105,106 +105,51 @@ struct simdjson_result : public std::pair<T, error_code> {
105105
*
106106
* @throw simdjson_error if there was an error.
107107
*/
108-
T get() noexcept(false) {
108+
T& get() noexcept(false) {
109109
if (error()) { throw simdjson_error(error()); }
110110
return this->first;
111111
};
112112

113-
/**
114-
* Cast to the value (will throw on error).
115-
*
116-
* @throw simdjson_error if there was an error.
117-
*/
118-
operator T() noexcept(false) { return get(); }
119-
120-
#endif // SIMDJSON_EXCEPTIONS
121-
122-
/**
123-
* Create a new empty result with error = UNINITIALIZED.
124-
*/
125-
simdjson_result() noexcept : simdjson_result(UNINITIALIZED) {}
126-
127-
/**
128-
* Create a new error result.
129-
*/
130-
simdjson_result(error_code _error) noexcept : std::pair<T, error_code>({}, _error) {}
131-
132-
/**
133-
* Create a new successful result.
134-
*/
135-
simdjson_result(T _value) noexcept : std::pair<T, error_code>(_value, SUCCESS) {}
136-
137-
/**
138-
* Create a new result with both things (use if you don't want to branch when creating the result).
139-
*/
140-
simdjson_result(T value, error_code error) noexcept : std::pair<T, error_code>(value, error) {}
141-
};
142-
143-
/**
144-
* The result of a simd operation that could fail.
145-
*
146-
* This class is for values that must be *moved*, like padded_string and document.
147-
*
148-
* Gives the option of reading error codes, or throwing an exception by casting to the desired result.
149-
*/
150-
template<typename T>
151-
struct simdjson_move_result : std::pair<T, error_code> {
152-
/**
153-
* Move the value and the error to the provided variables.
154-
*/
155-
void tie(T& t, error_code & e) {
156-
// on the clang compiler that comes with current macOS (Apple clang version 11.0.0),
157-
// std::tie(this->json, error) = padded_string::load(filename);
158-
// fails with "benchmark/benchmarker.h:266:33: error: no viable overloaded '='""
159-
t = std::move(this->first);
160-
e = std::move(this->second);
161-
}
162-
163-
/**
164-
* The error.
165-
*/
166-
error_code error() const { return this->second; }
167-
168-
#if SIMDJSON_EXCEPTIONS
169-
170113
/**
171114
* The value of the function.
172115
*
173116
* @throw simdjson_error if there was an error.
174117
*/
175-
T move() noexcept(false) {
118+
T&& take() && {
176119
if (error()) { throw simdjson_error(error()); }
177-
return std::move(this->first);
120+
return std::forward<T>(this->first);
178121
};
179122

180123
/**
181124
* Cast to the value (will throw on error).
182125
*
183126
* @throw simdjson_error if there was an error.
184127
*/
185-
operator T() noexcept(false) { return move(); }
128+
operator T&&() && {
129+
return std::forward<simdjson_result<T>>(*this).take();
130+
}
186131

187-
#endif
132+
#endif // SIMDJSON_EXCEPTIONS
188133

189134
/**
190135
* Create a new empty result with error = UNINITIALIZED.
191136
*/
192-
simdjson_move_result() noexcept : simdjson_move_result(UNINITIALIZED) {}
137+
simdjson_result() noexcept : simdjson_result(UNINITIALIZED) {}
193138

194139
/**
195140
* Create a new error result.
196141
*/
197-
simdjson_move_result(error_code error) noexcept : std::pair<T, error_code>(T(), error) {}
142+
simdjson_result(error_code error) noexcept : std::pair<T, error_code>(T{}, error) {}
198143

199144
/**
200145
* Create a new successful result.
201146
*/
202-
simdjson_move_result(T value) noexcept : std::pair<T, error_code>(std::move(value), SUCCESS) {}
147+
simdjson_result(T &&value) noexcept : std::pair<T, error_code>(std::forward<T>(value), SUCCESS) {}
203148

204149
/**
205150
* Create a new result with both things (use if you don't want to branch when creating the result).
206151
*/
207-
simdjson_move_result(T value, error_code error) noexcept : std::pair<T, error_code>(std::move(value), error) {}
152+
simdjson_result(T &&value, error_code error) noexcept : std::pair<T, error_code>(std::forward<T>(value), error) {}
208153
};
209154

210155
/**

include/simdjson/inline/document.h

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace simdjson {
1717
// element_result inline implementation
1818
//
1919
really_inline document::element_result::element_result() noexcept : simdjson_result<element>() {}
20-
really_inline document::element_result::element_result(element value) noexcept : simdjson_result<element>(value) {}
20+
really_inline document::element_result::element_result(element &&value) noexcept : simdjson_result<element>((element&&)value) {}
2121
really_inline document::element_result::element_result(error_code error) noexcept : simdjson_result<element>(error) {}
2222
inline simdjson_result<bool> document::element_result::is_null() const noexcept {
2323
if (error()) { return error(); }
@@ -113,7 +113,7 @@ inline document::element_result::operator document::object() const noexcept(fals
113113
// array_result inline implementation
114114
//
115115
really_inline document::array_result::array_result() noexcept : simdjson_result<array>() {}
116-
really_inline document::array_result::array_result(array value) noexcept : simdjson_result<array>(value) {}
116+
really_inline document::array_result::array_result(array value) noexcept : simdjson_result<array>((array&&)value) {}
117117
really_inline document::array_result::array_result(error_code error) noexcept : simdjson_result<array>(error) {}
118118

119119
#if SIMDJSON_EXCEPTIONS
@@ -149,7 +149,7 @@ inline document::element_result document::array_result::at(size_t index) const n
149149
// object_result inline implementation
150150
//
151151
really_inline document::object_result::object_result() noexcept : simdjson_result<object>() {}
152-
really_inline document::object_result::object_result(object value) noexcept : simdjson_result<object>(value) {}
152+
really_inline document::object_result::object_result(object value) noexcept : simdjson_result<object>((object&&)value) {}
153153
really_inline document::object_result::object_result(error_code error) noexcept : simdjson_result<object>(error) {}
154154

155155
inline document::element_result document::object_result::operator[](std::string_view json_pointer) const noexcept {
@@ -359,12 +359,14 @@ inline bool document::dump_raw_tape(std::ostream &os) const noexcept {
359359
inline document::doc_result::doc_result(document &doc, error_code error) noexcept : simdjson_result<document&>(doc, error) { }
360360

361361
inline document::array_result document::doc_result::as_array() const noexcept {
362-
if (error()) { return error(); }
363-
return first.root().as_array();
362+
return root().as_array();
364363
}
365364
inline document::object_result document::doc_result::as_object() const noexcept {
365+
return root().as_object();
366+
}
367+
inline document::element_result document::doc_result::root() const noexcept {
366368
if (error()) { return error(); }
367-
return first.root().as_object();
369+
return first.root();
368370
}
369371

370372
inline document::element_result document::doc_result::operator[](std::string_view key) const noexcept {
@@ -783,6 +785,16 @@ inline document::element_result document::object::at(std::string_view json_point
783785

784786
return child;
785787
}
788+
inline document::element_result document::object::at_key(const char *key, size_t length) const noexcept {
789+
iterator end_field = end();
790+
for (iterator field = begin(); field != end_field; ++field) {
791+
std::string_view v{field.key()};
792+
if ((v.size() == length) && (!memcmp(v.data(), key, length))) {
793+
return field.value();
794+
}
795+
}
796+
return NO_SUCH_FIELD;
797+
}
786798
inline document::element_result document::object::at_key(std::string_view key) const noexcept {
787799
iterator end_field = end();
788800
for (iterator field = begin(); field != end_field; ++field) {
@@ -801,7 +813,18 @@ inline document::element_result document::object::at_key(const char *key) const
801813
}
802814
return NO_SUCH_FIELD;
803815
}
804-
816+
// In case you wonder why we need this, please see
817+
// https://github.com/simdjson/simdjson/issues/323
818+
// People do seek keys in a case-insensitive manner.
819+
inline document::element_result document::object::at_key_case_insensitive(const char *key) const noexcept {
820+
iterator end_field = end();
821+
for (iterator field = begin(); field != end_field; ++field) {
822+
if (!simdjson_strcasecmp(key, field.key_c_str())) {
823+
return field.value();
824+
}
825+
}
826+
return NO_SUCH_FIELD;
827+
}
805828
//
806829
// document::object::iterator inline implementation
807830
//
@@ -859,6 +882,9 @@ really_inline bool document::element::is_float() const noexcept {
859882
really_inline bool document::element::is_integer() const noexcept {
860883
return type() == internal::tape_type::UINT64 || type() == internal::tape_type::INT64;
861884
}
885+
really_inline bool document::element::is_unsigned_integer() const noexcept {
886+
return type() == internal::tape_type::UINT64;
887+
}
862888
really_inline bool document::element::is_string() const noexcept {
863889
return type() == internal::tape_type::STRING;
864890
}
@@ -951,7 +977,7 @@ inline simdjson_result<double> document::element::as_double() const noexcept {
951977
if (result < 0) {
952978
return NUMBER_OUT_OF_RANGE;
953979
}
954-
return result;
980+
return double(result);
955981
}
956982
case internal::tape_type::DOUBLE:
957983
return next_tape_value<double>();

0 commit comments

Comments
 (0)