Merge pull request #949 from simdjson/jkeiser/get-type
Add non-template get_xxx/is_xxx methods to element
This commit is contained in:
commit
a5ccff720a
|
@ -16,12 +16,12 @@ class element;
|
|||
/**
|
||||
* JSON array.
|
||||
*/
|
||||
class array : protected internal::tape_ref {
|
||||
class array {
|
||||
public:
|
||||
/** Create a new, invalid array */
|
||||
really_inline array() noexcept;
|
||||
|
||||
class iterator : protected internal::tape_ref {
|
||||
class iterator {
|
||||
public:
|
||||
/**
|
||||
* Get the actual value
|
||||
|
@ -41,7 +41,8 @@ public:
|
|||
*/
|
||||
inline bool operator!=(const iterator& other) const noexcept;
|
||||
private:
|
||||
really_inline iterator(const document *doc, size_t json_index) noexcept;
|
||||
really_inline iterator(const internal::tape_ref &tape) noexcept;
|
||||
internal::tape_ref tape;
|
||||
friend class array;
|
||||
};
|
||||
|
||||
|
@ -98,7 +99,8 @@ public:
|
|||
inline simdjson_result<element> at(size_t index) const noexcept;
|
||||
|
||||
private:
|
||||
really_inline array(const document *doc, size_t json_index) noexcept;
|
||||
really_inline array(const internal::tape_ref &tape) noexcept;
|
||||
internal::tape_ref tape;
|
||||
friend class element;
|
||||
friend struct simdjson_result<element>;
|
||||
template<typename T>
|
||||
|
|
|
@ -35,7 +35,7 @@ enum class element_type {
|
|||
* References an element in a JSON document, representing a JSON null, boolean, string, number,
|
||||
* array or object.
|
||||
*/
|
||||
class element : protected internal::tape_ref {
|
||||
class element {
|
||||
public:
|
||||
/** Create a new, invalid element. */
|
||||
really_inline element() noexcept;
|
||||
|
@ -43,8 +43,135 @@ public:
|
|||
/** The type of this element. */
|
||||
really_inline element_type type() const noexcept;
|
||||
|
||||
/** Whether this element is a json `null`. */
|
||||
really_inline bool is_null() const noexcept;
|
||||
/**
|
||||
* Cast this element to an array.
|
||||
*
|
||||
* Equivalent to get<array>().
|
||||
*
|
||||
* @returns An object that can be used to iterate the array, or:
|
||||
* INCORRECT_TYPE if the JSON element is not an array.
|
||||
*/
|
||||
inline simdjson_result<array> get_array() const noexcept;
|
||||
/**
|
||||
* Cast this element to an object.
|
||||
*
|
||||
* Equivalent to get<object>().
|
||||
*
|
||||
* @returns An object that can be used to look up or iterate the object's fields, or:
|
||||
* INCORRECT_TYPE if the JSON element is not an object.
|
||||
*/
|
||||
inline simdjson_result<object> get_object() const noexcept;
|
||||
/**
|
||||
* Cast this element to a string.
|
||||
*
|
||||
* Equivalent to get<const char *>().
|
||||
*
|
||||
* @returns An pointer to a null-terminated string. This string is stored in the parser and will
|
||||
* be invalidated the next time it parses a document or when it is destroyed.
|
||||
* Returns INCORRECT_TYPE if the JSON element is not a string.
|
||||
*/
|
||||
inline simdjson_result<const char *> get_c_str() const noexcept;
|
||||
/**
|
||||
* Cast this element to a string.
|
||||
*
|
||||
* Equivalent to get<std::string_view>().
|
||||
*
|
||||
* @returns A string. The string is stored in the parser and will be invalidated the next time it
|
||||
* parses a document or when it is destroyed.
|
||||
* Returns INCORRECT_TYPE if the JSON element is not a string.
|
||||
*/
|
||||
inline simdjson_result<std::string_view> get_string() const noexcept;
|
||||
/**
|
||||
* Cast this element to a signed integer.
|
||||
*
|
||||
* Equivalent to get<int64_t>().
|
||||
*
|
||||
* @returns A signed 64-bit integer.
|
||||
* Returns INCORRECT_TYPE if the JSON element is not an integer, or NUMBER_OUT_OF_RANGE
|
||||
* if it is negative.
|
||||
*/
|
||||
inline simdjson_result<int64_t> get_int64_t() const noexcept;
|
||||
/**
|
||||
* Cast this element to an unsigned integer.
|
||||
*
|
||||
* Equivalent to get<uint64_t>().
|
||||
*
|
||||
* @returns An unsigned 64-bit integer.
|
||||
* Returns INCORRECT_TYPE if the JSON element is not an integer, or NUMBER_OUT_OF_RANGE
|
||||
* if it is too large.
|
||||
*/
|
||||
inline simdjson_result<uint64_t> get_uint64_t() const noexcept;
|
||||
/**
|
||||
* Cast this element to an double floating-point.
|
||||
*
|
||||
* Equivalent to get<double>().
|
||||
*
|
||||
* @returns A double value.
|
||||
* Returns INCORRECT_TYPE if the JSON element is not a number.
|
||||
*/
|
||||
inline simdjson_result<double> get_double() const noexcept;
|
||||
/**
|
||||
* Cast this element to a bool.
|
||||
*
|
||||
* Equivalent to get<bool>().
|
||||
*
|
||||
* @returns A bool value.
|
||||
* Returns INCORRECT_TYPE if the JSON element is not a boolean.
|
||||
*/
|
||||
inline simdjson_result<bool> get_bool() const noexcept;
|
||||
|
||||
/**
|
||||
* Whether this element is a json array.
|
||||
*
|
||||
* Equivalent to is<array>().
|
||||
*/
|
||||
inline bool is_array() const noexcept;
|
||||
/**
|
||||
* Whether this element is a json object.
|
||||
*
|
||||
* Equivalent to is<object>().
|
||||
*/
|
||||
inline bool is_object() const noexcept;
|
||||
/**
|
||||
* Whether this element is a json string.
|
||||
*
|
||||
* Equivalent to is<std::string_view>() or is<const char *>().
|
||||
*/
|
||||
inline bool is_string() const noexcept;
|
||||
/**
|
||||
* Whether this element is a json number that fits in a signed 64-bit integer.
|
||||
*
|
||||
* Equivalent to is<int64_t>().
|
||||
*/
|
||||
inline bool is_int64_t() const noexcept;
|
||||
/**
|
||||
* Whether this element is a json number that fits in an unsigned 64-bit integer.
|
||||
*
|
||||
* Equivalent to is<uint64_t>().
|
||||
*/
|
||||
inline bool is_uint64_t() const noexcept;
|
||||
/**
|
||||
* Whether this element is a json number that fits in a double.
|
||||
*
|
||||
* Equivalent to is<double>().
|
||||
*/
|
||||
inline bool is_double() const noexcept;
|
||||
/**
|
||||
* Whether this element is a json number.
|
||||
*
|
||||
* Both integers and floating points will return true.
|
||||
*/
|
||||
inline bool is_number() const noexcept;
|
||||
/**
|
||||
* Whether this element is a json `true` or `false`.
|
||||
*
|
||||
* Equivalent to is<bool>().
|
||||
*/
|
||||
inline bool is_bool() const noexcept;
|
||||
/**
|
||||
* Whether this element is a json `null`.
|
||||
*/
|
||||
inline bool is_null() const noexcept;
|
||||
|
||||
/**
|
||||
* Tell whether the value can be cast to provided type (T).
|
||||
|
@ -249,7 +376,8 @@ public:
|
|||
inline bool dump_raw_tape(std::ostream &out) const noexcept;
|
||||
|
||||
private:
|
||||
really_inline element(const document *doc, size_t json_index) noexcept;
|
||||
really_inline element(const internal::tape_ref &tape) noexcept;
|
||||
internal::tape_ref tape;
|
||||
friend class document;
|
||||
friend class object;
|
||||
friend class array;
|
||||
|
@ -289,12 +417,29 @@ public:
|
|||
really_inline simdjson_result(error_code error) noexcept; ///< @private
|
||||
|
||||
inline simdjson_result<dom::element_type> type() const noexcept;
|
||||
inline simdjson_result<bool> is_null() const noexcept;
|
||||
template<typename T>
|
||||
inline simdjson_result<bool> is() const noexcept;
|
||||
template<typename T>
|
||||
inline simdjson_result<T> get() const noexcept;
|
||||
|
||||
inline simdjson_result<dom::array> get_array() const noexcept;
|
||||
inline simdjson_result<dom::object> get_object() const noexcept;
|
||||
inline simdjson_result<const char *> get_c_str() const noexcept;
|
||||
inline simdjson_result<std::string_view> get_string() const noexcept;
|
||||
inline simdjson_result<int64_t> get_int64_t() const noexcept;
|
||||
inline simdjson_result<uint64_t> get_uint64_t() const noexcept;
|
||||
inline simdjson_result<double> get_double() const noexcept;
|
||||
inline simdjson_result<bool> get_bool() const noexcept;
|
||||
|
||||
inline simdjson_result<bool> is_array() const noexcept;
|
||||
inline simdjson_result<bool> is_object() const noexcept;
|
||||
inline simdjson_result<bool> is_string() const noexcept;
|
||||
inline simdjson_result<bool> is_int64_t() const noexcept;
|
||||
inline simdjson_result<bool> is_uint64_t() const noexcept;
|
||||
inline simdjson_result<bool> is_double() const noexcept;
|
||||
inline simdjson_result<bool> is_bool() const noexcept;
|
||||
inline simdjson_result<bool> is_null() const noexcept;
|
||||
|
||||
inline simdjson_result<dom::element> operator[](const std::string_view &key) const noexcept;
|
||||
inline simdjson_result<dom::element> operator[](const char *key) const noexcept;
|
||||
inline simdjson_result<dom::element> at(const std::string_view &json_pointer) const noexcept;
|
||||
|
|
|
@ -17,12 +17,12 @@ class key_value_pair;
|
|||
/**
|
||||
* JSON object.
|
||||
*/
|
||||
class object : protected internal::tape_ref {
|
||||
class object {
|
||||
public:
|
||||
/** Create a new, invalid object */
|
||||
really_inline object() noexcept;
|
||||
|
||||
class iterator : protected internal::tape_ref {
|
||||
class iterator {
|
||||
public:
|
||||
/**
|
||||
* Get the actual key/value pair
|
||||
|
@ -70,7 +70,10 @@ public:
|
|||
*/
|
||||
inline element value() const noexcept;
|
||||
private:
|
||||
really_inline iterator(const document *doc, size_t json_index) noexcept;
|
||||
really_inline iterator(const internal::tape_ref &tape) noexcept;
|
||||
|
||||
internal::tape_ref tape;
|
||||
|
||||
friend class object;
|
||||
};
|
||||
|
||||
|
@ -172,7 +175,10 @@ public:
|
|||
inline simdjson_result<element> at_key_case_insensitive(const std::string_view &key) const noexcept;
|
||||
|
||||
private:
|
||||
really_inline object(const document *doc, size_t json_index) noexcept;
|
||||
really_inline object(const internal::tape_ref &tape) noexcept;
|
||||
|
||||
internal::tape_ref tape;
|
||||
|
||||
friend class element;
|
||||
friend struct simdjson_result<element>;
|
||||
template<typename T>
|
||||
|
|
|
@ -50,16 +50,16 @@ namespace dom {
|
|||
//
|
||||
// array inline implementation
|
||||
//
|
||||
really_inline array::array() noexcept : internal::tape_ref() {}
|
||||
really_inline array::array(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) {}
|
||||
really_inline array::array() noexcept : tape{} {}
|
||||
really_inline array::array(const internal::tape_ref &_tape) noexcept : tape{_tape} {}
|
||||
inline array::iterator array::begin() const noexcept {
|
||||
return iterator(doc, json_index + 1);
|
||||
return internal::tape_ref(tape.doc, tape.json_index + 1);
|
||||
}
|
||||
inline array::iterator array::end() const noexcept {
|
||||
return iterator(doc, after_element() - 1);
|
||||
return internal::tape_ref(tape.doc, tape.after_element() - 1);
|
||||
}
|
||||
inline size_t array::size() const noexcept {
|
||||
return scope_count();
|
||||
return tape.scope_count();
|
||||
}
|
||||
inline simdjson_result<element> array::at(const std::string_view &json_pointer) const noexcept {
|
||||
// - means "the append position" or "the element after the end of the array"
|
||||
|
@ -83,7 +83,7 @@ inline simdjson_result<element> array::at(const std::string_view &json_pointer)
|
|||
if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
|
||||
|
||||
// Get the child
|
||||
auto child = array(doc, json_index).at(array_index);
|
||||
auto child = array(tape).at(array_index);
|
||||
// If there is a /, we're not done yet, call recursively.
|
||||
if (i < json_pointer.length()) {
|
||||
child = child.at(json_pointer.substr(i+1));
|
||||
|
@ -102,15 +102,15 @@ inline simdjson_result<element> array::at(size_t index) const noexcept {
|
|||
//
|
||||
// array::iterator inline implementation
|
||||
//
|
||||
really_inline array::iterator::iterator(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
|
||||
really_inline array::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
|
||||
inline element array::iterator::operator*() const noexcept {
|
||||
return element(doc, json_index);
|
||||
return element(tape);
|
||||
}
|
||||
inline bool array::iterator::operator!=(const array::iterator& other) const noexcept {
|
||||
return json_index != other.json_index;
|
||||
return tape.json_index != other.tape.json_index;
|
||||
}
|
||||
inline array::iterator& array::iterator::operator++() noexcept {
|
||||
json_index = after_element();
|
||||
tape.json_index = tape.after_element();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace dom {
|
|||
// document inline implementation
|
||||
//
|
||||
inline element document::root() const noexcept {
|
||||
return element(this, 1);
|
||||
return element(internal::tape_ref(this, 1));
|
||||
}
|
||||
|
||||
WARN_UNUSED
|
||||
|
|
|
@ -22,10 +22,7 @@ inline simdjson_result<dom::element_type> simdjson_result<dom::element>::type()
|
|||
if (error()) { return error(); }
|
||||
return first.type();
|
||||
}
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_null() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_null();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
|
@ -37,6 +34,73 @@ inline simdjson_result<T> simdjson_result<dom::element>::get() const noexcept {
|
|||
return first.get<T>();
|
||||
}
|
||||
|
||||
inline simdjson_result<dom::array> simdjson_result<dom::element>::get_array() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_array();
|
||||
}
|
||||
inline simdjson_result<dom::object> simdjson_result<dom::element>::get_object() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_object();
|
||||
}
|
||||
inline simdjson_result<const char *> simdjson_result<dom::element>::get_c_str() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_c_str();
|
||||
}
|
||||
inline simdjson_result<std::string_view> simdjson_result<dom::element>::get_string() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_string();
|
||||
}
|
||||
inline simdjson_result<int64_t> simdjson_result<dom::element>::get_int64_t() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_int64_t();
|
||||
}
|
||||
inline simdjson_result<uint64_t> simdjson_result<dom::element>::get_uint64_t() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_uint64_t();
|
||||
}
|
||||
inline simdjson_result<double> simdjson_result<dom::element>::get_double() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_double();
|
||||
}
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::get_bool() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_bool();
|
||||
}
|
||||
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_array() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_array();
|
||||
}
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_object() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_object();
|
||||
}
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_string() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_string();
|
||||
}
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_int64_t() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_int64_t();
|
||||
}
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_uint64_t() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_uint64_t();
|
||||
}
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_double() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_double();
|
||||
}
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_bool() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_bool();
|
||||
}
|
||||
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_null() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_null();
|
||||
}
|
||||
|
||||
inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](const std::string_view &key) const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first[key];
|
||||
|
@ -105,50 +169,43 @@ namespace dom {
|
|||
//
|
||||
// element inline implementation
|
||||
//
|
||||
really_inline element::element() noexcept : internal::tape_ref() {}
|
||||
really_inline element::element(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
|
||||
really_inline element::element() noexcept : tape{} {}
|
||||
really_inline element::element(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
|
||||
|
||||
inline element_type element::type() const noexcept {
|
||||
auto tape_type = tape_ref_type();
|
||||
auto tape_type = tape.tape_ref_type();
|
||||
return tape_type == internal::tape_type::FALSE_VALUE ? element_type::BOOL : static_cast<element_type>(tape_type);
|
||||
}
|
||||
really_inline bool element::is_null() const noexcept {
|
||||
return is_null_on_tape();
|
||||
}
|
||||
|
||||
template<>
|
||||
inline simdjson_result<bool> element::get<bool>() const noexcept {
|
||||
if(is_true()) {
|
||||
inline simdjson_result<bool> element::get_bool() const noexcept {
|
||||
if(tape.is_true()) {
|
||||
return true;
|
||||
} else if(is_false()) {
|
||||
} else if(tape.is_false()) {
|
||||
return false;
|
||||
}
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<const char *> element::get<const char *>() const noexcept {
|
||||
switch (tape_ref_type()) {
|
||||
inline simdjson_result<const char *> element::get_c_str() const noexcept {
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING: {
|
||||
return get_c_str();
|
||||
return tape.get_c_str();
|
||||
}
|
||||
default:
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<std::string_view> element::get<std::string_view>() const noexcept {
|
||||
switch (tape_ref_type()) {
|
||||
inline simdjson_result<std::string_view> element::get_string() const noexcept {
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING:
|
||||
return get_string_view();
|
||||
return tape.get_string_view();
|
||||
default:
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept {
|
||||
if(unlikely(!is_uint64())) { // branch rarely taken
|
||||
if(is_int64()) {
|
||||
int64_t result = next_tape_value<int64_t>();
|
||||
inline simdjson_result<uint64_t> element::get_uint64_t() const noexcept {
|
||||
if(unlikely(!tape.is_uint64())) { // branch rarely taken
|
||||
if(tape.is_int64()) {
|
||||
int64_t result = tape.next_tape_value<int64_t>();
|
||||
if (result < 0) {
|
||||
return NUMBER_OUT_OF_RANGE;
|
||||
}
|
||||
|
@ -156,13 +213,12 @@ inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept {
|
|||
}
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
return next_tape_value<int64_t>();
|
||||
return tape.next_tape_value<int64_t>();
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<int64_t> element::get<int64_t>() const noexcept {
|
||||
if(unlikely(!is_int64())) { // branch rarely taken
|
||||
if(is_uint64()) {
|
||||
uint64_t result = next_tape_value<uint64_t>();
|
||||
inline simdjson_result<int64_t> element::get_int64_t() const noexcept {
|
||||
if(unlikely(!tape.is_int64())) { // branch rarely taken
|
||||
if(tape.is_uint64()) {
|
||||
uint64_t result = tape.next_tape_value<uint64_t>();
|
||||
// Wrapping max in parens to handle Windows issue: https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std
|
||||
if (result > uint64_t((std::numeric_limits<int64_t>::max)())) {
|
||||
return NUMBER_OUT_OF_RANGE;
|
||||
|
@ -171,10 +227,9 @@ inline simdjson_result<int64_t> element::get<int64_t>() const noexcept {
|
|||
}
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
return next_tape_value<int64_t>();
|
||||
return tape.next_tape_value<int64_t>();
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<double> element::get<double>() const noexcept {
|
||||
inline simdjson_result<double> element::get_double() const noexcept {
|
||||
// Performance considerations:
|
||||
// 1. Querying tape_ref_type() implies doing a shift, it is fast to just do a straight
|
||||
// comparison.
|
||||
|
@ -184,42 +239,61 @@ inline simdjson_result<double> element::get<double>() const noexcept {
|
|||
// We can expect get<double> to refer to a double type almost all the time.
|
||||
// It is important to craft the code accordingly so that the compiler can use this
|
||||
// information. (This could also be solved with profile-guided optimization.)
|
||||
if(unlikely(!is_double())) { // branch rarely taken
|
||||
if(is_uint64()) {
|
||||
return double(next_tape_value<uint64_t>());
|
||||
} else if(is_int64()) {
|
||||
return double(next_tape_value<int64_t>());
|
||||
if(unlikely(!tape.is_double())) { // branch rarely taken
|
||||
if(tape.is_uint64()) {
|
||||
return double(tape.next_tape_value<uint64_t>());
|
||||
} else if(tape.is_int64()) {
|
||||
return double(tape.next_tape_value<int64_t>());
|
||||
}
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
// this is common:
|
||||
return next_tape_value<double>();
|
||||
return tape.next_tape_value<double>();
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<array> element::get<array>() const noexcept {
|
||||
switch (tape_ref_type()) {
|
||||
inline simdjson_result<array> element::get_array() const noexcept {
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_ARRAY:
|
||||
return array(doc, json_index);
|
||||
return array(tape);
|
||||
default:
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<object> element::get<object>() const noexcept {
|
||||
switch (tape_ref_type()) {
|
||||
inline simdjson_result<object> element::get_object() const noexcept {
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(doc, json_index);
|
||||
return object(tape);
|
||||
default:
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
really_inline bool element::is() const noexcept {
|
||||
inline bool element::is() const noexcept {
|
||||
auto result = get<T>();
|
||||
return !result.error();
|
||||
}
|
||||
|
||||
template<> inline simdjson_result<array> element::get<array>() const noexcept { return get_array(); }
|
||||
template<> inline simdjson_result<object> element::get<object>() const noexcept { return get_object(); }
|
||||
template<> inline simdjson_result<const char *> element::get<const char *>() const noexcept { return get_c_str(); }
|
||||
template<> inline simdjson_result<std::string_view> element::get<std::string_view>() const noexcept { return get_string(); }
|
||||
template<> inline simdjson_result<int64_t> element::get<int64_t>() const noexcept { return get_int64_t(); }
|
||||
template<> inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept { return get_uint64_t(); }
|
||||
template<> inline simdjson_result<double> element::get<double>() const noexcept { return get_double(); }
|
||||
template<> inline simdjson_result<bool> element::get<bool>() const noexcept { return get_bool(); }
|
||||
|
||||
inline bool element::is_array() const noexcept { return is<array>(); }
|
||||
inline bool element::is_object() const noexcept { return is<object>(); }
|
||||
inline bool element::is_string() const noexcept { return is<std::string_view>(); }
|
||||
inline bool element::is_int64_t() const noexcept { return is<int64_t>(); }
|
||||
inline bool element::is_uint64_t() const noexcept { return is<uint64_t>(); }
|
||||
inline bool element::is_double() const noexcept { return is<double>(); }
|
||||
inline bool element::is_bool() const noexcept { return is<bool>(); }
|
||||
|
||||
inline bool element::is_null() const noexcept {
|
||||
return tape.is_null_on_tape();
|
||||
}
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
inline element::operator bool() const noexcept(false) { return get<bool>(); }
|
||||
|
@ -247,11 +321,11 @@ inline simdjson_result<element> element::operator[](const char *key) const noexc
|
|||
return at_key(key);
|
||||
}
|
||||
inline simdjson_result<element> element::at(const std::string_view &json_pointer) const noexcept {
|
||||
switch (tape_ref_type()) {
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(doc, json_index).at(json_pointer);
|
||||
return object(tape).at(json_pointer);
|
||||
case internal::tape_type::START_ARRAY:
|
||||
return array(doc, json_index).at(json_pointer);
|
||||
return array(tape).at(json_pointer);
|
||||
default:
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
|
@ -267,7 +341,7 @@ inline simdjson_result<element> element::at_key_case_insensitive(const std::stri
|
|||
}
|
||||
|
||||
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
|
||||
return doc->dump_raw_tape(out);
|
||||
return tape.doc->dump_raw_tape(out);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const element &value) {
|
||||
|
@ -308,7 +382,7 @@ inline std::ostream& minifier<dom::element>::print(std::ostream& out) {
|
|||
is_object[0] = false;
|
||||
bool after_value = false;
|
||||
|
||||
internal::tape_ref iter(value);
|
||||
internal::tape_ref iter(value.tape);
|
||||
do {
|
||||
// print commas after each value
|
||||
if (after_value) {
|
||||
|
@ -326,7 +400,7 @@ inline std::ostream& minifier<dom::element>::print(std::ostream& out) {
|
|||
// If we're too deep, we need to recurse to go deeper.
|
||||
depth++;
|
||||
if (unlikely(depth >= MAX_DEPTH)) {
|
||||
out << minify<dom::array>(dom::array(iter.doc, iter.json_index));
|
||||
out << minify<dom::array>(dom::array(iter));
|
||||
iter.json_index = iter.matching_brace_index() - 1; // Jump to the ]
|
||||
depth--;
|
||||
break;
|
||||
|
@ -353,7 +427,7 @@ inline std::ostream& minifier<dom::element>::print(std::ostream& out) {
|
|||
// If we're too deep, we need to recurse to go deeper.
|
||||
depth++;
|
||||
if (unlikely(depth >= MAX_DEPTH)) {
|
||||
out << minify<dom::object>(dom::object(iter.doc, iter.json_index));
|
||||
out << minify<dom::object>(dom::object(iter));
|
||||
iter.json_index = iter.matching_brace_index() - 1; // Jump to the }
|
||||
depth--;
|
||||
break;
|
||||
|
|
|
@ -62,16 +62,16 @@ namespace dom {
|
|||
//
|
||||
// object inline implementation
|
||||
//
|
||||
really_inline object::object() noexcept : internal::tape_ref() {}
|
||||
really_inline object::object(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
|
||||
really_inline object::object() noexcept : tape{} {}
|
||||
really_inline object::object(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
|
||||
inline object::iterator object::begin() const noexcept {
|
||||
return iterator(doc, json_index + 1);
|
||||
return internal::tape_ref(tape.doc, tape.json_index + 1);
|
||||
}
|
||||
inline object::iterator object::end() const noexcept {
|
||||
return iterator(doc, after_element() - 1);
|
||||
return internal::tape_ref(tape.doc, tape.after_element() - 1);
|
||||
}
|
||||
inline size_t object::size() const noexcept {
|
||||
return scope_count();
|
||||
return tape.scope_count();
|
||||
}
|
||||
|
||||
inline simdjson_result<element> object::operator[](const std::string_view &key) const noexcept {
|
||||
|
@ -142,29 +142,29 @@ inline simdjson_result<element> object::at_key_case_insensitive(const std::strin
|
|||
//
|
||||
// object::iterator inline implementation
|
||||
//
|
||||
really_inline object::iterator::iterator(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
|
||||
really_inline object::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
|
||||
inline const key_value_pair object::iterator::operator*() const noexcept {
|
||||
return key_value_pair(key(), value());
|
||||
}
|
||||
inline bool object::iterator::operator!=(const object::iterator& other) const noexcept {
|
||||
return json_index != other.json_index;
|
||||
return tape.json_index != other.tape.json_index;
|
||||
}
|
||||
inline object::iterator& object::iterator::operator++() noexcept {
|
||||
json_index++;
|
||||
json_index = after_element();
|
||||
tape.json_index++;
|
||||
tape.json_index = tape.after_element();
|
||||
return *this;
|
||||
}
|
||||
inline std::string_view object::iterator::key() const noexcept {
|
||||
return get_string_view();
|
||||
return tape.get_string_view();
|
||||
}
|
||||
inline uint32_t object::iterator::key_length() const noexcept {
|
||||
return get_string_length();
|
||||
return tape.get_string_length();
|
||||
}
|
||||
inline const char* object::iterator::key_c_str() const noexcept {
|
||||
return reinterpret_cast<const char *>(&doc->string_buf[size_t(tape_value()) + sizeof(uint32_t)]);
|
||||
return reinterpret_cast<const char *>(&tape.doc->string_buf[size_t(tape.tape_value()) + sizeof(uint32_t)]);
|
||||
}
|
||||
inline element object::iterator::value() const noexcept {
|
||||
return element(doc, json_index + 1);
|
||||
return element(internal::tape_ref(tape.doc, tape.json_index + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,37 +14,8 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "simdjson.h"
|
||||
|
||||
#ifndef SIMDJSON_BENCHMARK_DATA_DIR
|
||||
#define SIMDJSON_BENCHMARK_DATA_DIR "jsonexamples/"
|
||||
#endif
|
||||
const char *TWITTER_JSON = SIMDJSON_BENCHMARK_DATA_DIR "twitter.json";
|
||||
const char *TWITTER_TIMELINE_JSON = SIMDJSON_BENCHMARK_DATA_DIR "twitter_timeline.json";
|
||||
const char *REPEAT_JSON = SIMDJSON_BENCHMARK_DATA_DIR "repeat.json";
|
||||
const char *AMAZON_CELLPHONES_NDJSON = SIMDJSON_BENCHMARK_DATA_DIR "amazon_cellphones.ndjson";
|
||||
|
||||
#define SIMDJSON_BENCHMARK_SMALLDATA_DIR SIMDJSON_BENCHMARK_DATA_DIR "small/"
|
||||
|
||||
const char *ADVERSARIAL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "adversarial.json";
|
||||
const char *FLATADVERSARIAL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "flatadversarial.json";
|
||||
const char *DEMO_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "demo.json";
|
||||
const char *SMALLDEMO_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "smalldemo.json";
|
||||
const char *TRUENULL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "truenull.json";
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool equals_expected(T actual, T expected) {
|
||||
return actual == expected;
|
||||
}
|
||||
template<>
|
||||
bool equals_expected<const char *>(const char *actual, const char *expected) {
|
||||
return !strcmp(actual, expected);
|
||||
}
|
||||
|
||||
#define ASSERT_EQUAL(ACTUAL, EXPECTED) if (!equals_expected(ACTUAL, EXPECTED)) { std::cerr << "Expected " << #ACTUAL << " to be " << (EXPECTED) << ", got " << (ACTUAL) << " instead!" << std::endl; return false; }
|
||||
#define ASSERT(RESULT, MESSAGE) if (!(RESULT)) { std::cerr << MESSAGE << std::endl; return false; }
|
||||
#define ASSERT_SUCCESS(ERROR) if (ERROR) { std::cerr << (ERROR) << std::endl; return false; }
|
||||
#include "cast_tester.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace number_tests {
|
||||
|
||||
|
@ -1367,222 +1338,73 @@ namespace type_tests {
|
|||
}
|
||||
)"_padded;
|
||||
|
||||
// test_implicit_cast<T>::with(value, [](T value) { return true; })
|
||||
// Makes it so we test implicit casts for anything that supports them, but *don't* test them
|
||||
// for const char *
|
||||
template<typename T>
|
||||
class test_implicit_cast {
|
||||
public:
|
||||
template<typename A, typename F>
|
||||
static bool with(A input, F const & test);
|
||||
template<typename A>
|
||||
static bool error_with(A input, simdjson::error_code expected_error);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<typename A, typename F>
|
||||
bool test_implicit_cast<T>::with(A input, F const & test) {
|
||||
T actual;
|
||||
actual = input;
|
||||
return test(actual);
|
||||
}
|
||||
|
||||
template<>
|
||||
template<typename A, typename F>
|
||||
bool test_implicit_cast<const char *>::with(A, F const &) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename A>
|
||||
bool test_implicit_cast<T>::error_with(A input, simdjson::error_code expected_error) {
|
||||
try {
|
||||
UNUSED T actual;
|
||||
actual = input;
|
||||
return false;
|
||||
} catch(simdjson_error &e) {
|
||||
ASSERT_EQUAL(e.error(), expected_error);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
template<typename A>
|
||||
bool test_implicit_cast<const char *>::error_with(A, simdjson::error_code) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool test_cast(simdjson_result<dom::element> result, T expected) {
|
||||
cast_tester<T> tester;
|
||||
std::cout << " test_cast<" << typeid(T).name() << "> expecting " << expected << std::endl;
|
||||
// Grab the element out and check success
|
||||
dom::element element = result.first;
|
||||
|
||||
// get<T>() == expected
|
||||
T actual;
|
||||
simdjson::error_code error;
|
||||
result.get<T>().tie(actual, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(actual, expected);
|
||||
|
||||
element.get<T>().tie(actual, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(actual, expected);
|
||||
|
||||
// is<T>()
|
||||
bool actual_is;
|
||||
result.is<T>().tie(actual_is, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(actual_is, true);
|
||||
|
||||
actual_is = element.is<T>();
|
||||
ASSERT_EQUAL(actual_is, true);
|
||||
|
||||
RUN_TEST( tester.test_get(element, expected ) );
|
||||
RUN_TEST( tester.test_get(result, expected) );
|
||||
// RUN_TEST( tester.test_named_get(element, expected) );
|
||||
// RUN_TEST( tester.test_named_get(result, expected) );
|
||||
RUN_TEST( tester.test_is(element, true) );
|
||||
RUN_TEST( tester.test_is(result, true) );
|
||||
// RUN_TEST( tester.test_named_is(element, true) );
|
||||
// RUN_TEST( tester.test_named_is(result, true) );
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
try {
|
||||
|
||||
// T() == expected
|
||||
actual = T(result);
|
||||
ASSERT_EQUAL(actual, expected);
|
||||
actual = T(element);
|
||||
ASSERT_EQUAL(actual, expected);
|
||||
|
||||
test_implicit_cast<T>::with(result, [&](T a) { ASSERT_EQUAL(a, expected); return false; });
|
||||
|
||||
test_implicit_cast<T>::with(element, [&](T a) { ASSERT_EQUAL(a, expected); return false; });
|
||||
|
||||
// get<T>() == expected
|
||||
actual = result.get<T>();
|
||||
ASSERT_EQUAL(actual, expected);
|
||||
|
||||
actual = element.get<T>();
|
||||
ASSERT_EQUAL(actual, expected);
|
||||
|
||||
// is<T>()
|
||||
actual_is = result.is<T>();
|
||||
ASSERT_EQUAL(actual_is, true);
|
||||
|
||||
} catch(simdjson_error &e) {
|
||||
std::cerr << e.error() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
RUN_TEST( tester.test_implicit_cast(element, expected) );
|
||||
RUN_TEST( tester.test_implicit_cast(result, expected) );
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool test_cast(simdjson_result<dom::element> result) {
|
||||
std::cout << " test_cast<" << typeid(T).name() << "> expecting success" << std::endl;
|
||||
cast_tester<T> tester;
|
||||
std::cout << " test_cast<" << typeid(T).name() << ">" << std::endl;
|
||||
// Grab the element out and check success
|
||||
dom::element element = result.first;
|
||||
|
||||
// get<T>() == expected
|
||||
T actual;
|
||||
simdjson::error_code error;
|
||||
result.get<T>().tie(actual, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
|
||||
element.get<T>().tie(actual, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
|
||||
// is<T>()
|
||||
bool actual_is;
|
||||
result.is<T>().tie(actual_is, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(actual_is, true);
|
||||
|
||||
actual_is = element.is<T>();
|
||||
ASSERT_EQUAL(actual_is, true);
|
||||
|
||||
RUN_TEST( tester.test_get(element) );
|
||||
RUN_TEST( tester.test_get(result) );
|
||||
RUN_TEST( tester.test_named_get(element) );
|
||||
RUN_TEST( tester.test_named_get(result) );
|
||||
RUN_TEST( tester.test_is(element, true) );
|
||||
RUN_TEST( tester.test_is(result, true) );
|
||||
RUN_TEST( tester.test_named_is(element, true) );
|
||||
RUN_TEST( tester.test_named_is(result, true) );
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
try {
|
||||
|
||||
// T()
|
||||
actual = T(result);
|
||||
|
||||
actual = T(element);
|
||||
|
||||
test_implicit_cast<T>::with(result, [&](T) { return true; });
|
||||
|
||||
test_implicit_cast<T>::with(element, [&](T) { return true; });
|
||||
|
||||
// get<T>() == expected
|
||||
actual = result.get<T>();
|
||||
|
||||
actual = element.get<T>();
|
||||
|
||||
// is<T>()
|
||||
actual_is = result.is<T>();
|
||||
ASSERT_EQUAL(actual_is, true);
|
||||
|
||||
} catch(simdjson_error &e) {
|
||||
std::cerr << e.error() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
RUN_TEST( tester.test_implicit_cast(element) );
|
||||
RUN_TEST( tester.test_implicit_cast(result) );
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Test that we get errors when we cast to the wrong type
|
||||
//
|
||||
template<typename T>
|
||||
bool test_cast(simdjson_result<dom::element> result, simdjson::error_code expected_error) {
|
||||
std::cout << " test_cast<" << typeid(T).name() << "> expecting error '" << expected_error << "'" << std::endl;
|
||||
bool test_cast_error(simdjson_result<dom::element> result, simdjson::error_code expected_error) {
|
||||
std::cout << " test_cast_error<" << typeid(T).name() << "> expecting error '" << expected_error << "'" << std::endl;
|
||||
dom::element element = result.first;
|
||||
// get<T>() == expected
|
||||
T actual;
|
||||
simdjson::error_code error;
|
||||
result.get<T>().tie(actual, error);
|
||||
ASSERT_EQUAL(error, expected_error);
|
||||
|
||||
element.get<T>().tie(actual, error);
|
||||
ASSERT_EQUAL(error, expected_error);
|
||||
|
||||
// is<T>()
|
||||
bool actual_is;
|
||||
result.is<T>().tie(actual_is, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(actual_is, false);
|
||||
|
||||
actual_is = element.is<T>();
|
||||
ASSERT_EQUAL(actual_is, false);
|
||||
cast_tester<T> tester;
|
||||
|
||||
RUN_TEST( tester.test_get_error(element, expected_error) );
|
||||
RUN_TEST( tester.test_get_error(result, expected_error) );
|
||||
RUN_TEST( tester.test_named_get_error(element, expected_error) );
|
||||
RUN_TEST( tester.test_named_get_error(result, expected_error) );
|
||||
RUN_TEST( tester.test_is(element, false) );
|
||||
RUN_TEST( tester.test_is(result, false) );
|
||||
RUN_TEST( tester.test_named_is(element, false) );
|
||||
RUN_TEST( tester.test_named_is(result, false) );
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
// T()
|
||||
try {
|
||||
actual = T(result);
|
||||
return false;
|
||||
} catch(simdjson_error &e) {
|
||||
ASSERT_EQUAL(e.error(), expected_error);
|
||||
}
|
||||
|
||||
try {
|
||||
actual = T(element);
|
||||
return false;
|
||||
} catch(simdjson_error &e) {
|
||||
ASSERT_EQUAL(e.error(), expected_error);
|
||||
}
|
||||
|
||||
if (!test_implicit_cast<T>::error_with(result, expected_error)) { return false; }
|
||||
|
||||
if (!test_implicit_cast<T>::error_with(result, expected_error)) { return true; }
|
||||
|
||||
try {
|
||||
|
||||
// is<T>()
|
||||
actual_is = result.is<T>();
|
||||
ASSERT_EQUAL(actual_is, false);
|
||||
|
||||
} catch(simdjson_error &e) {
|
||||
std::cerr << e.error() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
RUN_TEST( tester.test_implicit_cast_error(element, expected_error) );
|
||||
RUN_TEST( tester.test_implicit_cast_error(result, expected_error) );
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -1657,13 +1479,13 @@ namespace type_tests {
|
|||
return true
|
||||
&& test_type(result, dom::element_type::ARRAY)
|
||||
&& test_cast<dom::array>(result)
|
||||
&& test_cast<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<double>(result, INCORRECT_TYPE)
|
||||
&& test_cast<bool>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<double>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<bool>(result, INCORRECT_TYPE)
|
||||
&& test_is_null(result, false);
|
||||
}
|
||||
|
||||
|
@ -1675,14 +1497,14 @@ namespace type_tests {
|
|||
|
||||
return true
|
||||
&& test_type(result, dom::element_type::OBJECT)
|
||||
&& test_cast<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast<dom::object>(result)
|
||||
&& test_cast<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<double>(result, INCORRECT_TYPE)
|
||||
&& test_cast<bool>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<double>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<bool>(result, INCORRECT_TYPE)
|
||||
&& test_is_null(result, false);
|
||||
}
|
||||
|
||||
|
@ -1694,14 +1516,14 @@ namespace type_tests {
|
|||
|
||||
return true
|
||||
&& test_type(result, dom::element_type::STRING)
|
||||
&& test_cast<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast<std::string_view>(result, "foo")
|
||||
&& test_cast<const char *>(result, "foo")
|
||||
&& test_cast<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<double>(result, INCORRECT_TYPE)
|
||||
&& test_cast<bool>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<double>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<bool>(result, INCORRECT_TYPE)
|
||||
&& test_is_null(result, false);
|
||||
}
|
||||
|
||||
|
@ -1712,16 +1534,16 @@ namespace type_tests {
|
|||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
return true
|
||||
&& test_type(result, dom::element_type::INT64)
|
||||
&& test_cast<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast<int64_t>(result, expected_value)
|
||||
&& (expected_value >= 0 ?
|
||||
test_cast<uint64_t>(result, expected_value) :
|
||||
test_cast<uint64_t>(result, NUMBER_OUT_OF_RANGE))
|
||||
test_cast_error<uint64_t>(result, NUMBER_OUT_OF_RANGE))
|
||||
&& test_cast<double>(result, static_cast<double>(expected_value))
|
||||
&& test_cast<bool>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<bool>(result, INCORRECT_TYPE)
|
||||
&& test_is_null(result, false);
|
||||
}
|
||||
|
||||
|
@ -1733,14 +1555,14 @@ namespace type_tests {
|
|||
|
||||
return true
|
||||
&& test_type(result, dom::element_type::UINT64)
|
||||
&& test_cast<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast<int64_t>(result, NUMBER_OUT_OF_RANGE)
|
||||
&& test_cast_error<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<int64_t>(result, NUMBER_OUT_OF_RANGE)
|
||||
&& test_cast<uint64_t>(result, expected_value)
|
||||
&& test_cast<double>(result, static_cast<double>(expected_value))
|
||||
&& test_cast<bool>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<bool>(result, INCORRECT_TYPE)
|
||||
&& test_is_null(result, false);
|
||||
}
|
||||
|
||||
|
@ -1751,14 +1573,14 @@ namespace type_tests {
|
|||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
return true
|
||||
&& test_type(result, dom::element_type::DOUBLE)
|
||||
&& test_cast<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<double>(result, expected_value)
|
||||
&& test_cast<bool>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<bool>(result, INCORRECT_TYPE)
|
||||
&& test_is_null(result, false);
|
||||
}
|
||||
|
||||
|
@ -1770,13 +1592,13 @@ namespace type_tests {
|
|||
|
||||
return true
|
||||
&& test_type(result, dom::element_type::BOOL)
|
||||
&& test_cast<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<double>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<double>(result, INCORRECT_TYPE)
|
||||
&& test_cast<bool>(result, expected_value)
|
||||
&& test_is_null(result, false);
|
||||
}
|
||||
|
@ -1788,14 +1610,14 @@ namespace type_tests {
|
|||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)["null"];
|
||||
return true
|
||||
&& test_type(result, dom::element_type::NULL_VALUE)
|
||||
&& test_cast<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast<double>(result, INCORRECT_TYPE)
|
||||
&& test_cast<bool>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::array>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<dom::object>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<std::string_view>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<const char *>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<int64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<uint64_t>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<double>(result, INCORRECT_TYPE)
|
||||
&& test_cast_error<bool>(result, INCORRECT_TYPE)
|
||||
&& test_is_null(result, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,284 @@
|
|||
#ifndef CAST_TESTER_H
|
||||
#define CAST_TESTER_H
|
||||
|
||||
#include "simdjson.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace {
|
||||
using simdjson::error_code;
|
||||
using simdjson::simdjson_error;
|
||||
using simdjson::simdjson_result;
|
||||
using simdjson::dom::array;
|
||||
using simdjson::dom::element;
|
||||
using simdjson::dom::object;
|
||||
}
|
||||
|
||||
// cast_tester<T> tester;
|
||||
// tester.test_implicit(value, [](T value) { return true; })
|
||||
// tester.test_implicit_error(value, error)
|
||||
// Used to test casts to a type. In the case of const char * in particular, we don't test
|
||||
// implicit casts at all, so that method always returns true.
|
||||
template<typename T>
|
||||
class cast_tester {
|
||||
public:
|
||||
bool test_get(element element, T expected = {});
|
||||
bool test_get(simdjson_result<element> element, T expected = {});
|
||||
bool test_get_error(element element, error_code expected_error);
|
||||
bool test_get_error(simdjson_result<element> element, error_code expected_error);
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
bool test_implicit_cast(element element, T expected = {});
|
||||
bool test_implicit_cast(simdjson_result<element> element, T expected = {});
|
||||
bool test_implicit_cast_error(element element, error_code expected_error);
|
||||
bool test_implicit_cast_error(simdjson_result<element> element, error_code expected_error);
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
bool test_is(element element, bool expected);
|
||||
bool test_is(simdjson_result<element> element, bool expected);
|
||||
bool test_is_error(simdjson_result<element> element, error_code expected_error);
|
||||
|
||||
bool test_named_get(element element, T expected = {});
|
||||
bool test_named_get(simdjson_result<element> element, T expected = {});
|
||||
bool test_named_get_error(element element, error_code expected_error);
|
||||
bool test_named_get_error(simdjson_result<element> element, error_code expected_error);
|
||||
|
||||
bool test_named_is(element element, bool expected);
|
||||
bool test_named_is(simdjson_result<element> element, bool expected);
|
||||
bool test_named_is_error(simdjson_result<element> element, error_code expected_error);
|
||||
|
||||
private:
|
||||
simdjson_result<T> named_get(element element);
|
||||
simdjson_result<T> named_get(simdjson_result<element> element);
|
||||
bool named_is(element element);
|
||||
simdjson_result<bool> named_is(simdjson_result<element> element);
|
||||
bool assert_equal(const T& expected, const T& actual);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_get(element element, T expected) {
|
||||
T actual;
|
||||
error_code error;
|
||||
element.get<T>().tie(actual, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
return assert_equal(actual, expected);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_get(simdjson_result<element> element, T expected) {
|
||||
T actual;
|
||||
error_code error;
|
||||
element.get<T>().tie(actual, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
return assert_equal(actual, expected);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_get_error(element element, error_code expected_error) {
|
||||
T actual;
|
||||
error_code error;
|
||||
element.get<T>().tie(actual, error);
|
||||
ASSERT_EQUAL(error, expected_error);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_get_error(simdjson_result<element> element, error_code expected_error) {
|
||||
T actual;
|
||||
error_code error;
|
||||
element.get<T>().tie(actual, error);
|
||||
ASSERT_EQUAL(error, expected_error);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_named_get(element element, T expected) {
|
||||
T actual;
|
||||
error_code error;
|
||||
named_get(element).tie(actual, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
return assert_equal(actual, expected);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_named_get(simdjson_result<element> element, T expected) {
|
||||
T actual;
|
||||
error_code error;
|
||||
named_get(element).tie(actual, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
return assert_equal(actual, expected);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_named_get_error(element element, error_code expected_error) {
|
||||
T actual;
|
||||
error_code error;
|
||||
named_get(element).tie(actual, error);
|
||||
ASSERT_EQUAL(error, expected_error);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_named_get_error(simdjson_result<element> element, error_code expected_error) {
|
||||
T actual;
|
||||
error_code error;
|
||||
named_get(element).tie(actual, error);
|
||||
ASSERT_EQUAL(error, expected_error);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_implicit_cast(element element, T expected) {
|
||||
T actual;
|
||||
try {
|
||||
actual = element;
|
||||
} catch(simdjson_error &e) {
|
||||
std::cerr << e.error() << std::endl;
|
||||
return false;
|
||||
}
|
||||
return assert_equal(actual, expected);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_implicit_cast(simdjson_result<element> element, T expected) {
|
||||
T actual;
|
||||
try {
|
||||
actual = element;
|
||||
} catch(simdjson_error &e) {
|
||||
std::cerr << e.error() << std::endl;
|
||||
return false;
|
||||
}
|
||||
return assert_equal(actual, expected);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_implicit_cast_error(element element, error_code expected_error) {
|
||||
try {
|
||||
UNUSED T actual;
|
||||
actual = element;
|
||||
return false;
|
||||
} catch(simdjson_error &e) {
|
||||
ASSERT_EQUAL(e.error(), expected_error);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_implicit_cast_error(simdjson_result<element> element, error_code expected_error) {
|
||||
try {
|
||||
UNUSED T actual;
|
||||
actual = element;
|
||||
return false;
|
||||
} catch(simdjson_error &e) {
|
||||
ASSERT_EQUAL(e.error(), expected_error);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template<> bool cast_tester<const char *>::test_implicit_cast(element, const char *) { return true; }
|
||||
template<> bool cast_tester<const char *>::test_implicit_cast(simdjson_result<element>, const char *) { return true; }
|
||||
template<> bool cast_tester<const char *>::test_implicit_cast_error(element, error_code) { return true; }
|
||||
template<> bool cast_tester<const char *>::test_implicit_cast_error(simdjson_result<element>, error_code) { return true; }
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_is(element element, bool expected) {
|
||||
ASSERT_EQUAL(element.is<T>(), expected);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_is(simdjson_result<element> element, bool expected) {
|
||||
bool actual;
|
||||
error_code error;
|
||||
element.is<T>().tie(actual, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(actual, expected);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_is_error(simdjson_result<element> element, error_code expected_error) {
|
||||
UNUSED bool actual;
|
||||
error_code error;
|
||||
element.is<T>().tie(actual, error);
|
||||
ASSERT_EQUAL(error, expected_error);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_named_is(element element, bool expected) {
|
||||
ASSERT_EQUAL(named_is(element), expected);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_named_is(simdjson_result<element> element, bool expected) {
|
||||
bool actual;
|
||||
error_code error;
|
||||
named_is(element).tie(actual, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(actual, expected);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool cast_tester<T>::test_named_is_error(simdjson_result<element> element, error_code expected_error) {
|
||||
bool actual;
|
||||
error_code error;
|
||||
named_is(element, error).tie(actual, error);
|
||||
ASSERT_EQUAL(error, expected_error);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<> simdjson_result<array> cast_tester<array>::named_get(element element) { return element.get_array(); }
|
||||
template<> simdjson_result<object> cast_tester<object>::named_get(element element) { return element.get_object(); }
|
||||
template<> simdjson_result<const char *> cast_tester<const char *>::named_get(element element) { return element.get_c_str(); }
|
||||
template<> simdjson_result<std::string_view> cast_tester<std::string_view>::named_get(element element) { return element.get_string(); }
|
||||
template<> simdjson_result<uint64_t> cast_tester<uint64_t>::named_get(element element) { return element.get_uint64_t(); }
|
||||
template<> simdjson_result<int64_t> cast_tester<int64_t>::named_get(element element) { return element.get_int64_t(); }
|
||||
template<> simdjson_result<double> cast_tester<double>::named_get(element element) { return element.get_double(); }
|
||||
template<> simdjson_result<bool> cast_tester<bool>::named_get(element element) { return element.get_bool(); }
|
||||
|
||||
template<> simdjson_result<array> cast_tester<array>::named_get(simdjson_result<element> element) { return element.get_array(); }
|
||||
template<> simdjson_result<object> cast_tester<object>::named_get(simdjson_result<element> element) { return element.get_object(); }
|
||||
template<> simdjson_result<const char *> cast_tester<const char *>::named_get(simdjson_result<element> element) { return element.get_c_str(); }
|
||||
template<> simdjson_result<std::string_view> cast_tester<std::string_view>::named_get(simdjson_result<element> element) { return element.get_string(); }
|
||||
template<> simdjson_result<uint64_t> cast_tester<uint64_t>::named_get(simdjson_result<element> element) { return element.get_uint64_t(); }
|
||||
template<> simdjson_result<int64_t> cast_tester<int64_t>::named_get(simdjson_result<element> element) { return element.get_int64_t(); }
|
||||
template<> simdjson_result<double> cast_tester<double>::named_get(simdjson_result<element> element) { return element.get_double(); }
|
||||
template<> simdjson_result<bool> cast_tester<bool>::named_get(simdjson_result<element> element) { return element.get_bool(); }
|
||||
|
||||
template<> bool cast_tester<array>::named_is(element element) { return element.is_array(); }
|
||||
template<> bool cast_tester<object>::named_is(element element) { return element.is_object(); }
|
||||
template<> bool cast_tester<const char *>::named_is(element element) { return element.is_string(); }
|
||||
template<> bool cast_tester<std::string_view>::named_is(element element) { return element.is_string(); }
|
||||
template<> bool cast_tester<uint64_t>::named_is(element element) { return element.is_uint64_t(); }
|
||||
template<> bool cast_tester<int64_t>::named_is(element element) { return element.is_int64_t(); }
|
||||
template<> bool cast_tester<double>::named_is(element element) { return element.is_double(); }
|
||||
template<> bool cast_tester<bool>::named_is(element element) { return element.is_bool(); }
|
||||
|
||||
template<> simdjson_result<bool> cast_tester<array>::named_is(simdjson_result<element> element) { return element.is_array(); }
|
||||
template<> simdjson_result<bool> cast_tester<object>::named_is(simdjson_result<element> element) { return element.is_object(); }
|
||||
template<> simdjson_result<bool> cast_tester<const char *>::named_is(simdjson_result<element> element) { return element.is_string(); }
|
||||
template<> simdjson_result<bool> cast_tester<std::string_view>::named_is(simdjson_result<element> element) { return element.is_string(); }
|
||||
template<> simdjson_result<bool> cast_tester<uint64_t>::named_is(simdjson_result<element> element) { return element.is_uint64_t(); }
|
||||
template<> simdjson_result<bool> cast_tester<int64_t>::named_is(simdjson_result<element> element) { return element.is_int64_t(); }
|
||||
template<> simdjson_result<bool> cast_tester<double>::named_is(simdjson_result<element> element) { return element.is_double(); }
|
||||
template<> simdjson_result<bool> cast_tester<bool>::named_is(simdjson_result<element> element) { return element.is_bool(); }
|
||||
|
||||
template<typename T> bool cast_tester<T>::assert_equal(const T& expected, const T& actual) {
|
||||
ASSERT_EQUAL(expected, actual);
|
||||
return true;
|
||||
}
|
||||
// We don't actually check equality for objects and arrays, just check that they actually cast
|
||||
template<> bool cast_tester<array>::assert_equal(const array&, const array&) {
|
||||
return true;
|
||||
}
|
||||
template<> bool cast_tester<object>::assert_equal(const object&, const object&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef TEST_MACROS_H
|
||||
#define TEST_MACROS_H
|
||||
|
||||
#ifndef SIMDJSON_BENCHMARK_DATA_DIR
|
||||
#define SIMDJSON_BENCHMARK_DATA_DIR "jsonexamples/"
|
||||
#endif
|
||||
const char *TWITTER_JSON = SIMDJSON_BENCHMARK_DATA_DIR "twitter.json";
|
||||
const char *TWITTER_TIMELINE_JSON = SIMDJSON_BENCHMARK_DATA_DIR "twitter_timeline.json";
|
||||
const char *REPEAT_JSON = SIMDJSON_BENCHMARK_DATA_DIR "repeat.json";
|
||||
const char *AMAZON_CELLPHONES_NDJSON = SIMDJSON_BENCHMARK_DATA_DIR "amazon_cellphones.ndjson";
|
||||
|
||||
#define SIMDJSON_BENCHMARK_SMALLDATA_DIR SIMDJSON_BENCHMARK_DATA_DIR "small/"
|
||||
|
||||
const char *ADVERSARIAL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "adversarial.json";
|
||||
const char *FLATADVERSARIAL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "flatadversarial.json";
|
||||
const char *DEMO_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "demo.json";
|
||||
const char *SMALLDEMO_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "smalldemo.json";
|
||||
const char *TRUENULL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "truenull.json";
|
||||
|
||||
// For the ASSERT_EQUAL macro
|
||||
template<typename T>
|
||||
bool equals_expected(T actual, T expected) {
|
||||
return actual == expected;
|
||||
}
|
||||
template<>
|
||||
bool equals_expected<const char *>(const char *actual, const char *expected) {
|
||||
return !strcmp(actual, expected);
|
||||
}
|
||||
#define ASSERT_EQUAL(ACTUAL, EXPECTED) if (!equals_expected(ACTUAL, EXPECTED)) { std::cerr << "Expected " << #ACTUAL << " to be " << (EXPECTED) << ", got " << (ACTUAL) << " instead!" << std::endl; return false; }
|
||||
#define ASSERT(RESULT, MESSAGE) if (!(RESULT)) { std::cerr << MESSAGE << std::endl; return false; }
|
||||
#define RUN_TEST(RESULT) if (!RESULT) { return false; }
|
||||
#define ASSERT_SUCCESS(ERROR) if (ERROR) { std::cerr << (ERROR) << std::endl; return false; }
|
||||
|
||||
#endif // TEST_MACROS_H
|
Loading…
Reference in New Issue