🔨 templated output_adapter and used in class serializer
This commit is contained in:
parent
2d2b98a50a
commit
717106eced
2 changed files with 154 additions and 96 deletions
248
src/json.hpp
248
src/json.hpp
|
@ -2897,8 +2897,8 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
string_t dump(const int indent = -1) const
|
string_t dump(const int indent = -1) const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
string_t result;
|
||||||
serializer s(ss);
|
serializer s(output_adapter<char>::create(result));
|
||||||
|
|
||||||
if (indent >= 0)
|
if (indent >= 0)
|
||||||
{
|
{
|
||||||
|
@ -2909,7 +2909,7 @@ class basic_json
|
||||||
s.dump(*this, false, 0);
|
s.dump(*this, false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss.str();
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -6554,6 +6554,104 @@ class basic_json
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/////////////////////
|
||||||
|
// output adapters //
|
||||||
|
/////////////////////
|
||||||
|
|
||||||
|
template<typename CharType>
|
||||||
|
class output_adapter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void write_character(CharType c) = 0;
|
||||||
|
virtual void write_characters(const CharType* s, size_t length) = 0;
|
||||||
|
virtual ~output_adapter() {}
|
||||||
|
|
||||||
|
static std::shared_ptr<output_adapter<CharType>> create(std::vector<CharType>& vec)
|
||||||
|
{
|
||||||
|
return std::shared_ptr<output_adapter>(new output_vector_adapter<CharType>(vec));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::shared_ptr<output_adapter<CharType>> create(std::ostream& s)
|
||||||
|
{
|
||||||
|
return std::shared_ptr<output_adapter>(new output_stream_adapter<CharType>(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::shared_ptr<output_adapter<CharType>> create(std::string& s)
|
||||||
|
{
|
||||||
|
return std::shared_ptr<output_adapter>(new output_string_adapter<CharType>(s));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename CharType>
|
||||||
|
using output_adapter_t = std::shared_ptr<output_adapter<CharType>>;
|
||||||
|
|
||||||
|
template<typename CharType>
|
||||||
|
class output_vector_adapter : public output_adapter<CharType>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
output_vector_adapter(std::vector<CharType>& vec)
|
||||||
|
: v(vec)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void write_character(CharType c) override
|
||||||
|
{
|
||||||
|
v.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_characters(const CharType* s, size_t length) override
|
||||||
|
{
|
||||||
|
std::copy(s, s + length, std::back_inserter(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<CharType>& v;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename CharType>
|
||||||
|
class output_stream_adapter : public output_adapter<CharType>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
output_stream_adapter(std::basic_ostream<CharType>& s)
|
||||||
|
: stream(s)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void write_character(CharType c) override
|
||||||
|
{
|
||||||
|
stream.put(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_characters(const CharType* s, size_t length) override
|
||||||
|
{
|
||||||
|
stream.write(s, static_cast<std::streamsize>(length));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::basic_ostream<CharType>& stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename CharType>
|
||||||
|
class output_string_adapter : public output_adapter<CharType>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
output_string_adapter(std::string& s)
|
||||||
|
: str(s)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void write_character(CharType c) override
|
||||||
|
{
|
||||||
|
str.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_characters(const CharType* s, size_t length) override
|
||||||
|
{
|
||||||
|
str.append(s, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::basic_string<CharType>& str;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
// serialization //
|
// serialization //
|
||||||
|
@ -6576,7 +6674,7 @@ class basic_json
|
||||||
/*!
|
/*!
|
||||||
@param[in] s output stream to serialize to
|
@param[in] s output stream to serialize to
|
||||||
*/
|
*/
|
||||||
serializer(std::ostream& s)
|
serializer(output_adapter_t<char> s)
|
||||||
: o(s), loc(std::localeconv()),
|
: o(s), loc(std::localeconv()),
|
||||||
thousands_sep(!loc->thousands_sep ? '\0' : loc->thousands_sep[0]),
|
thousands_sep(!loc->thousands_sep ? '\0' : loc->thousands_sep[0]),
|
||||||
decimal_point(!loc->decimal_point ? '\0' : loc->decimal_point[0])
|
decimal_point(!loc->decimal_point ? '\0' : loc->decimal_point[0])
|
||||||
|
@ -6610,13 +6708,13 @@ class basic_json
|
||||||
{
|
{
|
||||||
if (val.m_value.object->empty())
|
if (val.m_value.object->empty())
|
||||||
{
|
{
|
||||||
o.write("{}", 2);
|
o->write_characters("{}", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pretty_print)
|
if (pretty_print)
|
||||||
{
|
{
|
||||||
o.write("{\n", 2);
|
o->write_characters("{\n", 2);
|
||||||
|
|
||||||
// variable to hold indentation for recursive calls
|
// variable to hold indentation for recursive calls
|
||||||
const auto new_indent = current_indent + indent_step;
|
const auto new_indent = current_indent + indent_step;
|
||||||
|
@ -6629,49 +6727,49 @@ class basic_json
|
||||||
auto i = val.m_value.object->cbegin();
|
auto i = val.m_value.object->cbegin();
|
||||||
for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
|
for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
|
||||||
{
|
{
|
||||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
o->write_characters(indent_string.c_str(), new_indent);
|
||||||
o.put('\"');
|
o->write_character('\"');
|
||||||
dump_escaped(i->first);
|
dump_escaped(i->first);
|
||||||
o.write("\": ", 3);
|
o->write_characters("\": ", 3);
|
||||||
dump(i->second, true, indent_step, new_indent);
|
dump(i->second, true, indent_step, new_indent);
|
||||||
o.write(",\n", 2);
|
o->write_characters(",\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// last element
|
// last element
|
||||||
assert(i != val.m_value.object->cend());
|
assert(i != val.m_value.object->cend());
|
||||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
o->write_characters(indent_string.c_str(), new_indent);
|
||||||
o.put('\"');
|
o->write_character('\"');
|
||||||
dump_escaped(i->first);
|
dump_escaped(i->first);
|
||||||
o.write("\": ", 3);
|
o->write_characters("\": ", 3);
|
||||||
dump(i->second, true, indent_step, new_indent);
|
dump(i->second, true, indent_step, new_indent);
|
||||||
|
|
||||||
o.put('\n');
|
o->write_character('\n');
|
||||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(current_indent));
|
o->write_characters(indent_string.c_str(), current_indent);
|
||||||
o.put('}');
|
o->write_character('}');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
o.put('{');
|
o->write_character('{');
|
||||||
|
|
||||||
// first n-1 elements
|
// first n-1 elements
|
||||||
auto i = val.m_value.object->cbegin();
|
auto i = val.m_value.object->cbegin();
|
||||||
for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
|
for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
|
||||||
{
|
{
|
||||||
o.put('\"');
|
o->write_character('\"');
|
||||||
dump_escaped(i->first);
|
dump_escaped(i->first);
|
||||||
o.write("\":", 2);
|
o->write_characters("\":", 2);
|
||||||
dump(i->second, false, indent_step, current_indent);
|
dump(i->second, false, indent_step, current_indent);
|
||||||
o.put(',');
|
o->write_character(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
// last element
|
// last element
|
||||||
assert(i != val.m_value.object->cend());
|
assert(i != val.m_value.object->cend());
|
||||||
o.put('\"');
|
o->write_character('\"');
|
||||||
dump_escaped(i->first);
|
dump_escaped(i->first);
|
||||||
o.write("\":", 2);
|
o->write_characters("\":", 2);
|
||||||
dump(i->second, false, indent_step, current_indent);
|
dump(i->second, false, indent_step, current_indent);
|
||||||
|
|
||||||
o.put('}');
|
o->write_character('}');
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -6681,13 +6779,13 @@ class basic_json
|
||||||
{
|
{
|
||||||
if (val.m_value.array->empty())
|
if (val.m_value.array->empty())
|
||||||
{
|
{
|
||||||
o.write("[]", 2);
|
o->write_characters("[]", 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pretty_print)
|
if (pretty_print)
|
||||||
{
|
{
|
||||||
o.write("[\n", 2);
|
o->write_characters("[\n", 2);
|
||||||
|
|
||||||
// variable to hold indentation for recursive calls
|
// variable to hold indentation for recursive calls
|
||||||
const auto new_indent = current_indent + indent_step;
|
const auto new_indent = current_indent + indent_step;
|
||||||
|
@ -6699,36 +6797,36 @@ class basic_json
|
||||||
// first n-1 elements
|
// first n-1 elements
|
||||||
for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i)
|
for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i)
|
||||||
{
|
{
|
||||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
o->write_characters(indent_string.c_str(), new_indent);
|
||||||
dump(*i, true, indent_step, new_indent);
|
dump(*i, true, indent_step, new_indent);
|
||||||
o.write(",\n", 2);
|
o->write_characters(",\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// last element
|
// last element
|
||||||
assert(not val.m_value.array->empty());
|
assert(not val.m_value.array->empty());
|
||||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
o->write_characters(indent_string.c_str(), new_indent);
|
||||||
dump(val.m_value.array->back(), true, indent_step, new_indent);
|
dump(val.m_value.array->back(), true, indent_step, new_indent);
|
||||||
|
|
||||||
o.put('\n');
|
o->write_character('\n');
|
||||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(current_indent));
|
o->write_characters(indent_string.c_str(), current_indent);
|
||||||
o.put(']');
|
o->write_character(']');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
o.put('[');
|
o->write_character('[');
|
||||||
|
|
||||||
// first n-1 elements
|
// first n-1 elements
|
||||||
for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i)
|
for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i)
|
||||||
{
|
{
|
||||||
dump(*i, false, indent_step, current_indent);
|
dump(*i, false, indent_step, current_indent);
|
||||||
o.put(',');
|
o->write_character(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
// last element
|
// last element
|
||||||
assert(not val.m_value.array->empty());
|
assert(not val.m_value.array->empty());
|
||||||
dump(val.m_value.array->back(), false, indent_step, current_indent);
|
dump(val.m_value.array->back(), false, indent_step, current_indent);
|
||||||
|
|
||||||
o.put(']');
|
o->write_character(']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -6736,9 +6834,9 @@ class basic_json
|
||||||
|
|
||||||
case value_t::string:
|
case value_t::string:
|
||||||
{
|
{
|
||||||
o.put('\"');
|
o->write_character('\"');
|
||||||
dump_escaped(*val.m_value.string);
|
dump_escaped(*val.m_value.string);
|
||||||
o.put('\"');
|
o->write_character('\"');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6746,11 +6844,11 @@ class basic_json
|
||||||
{
|
{
|
||||||
if (val.m_value.boolean)
|
if (val.m_value.boolean)
|
||||||
{
|
{
|
||||||
o.write("true", 4);
|
o->write_characters("true", 4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
o.write("false", 5);
|
o->write_characters("false", 5);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -6775,13 +6873,13 @@ class basic_json
|
||||||
|
|
||||||
case value_t::discarded:
|
case value_t::discarded:
|
||||||
{
|
{
|
||||||
o.write("<discarded>", 11);
|
o->write_characters("<discarded>", 11);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::null:
|
case value_t::null:
|
||||||
{
|
{
|
||||||
o.write("null", 4);
|
o->write_characters("null", 4);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6872,7 +6970,7 @@ class basic_json
|
||||||
const auto space = extra_space(s);
|
const auto space = extra_space(s);
|
||||||
if (space == 0)
|
if (space == 0)
|
||||||
{
|
{
|
||||||
o.write(s.c_str(), static_cast<std::streamsize>(s.size()));
|
o->write_characters(s.c_str(), s.size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6998,7 +7096,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(pos == s.size() + space);
|
assert(pos == s.size() + space);
|
||||||
o.write(result.c_str(), static_cast<std::streamsize>(result.size()));
|
o->write_characters(result.c_str(), result.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -7018,7 +7116,7 @@ class basic_json
|
||||||
// special case for "0"
|
// special case for "0"
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
o.put('0');
|
o->write_character('0');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7044,7 +7142,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
std::reverse(number_buffer.begin(), number_buffer.begin() + i);
|
std::reverse(number_buffer.begin(), number_buffer.begin() + i);
|
||||||
o.write(number_buffer.data(), static_cast<std::streamsize>(i));
|
o->write_characters(number_buffer.data(), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -7060,7 +7158,7 @@ class basic_json
|
||||||
// NaN / inf
|
// NaN / inf
|
||||||
if (not std::isfinite(x) or std::isnan(x))
|
if (not std::isfinite(x) or std::isnan(x))
|
||||||
{
|
{
|
||||||
o.write("null", 4);
|
o->write_characters("null", 4);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7069,11 +7167,11 @@ class basic_json
|
||||||
{
|
{
|
||||||
if (std::signbit(x))
|
if (std::signbit(x))
|
||||||
{
|
{
|
||||||
o.write("-0.0", 4);
|
o->write_characters("-0.0", 4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
o.write("0.0", 3);
|
o->write_characters("0.0", 3);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -7114,7 +7212,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
o.write(number_buffer.data(), static_cast<std::streamsize>(len));
|
o->write_characters(number_buffer.data(), static_cast<size_t>(len));
|
||||||
|
|
||||||
// determine if need to append ".0"
|
// determine if need to append ".0"
|
||||||
const bool value_is_int_like = std::none_of(number_buffer.begin(),
|
const bool value_is_int_like = std::none_of(number_buffer.begin(),
|
||||||
|
@ -7126,13 +7224,13 @@ class basic_json
|
||||||
|
|
||||||
if (value_is_int_like)
|
if (value_is_int_like)
|
||||||
{
|
{
|
||||||
o.write(".0", 2);
|
o->write_characters(".0", 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// the output of the serializer
|
/// the output of the serializer
|
||||||
std::ostream& o;
|
output_adapter_t<char> o = nullptr;
|
||||||
|
|
||||||
/// a (hopefully) large enough character buffer
|
/// a (hopefully) large enough character buffer
|
||||||
std::array<char, 64> number_buffer{{}};
|
std::array<char, 64> number_buffer{{}};
|
||||||
|
@ -7181,7 +7279,7 @@ class basic_json
|
||||||
o.width(0);
|
o.width(0);
|
||||||
|
|
||||||
// do the actual serialization
|
// do the actual serialization
|
||||||
serializer s(o);
|
serializer s(output_adapter<char>::create(o));
|
||||||
s.dump(j, pretty_print, static_cast<unsigned int>(indentation));
|
s.dump(j, pretty_print, static_cast<unsigned int>(indentation));
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -8778,46 +8876,6 @@ class basic_json
|
||||||
const char* start;
|
const char* start;
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////
|
|
||||||
// output adapters //
|
|
||||||
/////////////////////
|
|
||||||
|
|
||||||
class output_adapter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void write_character(uint8_t c) = 0;
|
|
||||||
virtual void write_characters(const uint8_t* s, size_t length) = 0;
|
|
||||||
virtual ~output_adapter() {}
|
|
||||||
|
|
||||||
static std::shared_ptr<output_adapter> create(std::vector<uint8_t>& vec)
|
|
||||||
{
|
|
||||||
return std::shared_ptr<output_adapter>(new output_vector_adapter(vec));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using output_adapter_t = std::shared_ptr<output_adapter>;
|
|
||||||
|
|
||||||
class output_vector_adapter : public output_adapter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
output_vector_adapter(std::vector<uint8_t>& vec)
|
|
||||||
: v(vec)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void write_character(uint8_t c) override
|
|
||||||
{
|
|
||||||
v.push_back(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_characters(const uint8_t* s, size_t length) override
|
|
||||||
{
|
|
||||||
std::copy(s, s + length, std::back_inserter(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<uint8_t>& v;
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
// binary serialization/deserialization //
|
// binary serialization/deserialization //
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
|
@ -9872,7 +9930,7 @@ class basic_json
|
||||||
: is_little_endian(little_endianess())
|
: is_little_endian(little_endianess())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
explicit binary_writer(output_adapter_t adapter)
|
explicit binary_writer(output_adapter_t<uint8_t> adapter)
|
||||||
: is_little_endian(little_endianess()), oa(adapter)
|
: is_little_endian(little_endianess()), oa(adapter)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -10379,7 +10437,7 @@ class basic_json
|
||||||
const bool is_little_endian = true;
|
const bool is_little_endian = true;
|
||||||
|
|
||||||
/// the output
|
/// the output
|
||||||
output_adapter_t oa = nullptr;
|
output_adapter_t<uint8_t> oa = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -10468,7 +10526,7 @@ class basic_json
|
||||||
static std::vector<uint8_t> to_cbor(const basic_json& j)
|
static std::vector<uint8_t> to_cbor(const basic_json& j)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> result;
|
std::vector<uint8_t> result;
|
||||||
binary_writer bw(output_adapter::create(result));
|
binary_writer bw(output_adapter<uint8_t>::create(result));
|
||||||
bw.write_cbor(j);
|
bw.write_cbor(j);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -10550,7 +10608,7 @@ class basic_json
|
||||||
static std::vector<uint8_t> to_msgpack(const basic_json& j)
|
static std::vector<uint8_t> to_msgpack(const basic_json& j)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> result;
|
std::vector<uint8_t> result;
|
||||||
binary_writer bw(output_adapter::create(result));
|
binary_writer bw(output_adapter<uint8_t>::create(result));
|
||||||
bw.write_msgpack(j);
|
bw.write_msgpack(j);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ TEST_CASE("convenience functions")
|
||||||
const char* escaped)
|
const char* escaped)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
json::serializer s(ss);
|
json::serializer s(json::output_adapter<char>::create(ss));
|
||||||
s.dump_escaped(original);
|
s.dump_escaped(original);
|
||||||
CHECK(ss.str() == escaped);
|
CHECK(ss.str() == escaped);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue