Merge 2614b81092 into 58d6aa5831
This commit is contained in:
commit
20261d52f1
@ -132,6 +132,7 @@ class input_stream_adapter
|
|||||||
};
|
};
|
||||||
#endif // JSON_NO_IO
|
#endif // JSON_NO_IO
|
||||||
|
|
||||||
|
|
||||||
// General-purpose iterator-based adapter. It might not be as fast as
|
// General-purpose iterator-based adapter. It might not be as fast as
|
||||||
// theoretically possible for some containers, but it is extremely versatile.
|
// theoretically possible for some containers, but it is extremely versatile.
|
||||||
template<typename IteratorType>
|
template<typename IteratorType>
|
||||||
@ -141,30 +142,46 @@ class iterator_input_adapter
|
|||||||
using char_type = typename std::iterator_traits<IteratorType>::value_type;
|
using char_type = typename std::iterator_traits<IteratorType>::value_type;
|
||||||
|
|
||||||
iterator_input_adapter(IteratorType first, IteratorType last)
|
iterator_input_adapter(IteratorType first, IteratorType last)
|
||||||
: current(std::move(first)), end(std::move(last))
|
: current(std::move(first)), end(std::move(last)), current_has_been_consumed(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
typename std::char_traits<char_type>::int_type get_character()
|
typename std::char_traits<char_type>::int_type get_character()
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_LIKELY(current != end))
|
|
||||||
|
if (JSON_HEDLEY_LIKELY(current_has_been_consumed))
|
||||||
{
|
{
|
||||||
auto result = std::char_traits<char_type>::to_int_type(*current);
|
|
||||||
std::advance(current, 1);
|
std::advance(current, 1);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::char_traits<char_type>::eof();
|
if (JSON_HEDLEY_LIKELY(current != end))
|
||||||
|
{
|
||||||
|
current_has_been_consumed = true;
|
||||||
|
return std::char_traits<char_type>::to_int_type(*current);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_has_been_consumed = false;
|
||||||
|
return std::char_traits<char_type>::eof();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IteratorType current;
|
mutable IteratorType current;
|
||||||
IteratorType end;
|
const IteratorType end;
|
||||||
|
mutable bool current_has_been_consumed;
|
||||||
|
|
||||||
template<typename BaseInputAdapter, size_t T>
|
template<typename BaseInputAdapter, size_t T>
|
||||||
friend struct wide_string_input_helper;
|
friend struct wide_string_input_helper;
|
||||||
|
|
||||||
bool empty() const
|
bool empty() const
|
||||||
{
|
{
|
||||||
|
if (JSON_HEDLEY_LIKELY(current_has_been_consumed))
|
||||||
|
{
|
||||||
|
std::advance(current, 1);
|
||||||
|
current_has_been_consumed = false;
|
||||||
|
}
|
||||||
|
|
||||||
return current == end;
|
return current == end;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -6208,6 +6208,7 @@ class input_stream_adapter
|
|||||||
};
|
};
|
||||||
#endif // JSON_NO_IO
|
#endif // JSON_NO_IO
|
||||||
|
|
||||||
|
|
||||||
// General-purpose iterator-based adapter. It might not be as fast as
|
// General-purpose iterator-based adapter. It might not be as fast as
|
||||||
// theoretically possible for some containers, but it is extremely versatile.
|
// theoretically possible for some containers, but it is extremely versatile.
|
||||||
template<typename IteratorType>
|
template<typename IteratorType>
|
||||||
@ -6217,30 +6218,46 @@ class iterator_input_adapter
|
|||||||
using char_type = typename std::iterator_traits<IteratorType>::value_type;
|
using char_type = typename std::iterator_traits<IteratorType>::value_type;
|
||||||
|
|
||||||
iterator_input_adapter(IteratorType first, IteratorType last)
|
iterator_input_adapter(IteratorType first, IteratorType last)
|
||||||
: current(std::move(first)), end(std::move(last))
|
: current(std::move(first)), end(std::move(last)), current_has_been_consumed(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
typename std::char_traits<char_type>::int_type get_character()
|
typename std::char_traits<char_type>::int_type get_character()
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_LIKELY(current != end))
|
|
||||||
|
if (JSON_HEDLEY_LIKELY(current_has_been_consumed))
|
||||||
{
|
{
|
||||||
auto result = std::char_traits<char_type>::to_int_type(*current);
|
|
||||||
std::advance(current, 1);
|
std::advance(current, 1);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::char_traits<char_type>::eof();
|
if (JSON_HEDLEY_LIKELY(current != end))
|
||||||
|
{
|
||||||
|
current_has_been_consumed = true;
|
||||||
|
return std::char_traits<char_type>::to_int_type(*current);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_has_been_consumed = false;
|
||||||
|
return std::char_traits<char_type>::eof();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IteratorType current;
|
mutable IteratorType current;
|
||||||
IteratorType end;
|
const IteratorType end;
|
||||||
|
mutable bool current_has_been_consumed;
|
||||||
|
|
||||||
template<typename BaseInputAdapter, size_t T>
|
template<typename BaseInputAdapter, size_t T>
|
||||||
friend struct wide_string_input_helper;
|
friend struct wide_string_input_helper;
|
||||||
|
|
||||||
bool empty() const
|
bool empty() const
|
||||||
{
|
{
|
||||||
|
if (JSON_HEDLEY_LIKELY(current_has_been_consumed))
|
||||||
|
{
|
||||||
|
std::advance(current, 1);
|
||||||
|
current_has_been_consumed = false;
|
||||||
|
}
|
||||||
|
|
||||||
return current == end;
|
return current == end;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
126
tests/src/unit-consuming_stream.cpp
Normal file
126
tests/src/unit-consuming_stream.cpp
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "doctest_compatibility.h"
|
||||||
|
|
||||||
|
#define JSON_TESTS_PRIVATE
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
using nlohmann::json;
|
||||||
|
|
||||||
|
|
||||||
|
//This struct emulate an Input Stream, once a "char" is readed from it it is lost
|
||||||
|
struct EmulateStream
|
||||||
|
{
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using value_type = char;
|
||||||
|
using pointer = const char*;
|
||||||
|
using reference = const char&;
|
||||||
|
using iterator_category = std::input_iterator_tag;
|
||||||
|
|
||||||
|
// Like a pop_left() -> consume one char from the underlying buffer
|
||||||
|
static char ConsumeChar(std::string* str)
|
||||||
|
{
|
||||||
|
const char c = str->front();
|
||||||
|
str->erase(0, 1);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulateStream()
|
||||||
|
:
|
||||||
|
target{nullptr}
|
||||||
|
{}
|
||||||
|
|
||||||
|
EmulateStream(std::string* target_)
|
||||||
|
:
|
||||||
|
target{target_},
|
||||||
|
c{ConsumeChar(target_)}
|
||||||
|
{}
|
||||||
|
|
||||||
|
EmulateStream& operator++()
|
||||||
|
{
|
||||||
|
c = ConsumeChar(target);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const EmulateStream& rhs) const
|
||||||
|
{
|
||||||
|
return rhs.target != target;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator*() const
|
||||||
|
{
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string* target;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EmulateStream CreateBegin(std::string& tgt)
|
||||||
|
{
|
||||||
|
return EmulateStream{&tgt};
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulateStream CreateEnd(const std::string& tgt)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("consume only needed")
|
||||||
|
{
|
||||||
|
|
||||||
|
nlohmann::detail::json_sax_acceptor<json> sax_parser;
|
||||||
|
|
||||||
|
const std::string json_A = R"({ "key_A" : "value_A" })";
|
||||||
|
const std::string json_B = R"({ "key_B" : "value_B" })";
|
||||||
|
|
||||||
|
std::string json_concat_AB = json_A + json_B;
|
||||||
|
|
||||||
|
CHECK(
|
||||||
|
json::sax_parse(
|
||||||
|
CreateBegin(json_concat_AB),
|
||||||
|
CreateEnd(json_concat_AB),
|
||||||
|
&sax_parser,
|
||||||
|
nlohmann::detail::input_format_t::json,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
== true
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CHECK(json_concat_AB == json_B);
|
||||||
|
|
||||||
|
|
||||||
|
CHECK(
|
||||||
|
json::sax_parse(
|
||||||
|
CreateBegin(json_concat_AB),
|
||||||
|
CreateEnd(json_concat_AB),
|
||||||
|
&sax_parser,
|
||||||
|
nlohmann::detail::input_format_t::json,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
== true
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
CHECK(json_concat_AB == "");
|
||||||
|
CHECK(json_concat_AB.size() == 0);
|
||||||
|
|
||||||
|
|
||||||
|
CHECK(
|
||||||
|
json::sax_parse(
|
||||||
|
CreateBegin(json_concat_AB),
|
||||||
|
CreateEnd(json_concat_AB),
|
||||||
|
&sax_parser,
|
||||||
|
nlohmann::detail::input_format_t::json,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
== false
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user