Compare commits

...

3 Commits

  1. 40
      src/common/app_parameters.cpp
  2. 2
      src/common/object.cpp
  3. 98
      src/common/parsers/json.cpp
  4. 24
      src/include/jessilib/app_parameters.hpp
  5. 2
      src/include/jessilib/http_query.hpp
  6. 26
      src/include/jessilib/object.hpp
  7. 4
      src/include/jessilib/parser.hpp
  8. 12
      src/include/jessilib/unicode.hpp
  9. 32
      src/include/jessilib/unicode_base.hpp
  10. 12
      src/include/jessilib/unicode_compare.hpp
  11. 2
      src/include/jessilib/unicode_sequence.hpp
  12. 8
      src/include/jessilib/unicode_syntax.hpp
  13. 112
      src/test/app_parameters.cpp
  14. 20
      src/test/config.cpp
  15. 186
      src/test/object.cpp
  16. 21
      src/test/parser.cpp
  17. 67
      src/test/parsers/json.cpp

40
src/common/app_parameters.cpp

@ -26,17 +26,19 @@ app_parameters::app_parameters(int in_argc, char** in_argv)
}
app_parameters::app_parameters(int in_argc, const char** in_argv) {
// TODO: discard argc/argv and use GetCommandLineW on Windows
// TODO: not assume argv is utf-8; it often will not be
// Sanity safety check; should never happen
if (in_argc <= 0 || in_argv == nullptr) {
return;
}
// Populate path
m_path = in_argv[0];
m_path = reinterpret_cast<const char8_t*>(in_argv[0]);
// Process args
std::string_view key;
std::string value;
std::u8string_view key;
std::u8string value;
auto flush_value = [&key, &value, this]() {
// This is the start of a key; flush what we were previously processing
if (!key.empty()) {
@ -51,7 +53,7 @@ app_parameters::app_parameters(int in_argc, const char** in_argv) {
};
for (int index = 1; index < in_argc; ++index) {
const char* arg = in_argv[index];
const char8_t* arg = reinterpret_cast<const char8_t*>(in_argv[index]);
if (arg != nullptr && *arg != '\0') {
// Check if this is a key or value
if (*arg == '-') {
@ -66,7 +68,7 @@ app_parameters::app_parameters(int in_argc, const char** in_argv) {
// Parse key for any value denominator ('=')
size_t key_end = key.find('=');
if (key_end != std::string_view::npos) {
if (key_end != std::u8string_view::npos) {
// arg contains start of a value
value = key.substr(key_end + 1);
key = key.substr(0, key_end);
@ -91,30 +93,32 @@ app_parameters::app_parameters(int in_argc, const char** in_argv) {
flush_value();
// Populate m_switches_set from m_switches
m_switches_set = std::unordered_set<std::string_view>{ m_switches.begin(), m_switches.end() };
m_switches_set = std::unordered_set<std::u8string_view>{ m_switches.begin(), m_switches.end() };
}
std::string_view app_parameters::path() const {
std::u8string_view app_parameters::path() const {
return m_path;
}
const std::vector<std::string_view>& app_parameters::arguments() const {
const std::vector<std::u8string_view>& app_parameters::arguments() const {
return m_args;
}
const std::vector<std::string_view>& app_parameters::switches() const {
const std::vector<std::u8string_view>& app_parameters::switches() const {
return m_switches;
}
const std::unordered_set<std::string_view>& app_parameters::switches_set() const {
const std::unordered_set<std::u8string_view>& app_parameters::switches_set() const {
return m_switches_set;
}
const std::unordered_map<std::string_view, std::string>& app_parameters::values() const {
const std::unordered_map<std::u8string_view, std::u8string>& app_parameters::values() const {
return m_values;
}
object app_parameters::as_object() const {
using namespace std::literals;
// Null check
if (m_path.empty()
&& m_args.empty()) {
@ -122,19 +126,19 @@ object app_parameters::as_object() const {
return object{};
}
return std::map<std::string, object>{
{ "Path", m_path },
{ "Args", m_args },
{ "Switches", m_switches },
{ "Values", m_values }
return std::map<std::u8string, object>{
{ u8"Path"s, m_path },
{ u8"Args"s, m_args },
{ u8"Switches"s, m_switches },
{ u8"Values"s, m_values }
};
}
bool app_parameters::has_switch(std::string_view in_switch) const {
bool app_parameters::has_switch(std::u8string_view in_switch) const {
return m_switches_set.find(in_switch) != m_switches_set.end();
}
std::string_view app_parameters::get_value(std::string_view in_key, std::string_view in_default) const {
std::u8string_view app_parameters::get_value(std::u8string_view in_key, std::u8string_view in_default) const {
auto result = m_values.find(in_key);
// Safety check

2
src/common/object.cpp

@ -28,7 +28,7 @@ object::object(object&& in_object) {
m_value = std::move(in_object.m_value);
}
object::object(const char* in_str)
object::object(const text_char_type* in_str)
: m_value{ string_type{ in_str } } {
// Empty ctor body
}

98
src/common/parsers/json.cpp

@ -25,79 +25,42 @@ using namespace std::literals;
namespace jessilib {
std::string make_json_string(std::string_view in_string) {
std::string make_json_string(std::u8string_view in_string) {
std::string result;
result.reserve(in_string.size() + 2);
result = '\"';
while (!in_string.empty()) {
if (in_string.front() == '\\') { // backslash
decode_result decode;
while ((decode = decode_codepoint(in_string)).units != 0) {
if (decode.codepoint == U'\\') { // backslash
result += '\\';
result += '\\';
}
else if (in_string.front() == '\"') { // quotation
else if (decode.codepoint == U'\"') { // quotation
result += '\\';
result += '\"';
}
else if (in_string.front() < 0x20) { // control characters
else if (decode.codepoint < 0x20) { // control characters
result += "\\u0000"sv;
// overwrite last 2 zeroes with correct hexadecimal sequence
char* data_end = result.data() + result.size();
char* data = data_end - 2;
std::to_chars(data, data_end, in_string.front(), 16);
}
else if ((in_string.front() & 0x80) != 0) { // UTF-8 sequence; copy to bypass above processing
if ((in_string.front() & 0x40) != 0) {
// this is a 2+ byte sequence
if ((in_string.front() & 0x20) != 0) {
// this is a 3+ byte sequence
if ((in_string.front() & 0x10) != 0) {
// this is a 4 byte sequence
if (in_string.size() < 4) {
// Invalid sequence encountered (first byte indicates 4 bytes, but less than 4 available)
break;
}
// This is a 4-byte sequence
result += in_string.substr(0, 4);
in_string.remove_prefix(4);
continue;
}
if (in_string.size() < 3) {
// Invalid sequence encountered (first byte indicates 3 bytes, but less than 3 available)
break;
}
// This is a 3-byte sequence
result += in_string.substr(0, 3);
in_string.remove_prefix(3);
continue;
}
if (in_string.size() < 2) {
// Invalid sequence encountered (first byte indicates 2 bytes, but less than 2 available)
break;
}
// This is a 2-byte sequence
result += in_string.substr(0, 2);
in_string.remove_prefix(2);
continue;
char* data = data_end - 2; // Will only ever use 2 chars
auto to_chars_result = std::to_chars(data, data_end, static_cast<uint32_t>(decode.codepoint), 16);
if (to_chars_result.ec == std::errc{} && to_chars_result.ptr != data_end) {
// Only 1 byte written; shift it over
*to_chars_result.ptr = *(to_chars_result.ptr - 1);
// And fill in the zeroes
*(to_chars_result.ptr - 1) = '0';
}
// Invalid sequence encountered (first bit is 1, but not second)
break;
}
else {
// Character in standard ASCII table
result += in_string.front();
// Valid UTF-8 sequence; copy it over
result.append(reinterpret_cast<const char*>(in_string.data()), decode.units);
}
in_string.remove_prefix(1);
in_string.remove_prefix(decode.units);
}
result += '\"';
@ -132,8 +95,8 @@ uint16_t get_codepoint_from_hex(const std::string_view& in_data) {
return value;
}
std::string read_json_string(std::string_view& in_data) {
std::string result;
std::u8string read_json_string(std::string_view& in_data) {
std::u8string result;
// Remove leading quotation
in_data.remove_prefix(1);
@ -154,49 +117,49 @@ std::string read_json_string(std::string_view& in_data) {
// Quote
case '\"':
in_data.remove_prefix(1);
result += '\"';
result += u8'\"';
break;
// Backslash
case '\\':
in_data.remove_prefix(1);
result += '\\';
result += u8'\\';
break;
// Forward slash
case '/':
in_data.remove_prefix(1);
result += '/';
result += u8'/';
break;
// Backspace
case 'b':
in_data.remove_prefix(1);
result += '\b';
result += u8'\b';
break;
// Formfeed
case 'f':
in_data.remove_prefix(1);
result += '\f';
result += u8'\f';
break;
// Newline
case 'n':
in_data.remove_prefix(1);
result += '\n';
result += u8'\n';
break;
// Carriage return
case 'r':
in_data.remove_prefix(1);
result += '\r';
result += u8'\r';
break;
// Horizontal tab
case 't':
in_data.remove_prefix(1);
result += '\t';
result += u8'\t';
break;
// Unicode codepoint
@ -258,8 +221,7 @@ std::string read_json_string(std::string_view& in_data) {
}
// Valid unicode sequence
result += in_data.substr(0, codepoint.units);
//result.append(reinterpret_cast<const char8_t*>(in_data.data()), codepoint.units);
result.append(reinterpret_cast<const char8_t*>(in_data.data()), codepoint.units);
in_data.remove_prefix(codepoint.units);
break;
}
@ -492,8 +454,8 @@ std::string json_parser::serialize(const object& in_object) {
case object::type::decimal:
return std::to_string(in_object.get<long double>());
case object::type::string:
return make_json_string(in_object.get<std::string>());
case object::type::text:
return make_json_string(in_object.get<std::u8string>());
case object::type::array: {
if (in_object.size() == 0) {

24
src/include/jessilib/app_parameters.hpp

@ -25,24 +25,24 @@ public:
app_parameters(int in_argc, char** in_argv);
app_parameters(int in_argc, const char** in_argv);
std::string_view path() const;
const std::vector<std::string_view>& arguments() const;
const std::vector<std::string_view>& switches() const;
const std::unordered_set<std::string_view>& switches_set() const;
const std::unordered_map<std::string_view, std::string>& values() const;
std::u8string_view path() const;
const std::vector<std::u8string_view>& arguments() const;
const std::vector<std::u8string_view>& switches() const;
const std::unordered_set<std::u8string_view>& switches_set() const;
const std::unordered_map<std::u8string_view, std::u8string>& values() const;
jessilib::object as_object() const;
bool has_switch(std::string_view in_switch) const;
std::string_view get_value(std::string_view in_key, std::string_view in_default = {}) const;
bool has_switch(std::u8string_view in_switch) const;
std::u8string_view get_value(std::u8string_view in_key, std::u8string_view in_default = {}) const;
operator jessilib::object() const { return as_object(); }
private:
std::string_view m_path;
std::vector<std::string_view> m_args;
std::vector<std::string_view> m_switches;
std::unordered_set<std::string_view> m_switches_set;
std::unordered_map<std::string_view, std::string> m_values;
std::u8string_view m_path;
std::vector<std::u8string_view> m_args;
std::vector<std::u8string_view> m_switches;
std::unordered_set<std::u8string_view> m_switches_set;
std::unordered_map<std::u8string_view, std::u8string> m_values;
};
} // namespace jessilib

2
src/include/jessilib/http_query.hpp

@ -144,7 +144,7 @@ constexpr syntax_tree_member<CharT, ContextT> make_simple_shrink_pair() {
}
template<typename CharT, typename ContextT>
bool html_form_default_action(get_endpoint_result decode, ContextT& inout_context, std::basic_string_view<CharT>& inout_read_view) {
bool html_form_default_action(decode_result decode, ContextT& inout_context, std::basic_string_view<CharT>& inout_read_view) {
// A regular character; copy it and advance the read/write heads
CharT*& write_head = inout_context.write_head;
CharT* write_end = write_head + decode.units;

26
src/include/jessilib/object.hpp

@ -31,8 +31,12 @@ namespace jessilib {
class object {
public:
using array_type = std::vector<object>;
using string_type = std::string;
using string_view_type = std::string_view;
using text_char_type = char8_t;
using text_type = std::basic_string<text_char_type>;
using text_view_type = std::basic_string_view<text_char_type>;
using data_type = std::vector<unsigned char>;
using string_type = text_type;
using string_view_type = text_view_type;
using map_type = std::map<string_type, object>;
using index_type = std::size_t;
@ -86,7 +90,8 @@ public:
boolean,
integer,
decimal,
string, // TODO: consider separating into 'binary' (std::vector<std::byte>) and 'text' (string_type) types
text,
data,
array,
map
};
@ -152,7 +157,7 @@ public:
}
}
object(const char* in_str);
object(const text_char_type* in_str);
object(const string_view_type& in_str);
// Comparison operators
@ -454,6 +459,17 @@ public:
return result;
}
else if constexpr (std::is_same<T, data_type>::value) {
// TODO: pull this into a separate method
uint64_t hash = 14695981039346656037ULL;
for (auto byte : value) {
hash = hash ^ byte;
hash = hash * 1099511628211ULL;
}
return hash;
}
else {
return std::hash<T>{}(std::forward<decltype(value)>(value));
}
@ -464,7 +480,7 @@ private:
using null_variant_t = void*;
// TODO: consider replacing std::string with std::u8string (for strings) & std::vector<unsigned char> (for data)
// TODO: consider some more generic mechanism for underlying string type, to support utf-16 & utf-32 strings
std::variant<null_variant_t, bool, intmax_t, long double, string_type, array_type, map_type> m_value;
std::variant<null_variant_t, bool, intmax_t, long double, text_type, data_type, array_type, map_type> m_value;
// TODO: note for future self, just use either first or last element in array_type to hold XML attributes
// OR, have every XML tag objects be a map, with all subobjects being in a "__values" array subobject or such

4
src/include/jessilib/parser.hpp

@ -38,9 +38,9 @@ public:
* @return A valid (possibly null) object
*/
virtual object deserialize(std::istream& in_stream);
virtual object deserialize(std::string_view in_data) = 0;
virtual object deserialize(std::string_view in_data) = 0; // TODO: serialize from arbitrary unicode strings
virtual void serialize(std::ostream& in_stream, const object& in_object);
virtual std::string serialize(const object& in_object) = 0;
virtual std::string serialize(const object& in_object) = 0; // TODO: serialize to arbitrary unicode strings
}; // parser
template<typename T>

12
src/include/jessilib/unicode.hpp

@ -89,7 +89,7 @@ bool is_valid(const InT& in_string) {
InViewT in_string_view = static_cast<InViewT>(in_string);
while (!in_string_view.empty()) {
get_endpoint_result string_front = decode_codepoint(in_string_view);
decode_result string_front = decode_codepoint(in_string_view);
if (string_front.units == 0) {
return false;
}
@ -163,7 +163,7 @@ std::basic_string<OutCharT> string_cast(const InT& in_string) {
}
while (!in_string_view.empty()) {
get_endpoint_result string_front = decode_codepoint(in_string_view);
decode_result string_front = decode_codepoint(in_string_view);
if (string_front.units == 0) {
return {};
}
@ -199,7 +199,7 @@ size_t find(std::basic_string_view<LhsCharT> in_string, char32_t in_codepoint) {
size_t codepoints_removed{};
while (!in_string.empty()) {
std::basic_string_view<LhsCharT> string = in_string;
get_endpoint_result string_front = decode_codepoint(string);
decode_result string_front = decode_codepoint(string);
if (string_front.units == 0) {
// Failed to decode front codepoint; bad unicode sequence
@ -267,12 +267,12 @@ size_t find(std::basic_string_view<LhsCharT> in_string, std::basic_string_view<R
std::basic_string_view<LhsCharT> string = in_string;
std::basic_string_view<RhsCharT> substring = in_substring;
get_endpoint_result string_front;
decode_result string_front;
do {
// TODO: optimize this for when in_string and in_substring are same type, by only decoding in_string, solely
// to determine number of data units to compare
string_front = decode_codepoint(string);
get_endpoint_result prefix_front = decode_codepoint(substring);
decode_result prefix_front = decode_codepoint(substring);
if (string_front.units == 0
|| prefix_front.units == 0) {
@ -386,7 +386,7 @@ constexpr void join_append(OutT& out_string, InT&& in_string, ArgsT&&... in_args
}
else {
// Append over all the codepoints
get_endpoint_result decode;
decode_result decode;
std::basic_string_view<InCharT> in_view = in_string;
while ((decode = decode_codepoint(in_view)).units != 0) {
encode_codepoint(out_string, decode.codepoint);

32
src/include/jessilib/unicode_base.hpp

@ -74,7 +74,7 @@ std::wstring encode_codepoint_w(char32_t in_codepoint); // ASSUMES UTF-16 OR UTF
/** decode_codepoint */
struct get_endpoint_result {
struct decode_result {
char32_t codepoint{}; // Codepoint
size_t units{}; // Number of data units codepoint was represented by, or 0
};
@ -86,17 +86,17 @@ struct get_endpoint_result {
* @return A struct containing a valid codepoint and the number of representative data units on success, zero otherwise.
*/
template<typename CharT>
constexpr get_endpoint_result decode_codepoint_utf8(std::basic_string_view<CharT> in_string); // UTF-8
constexpr decode_result decode_codepoint_utf8(std::basic_string_view<CharT> in_string); // UTF-8
template<typename CharT>
constexpr get_endpoint_result decode_codepoint_utf16(std::basic_string_view<CharT> in_string); // UTF-16
constexpr decode_result decode_codepoint_utf16(std::basic_string_view<CharT> in_string); // UTF-16
template<typename CharT>
constexpr get_endpoint_result decode_codepoint_utf32(std::basic_string_view<CharT> in_string); // UTF-32
constexpr decode_result decode_codepoint_utf32(std::basic_string_view<CharT> in_string); // UTF-32
template<typename CharT>
constexpr get_endpoint_result decode_codepoint(std::basic_string_view<CharT> in_string); // ASSUMES UTF-16 OR UTF-32
constexpr decode_result decode_codepoint(std::basic_string_view<CharT> in_string); // ASSUMES UTF-16 OR UTF-32
template<typename CharT>
constexpr get_endpoint_result decode_codepoint(const CharT* in_begin, size_t in_length);
constexpr decode_result decode_codepoint(const CharT* in_begin, size_t in_length);
template<typename CharT>
constexpr get_endpoint_result decode_codepoint(const CharT* in_begin, const CharT* in_end);
constexpr decode_result decode_codepoint(const CharT* in_begin, const CharT* in_end);
/** advance_codepoint */
@ -125,7 +125,7 @@ bool is_valid_codepoint(const std::basic_string_view<T>& in_string) {
constexpr bool is_high_surrogate(char32_t in_codepoint);
constexpr bool is_low_surrogate(char32_t in_codepoint);
constexpr get_endpoint_result decode_surrogate_pair(char16_t in_high_surrogate, char16_t in_low_surrogate);
constexpr decode_result decode_surrogate_pair(char16_t in_high_surrogate, char16_t in_low_surrogate);
template<typename CharT>
struct unicode_traits : std::false_type {};
@ -365,8 +365,8 @@ constexpr size_t encode_codepoint(CharT* out_buffer, char32_t in_codepoint) {
/** decode_codepoint */
template<typename CharT>
constexpr get_endpoint_result decode_codepoint_utf8(std::basic_string_view<CharT> in_string) {
get_endpoint_result result{ 0, 0 };
constexpr decode_result decode_codepoint_utf8(std::basic_string_view<CharT> in_string) {
decode_result result{ 0, 0 };
if (in_string.empty()) {
return result;
@ -426,7 +426,7 @@ constexpr get_endpoint_result decode_codepoint_utf8(std::basic_string_view<CharT
}
template<typename CharT>
constexpr get_endpoint_result decode_codepoint_utf16(std::basic_string_view<CharT> in_string) {
constexpr decode_result decode_codepoint_utf16(std::basic_string_view<CharT> in_string) {
if (in_string.empty()) {
return { 0, 0 };
}
@ -449,7 +449,7 @@ constexpr get_endpoint_result decode_codepoint_utf16(std::basic_string_view<Char
}
template<typename CharT>
constexpr get_endpoint_result decode_codepoint_utf32(std::basic_string_view<CharT> in_string) {
constexpr decode_result decode_codepoint_utf32(std::basic_string_view<CharT> in_string) {
if (in_string.empty()) {
return { 0, 0 };
}
@ -458,7 +458,7 @@ constexpr get_endpoint_result decode_codepoint_utf32(std::basic_string_view<Char
}
template<typename CharT>
constexpr get_endpoint_result decode_codepoint(std::basic_string_view<CharT> in_string) {
constexpr decode_result decode_codepoint(std::basic_string_view<CharT> in_string) {
if constexpr (std::is_same_v<CharT, char8_t>) {
return decode_codepoint_utf8(in_string);
}
@ -482,12 +482,12 @@ constexpr get_endpoint_result decode_codepoint(std::basic_string_view<CharT> in_
}
template<typename CharT>
constexpr get_endpoint_result decode_codepoint(const CharT* in_begin, size_t in_length) {
constexpr decode_result decode_codepoint(const CharT* in_begin, size_t in_length) {
return decode_codepoint<CharT>(std::basic_string_view<CharT>{in_begin, in_length});
}
template<typename CharT>
constexpr get_endpoint_result decode_codepoint(const CharT* in_begin, const CharT* in_end) {
constexpr decode_result decode_codepoint(const CharT* in_begin, const CharT* in_end) {
return decode_codepoint<CharT>(std::basic_string_view<CharT>{in_begin, static_cast<size_t>(in_end - in_begin)});
}
@ -499,7 +499,7 @@ constexpr bool is_low_surrogate(char32_t in_codepoint) {
return in_codepoint >= 0xDC00 && in_codepoint <= 0xDFFF;
}
constexpr get_endpoint_result decode_surrogate_pair(char16_t in_high_surrogate, char16_t in_low_surrogate) {
constexpr decode_result decode_surrogate_pair(char16_t in_high_surrogate, char16_t in_low_surrogate) {
if (is_high_surrogate(in_high_surrogate)
&& is_low_surrogate((in_low_surrogate))) {
// We have a valid surrogate pair; decode it into a codepoint and return

12
src/include/jessilib/unicode_compare.hpp

@ -145,8 +145,8 @@ size_t starts_with_length(std::basic_string_view<LhsCharT> in_string, std::basic
size_t codepoints_removed{};
while (!in_string.empty() && !in_prefix.empty()) {
get_endpoint_result string_front = decode_codepoint(in_string);
get_endpoint_result prefix_front = decode_codepoint(in_prefix);
decode_result string_front = decode_codepoint(in_string);
decode_result prefix_front = decode_codepoint(in_prefix);
if (string_front.units == 0
|| prefix_front.units == 0) {
@ -195,8 +195,8 @@ size_t starts_with_lengthi(std::basic_string_view<LhsCharT> in_string, std::basi
size_t codepoints_removed{};
while (!in_string.empty() && !in_prefix.empty()) {
get_endpoint_result string_front = decode_codepoint(in_string);
get_endpoint_result prefix_front = decode_codepoint(in_prefix);
decode_result string_front = decode_codepoint(in_string);
decode_result prefix_front = decode_codepoint(in_prefix);
if (string_front.units == 0
|| prefix_front.units == 0) {
@ -270,7 +270,7 @@ struct text_hash {
static uint64_t hash(const CharT* data, const CharT* end) {
uint64_t hash = 14695981039346656037ULL;
get_endpoint_result decode;
decode_result decode;
while (data != end) {
decode = decode_codepoint(data, end);
if (decode.units == 0) {
@ -355,7 +355,7 @@ struct text_hashi {
static uint64_t hash(const CharT* data, const CharT* end) {
uint64_t hash = 14695981039346656037ULL;
get_endpoint_result decode;
decode_result decode;
while (data != end) {
decode = decode_codepoint(data, end - data);
if (decode.units == 0) {

2
src/include/jessilib/unicode_sequence.hpp

@ -89,7 +89,7 @@ constexpr bool apply_shrink_sequence_tree(std::basic_string<CharT>& inout_string
std::basic_string_view<CharT> read_view = inout_string;
CharT* write_head = inout_string.data();
get_endpoint_result decode;
decode_result decode;
constexpr auto SubTreeEnd = SequenceTreeBegin + SequenceTreeSize;
while ((decode = decode_codepoint(read_view)).units != 0) {

8
src/include/jessilib/unicode_syntax.hpp

@ -37,7 +37,7 @@ template<typename CharT, typename ContextT>
using syntax_tree_action = bool(*)(ContextT& inout_context, std::basic_string_view<CharT>& inout_read_view);
template<typename CharT, typename ContextT>
using default_syntax_tree_action = bool(*)(get_endpoint_result in_codepoint, ContextT& inout_context, std::basic_string_view<CharT>& inout_read_view);
using default_syntax_tree_action = bool(*)(decode_result in_codepoint, ContextT& inout_context, std::basic_string_view<CharT>& inout_read_view);
template<typename CharT, typename ContextT>
using syntax_tree = const std::pair<char32_t, syntax_tree_action<CharT, ContextT>>[];
@ -73,12 +73,12 @@ constexpr bool is_sorted() {
}
template<typename CharT, typename ContextT>
bool fail_action(get_endpoint_result, ContextT&, std::basic_string_view<CharT>&) {
bool fail_action(decode_result, ContextT&, std::basic_string_view<CharT>&) {
return false;
}
template<typename CharT, typename ContextT>
bool noop_action(get_endpoint_result decode, ContextT&, std::basic_string_view<CharT>& inout_read_view) {
bool noop_action(decode_result decode, ContextT&, std::basic_string_view<CharT>& inout_read_view) {
inout_read_view.remove_prefix(decode.units);
return true;
}
@ -111,7 +111,7 @@ constexpr bool apply_syntax_tree(ContextT& inout_context, std::basic_string_view
return true;
}
get_endpoint_result decode;
decode_result decode;
constexpr auto SubTreeEnd = SequenceTreeBegin + SequenceTreeSize;
while ((decode = decode_codepoint(inout_read_view)).units != 0) {
auto parser = std::lower_bound(SequenceTreeBegin, SubTreeEnd, decode.codepoint, &syntax_tree_member_compare<CharT, ContextT>);

112
src/test/app_parameters.cpp

@ -75,7 +75,7 @@ TEST(AppParametersTest, path_only) {
ArgWrapper args{ "/path/to/exe" };
app_parameters parameters{ args.argc(), args.argv() };
EXPECT_EQ(parameters.path(), "/path/to/exe");
EXPECT_EQ(parameters.path(), u8"/path/to/exe");
EXPECT_TRUE(parameters.arguments().empty());
EXPECT_TRUE(parameters.switches().empty());
EXPECT_TRUE(parameters.switches_set().empty());
@ -83,7 +83,7 @@ TEST(AppParametersTest, path_only) {
auto obj = parameters.as_object();
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
}
TEST(AppParametersTest, single_switch) {
@ -98,9 +98,9 @@ TEST(AppParametersTest, single_switch) {
auto obj = parameters.as_object();
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj["Args"], object{ std::vector<std::string>{ "-switch" } });
EXPECT_EQ(obj["Switches"], object{ std::vector<std::string>{ "switch" } });
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
EXPECT_EQ(obj[u8"Args"], object{ std::vector<std::u8string>{ u8"-switch" } });
EXPECT_EQ(obj[u8"Switches"], object{ std::vector<std::u8string>{ u8"switch" } });
}
TEST(AppParametersTest, double_switch) {
@ -114,12 +114,12 @@ TEST(AppParametersTest, double_switch) {
EXPECT_TRUE(parameters.values().empty());
auto obj = parameters.as_object();
std::vector<std::string> expected_args{ "-switch1", "--switch2" };
std::vector<std::string> expected_switches{ "switch1", "switch2" };
std::vector<std::u8string> expected_args{ u8"-switch1", u8"--switch2" };
std::vector<std::u8string> expected_switches{ u8"switch1", u8"switch2" };
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj["Args"], expected_args);
EXPECT_EQ(obj["Switches"], expected_switches);
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
EXPECT_EQ(obj[u8"Args"], expected_args);
EXPECT_EQ(obj[u8"Switches"], expected_switches);
}
TEST(AppParametersTest, duplicate_switch) {
@ -133,12 +133,12 @@ TEST(AppParametersTest, duplicate_switch) {
EXPECT_TRUE(parameters.values().empty());
auto obj = parameters.as_object();
std::vector<std::string> expected_args{ "-switch", "--switch" };
std::vector<std::string> expected_switches{ "switch", "switch" };
std::vector<std::u8string> expected_args{ u8"-switch", u8"--switch" };
std::vector<std::u8string> expected_switches{ u8"switch", u8"switch" };
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj["Args"], expected_args);
EXPECT_EQ(obj["Switches"], expected_switches);
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
EXPECT_EQ(obj[u8"Args"], expected_args);
EXPECT_EQ(obj[u8"Switches"], expected_switches);
}
TEST(AppParametersTest, single_value) {
@ -152,12 +152,12 @@ TEST(AppParametersTest, single_value) {
EXPECT_EQ(parameters.values().size(), 1U);
auto obj = parameters.as_object();
std::vector<std::string> expected_args{ "-key", "value" };
std::map<std::string, object> expected_values{ { "key", "value" } };
std::vector<std::u8string> expected_args{ u8"-key", u8"value" };
std::map<std::u8string, object> expected_values{ { u8"key", u8"value" } };
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj["Args"], expected_args);
EXPECT_EQ(obj["Values"], expected_values);
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
EXPECT_EQ(obj[u8"Args"], expected_args);
EXPECT_EQ(obj[u8"Values"], expected_values);
}
TEST(AppParametersTest, single_value_eq) {
@ -171,12 +171,12 @@ TEST(AppParametersTest, single_value_eq) {
EXPECT_EQ(parameters.values().size(), 1U);
auto obj = parameters.as_object();
std::vector<std::string> expected_args{ "-key=value" };
std::map<std::string, object> expected_values{ { "key", "value" } };
std::vector<std::u8string> expected_args{ u8"-key=value" };
std::map<std::u8string, object> expected_values{ { u8"key", u8"value" } };
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj["Args"], expected_args);
EXPECT_EQ(obj["Values"], expected_values);
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
EXPECT_EQ(obj[u8"Args"], expected_args);
EXPECT_EQ(obj[u8"Values"], expected_values);
}
TEST(AppParametersTest, multiword_value) {
@ -190,12 +190,12 @@ TEST(AppParametersTest, multiword_value) {
EXPECT_EQ(parameters.values().size(), 1U);
auto obj = parameters.as_object();
std::vector<std::string> expected_args{ "-key", "valuePart1", "valuePart2" };
std::map<std::string, object> expected_values{ { "key", "valuePart1 valuePart2" } };
std::vector<std::u8string> expected_args{ u8"-key", u8"valuePart1", u8"valuePart2" };
std::map<std::u8string, object> expected_values{ { u8"key", u8"valuePart1 valuePart2" } };
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj["Args"], expected_args);
EXPECT_EQ(obj["Values"], expected_values);
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
EXPECT_EQ(obj[u8"Args"], expected_args);
EXPECT_EQ(obj[u8"Values"], expected_values);
}
TEST(AppParametersTest, multiword_value_eq) {
@ -209,12 +209,12 @@ TEST(AppParametersTest, multiword_value_eq) {
EXPECT_EQ(parameters.values().size(), 1U);
auto obj = parameters.as_object();
std::vector<std::string> expected_args{ "-key=valuePart1", "valuePart2" };
std::map<std::string, object> expected_values{ { "key", "valuePart1 valuePart2" } };
std::vector<std::u8string> expected_args{ u8"-key=valuePart1", u8"valuePart2" };
std::map<std::u8string, object> expected_values{ { u8"key", u8"valuePart1 valuePart2" } };
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj["Args"], expected_args);
EXPECT_EQ(obj["Values"], expected_values);
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
EXPECT_EQ(obj[u8"Args"], expected_args);
EXPECT_EQ(obj[u8"Values"], expected_values);
}
TEST(AppParametersTest, double_value) {
@ -228,12 +228,12 @@ TEST(AppParametersTest, double_value) {
EXPECT_EQ(parameters.values().size(), 2U);
auto obj = parameters.as_object();
std::vector<std::string> expected_args{ "-key", "value", "--key2", "value2" };
std::map<std::string, object> expected_values{ { "key", "value" }, { "key2", "value2" } };
std::vector<std::u8string> expected_args{ u8"-key", u8"value", u8"--key2", u8"value2" };
std::map<std::u8string, object> expected_values{ { u8"key", u8"value" }, { u8"key2", u8"value2" } };
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj["Args"], expected_args);
EXPECT_EQ(obj["Values"], expected_values);
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
EXPECT_EQ(obj[u8"Args"], expected_args);
EXPECT_EQ(obj[u8"Values"], expected_values);
}
TEST(AppParametersTest, double_value_eq) {
@ -247,12 +247,12 @@ TEST(AppParametersTest, double_value_eq) {
EXPECT_EQ(parameters.values().size(), 2U);
auto obj = parameters.as_object();
std::vector<std::string> expected_args{ "-key=value", "--key2=value2" };
std::map<std::string, object> expected_values{ { "key", "value" }, { "key2", "value2" } };
std::vector<std::u8string> expected_args{ u8"-key=value", u8"--key2=value2" };
std::map<std::u8string, object> expected_values{ { u8"key", u8"value" }, { u8"key2", u8"value2" } };
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj["Args"], expected_args);
EXPECT_EQ(obj["Values"], expected_values);
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
EXPECT_EQ(obj[u8"Args"], expected_args);
EXPECT_EQ(obj[u8"Values"], expected_values);
}
TEST(AppParametersTest, switch_and_value) {
@ -266,16 +266,16 @@ TEST(AppParametersTest, switch_and_value) {
EXPECT_EQ(parameters.values().size(), 1U);
auto obj = parameters.as_object();
std::vector<std::string> expected_args{ "--switch", "-key", "value" };
std::vector<std::string> expected_switches{ "switch" };
std::map<std::string, object> expected_values{ { "key", "value" } };
std::vector<std::u8string> expected_args{ u8"--switch", u8"-key", u8"value" };
std::vector<std::u8string> expected_switches{ u8"switch" };
std::map<std::u8string, object> expected_values{ { u8"key", u8"value" } };
EXPECT_FALSE(obj.null());
EXPECT_EQ(obj["Path"], "/path/to/exe");
EXPECT_EQ(obj["Args"], expected_args);
EXPECT_EQ(obj["Switches"], expected_switches);
EXPECT_EQ(obj["Values"], expected_values);
EXPECT_TRUE(parameters.has_switch("switch"));
EXPECT_FALSE(parameters.has_switch("switch2"));
EXPECT_EQ(parameters.get_value("key"), "value");
EXPECT_EQ(obj[u8"Path"], u8"/path/to/exe");
EXPECT_EQ(obj[u8"Args"], expected_args);
EXPECT_EQ(obj[u8"Switches"], expected_switches);
EXPECT_EQ(obj[u8"Values"], expected_values);
EXPECT_TRUE(parameters.has_switch(u8"switch"));
EXPECT_FALSE(parameters.has_switch(u8"switch2"));
EXPECT_EQ(parameters.get_value(u8"key"), u8"value");
}

20
src/test/config.cpp

@ -55,14 +55,14 @@ TEST(ConfigTest, get_format) {
TEST(ConfigTest, read_object) {
std::filesystem::path file_path = make_tmp_file("read_object.test", "some_data");
EXPECT_EQ(config::read_object(file_path).get<std::string>(), "some_data");
EXPECT_EQ(config::read_object(file_path).get<std::u8string>(), u8"some_data");
}
TEST(ConfigTest, write_object) {
std::filesystem::path file_path = make_tmp_file("write_object.test", "some_data");
config::write_object(object{}, file_path);
EXPECT_EQ(config::read_object(file_path).get<std::string>(), "serialize_result");
EXPECT_EQ(config::read_object(file_path).get<std::u8string>(), u8"serialize_result");
}
TEST(ConfigTest, load) {
@ -75,7 +75,7 @@ TEST(ConfigTest, load) {
l_config.load(file_path);
// Verify
EXPECT_EQ(l_config.data().get<std::string>(), "some_data");
EXPECT_EQ(l_config.data().get<std::u8string>(), u8"some_data");
EXPECT_EQ(l_config.filename(), file_path);
EXPECT_EQ(l_config.format(), "test");
}
@ -94,25 +94,25 @@ TEST(ConfigTest, reload) {
// Reload data from disk and compare
l_config.reload();
EXPECT_EQ(l_config.data().get<std::string>(), "some_other_data");
EXPECT_EQ(l_config.data().get<std::u8string>(), u8"some_other_data");
}
TEST(ConfigTest, set_data) {
config l_config;
l_config.set_data("some_data");
EXPECT_EQ(l_config.data().get<std::string>(), "some_data");
l_config.set_data(u8"some_data");
EXPECT_EQ(l_config.data().get<std::u8string>(), u8"some_data");
}
TEST(ConfigTest, write) {
config l_config;
std::filesystem::path file_path = make_tmp_file("write.test", "");
l_config.set_data("some_data");
l_config.set_data(u8"some_data");
l_config.write(file_path);
l_config.reload();
EXPECT_EQ(l_config.data().get<std::string>(), "some_data");
EXPECT_EQ(l_config.data().get<std::u8string>(), u8"some_data");
}
TEST(ConfigTest, rewrite) {
@ -125,12 +125,12 @@ TEST(ConfigTest, rewrite) {
l_config.load(file_path);
// Set some other data
l_config.set_data("some_other_data");
l_config.set_data(u8"some_other_data");
// Write data to disk
l_config.write();
// Reload from disk and verify
l_config.reload();
EXPECT_EQ(l_config.data().get<std::string>(), "some_other_data");
EXPECT_EQ(l_config.data().get<std::u8string>(), u8"some_other_data");
}

186
src/test/object.cpp

@ -27,19 +27,19 @@ using unsigned_char_t = unsigned char;
using long_long_t = long long;
using long_double_t = long double;
using map_str_str = std::map<std::string, std::string>;
using map_str_strv = std::map<std::string, std::string_view>;
using map_str_obj = std::map<std::string, object>;
using map_strv_str = std::map<std::string_view, std::string>;
using map_strv_strv = std::map<std::string_view, std::string_view>;
using map_strv_obj = std::map<std::string_view, object>;
using unordered_map_str_str = std::unordered_map<std::string, std::string>;
using unordered_map_str_strv = std::unordered_map<std::string, std::string_view>;
using unordered_map_str_obj = std::unordered_map<std::string, object>;
using unordered_map_strv_str = std::unordered_map<std::string_view, std::string>;
using unordered_map_strv_strv = std::unordered_map<std::string_view, std::string_view>;
using unordered_map_strv_obj = std::unordered_map<std::string_view, object>;
using map_str_str = std::map<std::u8string, std::u8string>;
using map_str_strv = std::map<std::u8string, std::u8string_view>;
using map_str_obj = std::map<std::u8string, object>;
using map_strv_str = std::map<std::u8string_view, std::u8string>;
using map_strv_strv = std::map<std::u8string_view, std::u8string_view>;
using map_strv_obj = std::map<std::u8string_view, object>;
using unordered_map_str_str = std::unordered_map<std::u8string, std::u8string>;
using unordered_map_str_strv = std::unordered_map<std::u8string, std::u8string_view>;
using unordered_map_str_obj = std::unordered_map<std::u8string, object>;
using unordered_map_strv_str = std::unordered_map<std::u8string_view, std::u8string>;
using unordered_map_strv_strv = std::unordered_map<std::u8string_view, std::u8string_view>;
using unordered_map_strv_obj = std::unordered_map<std::u8string_view, object>;
/** basic tests; these test function calls against null objects and heavily test for compilation errors */
@ -66,7 +66,7 @@ TEST(ObjectTest, basic_has) {
EXPECT_FALSE(obj.has<float>());
EXPECT_FALSE(obj.has<double>());
EXPECT_FALSE(obj.has<long double>());
EXPECT_FALSE(obj.has<std::string>());
EXPECT_FALSE(obj.has<std::u8string>());
EXPECT_FALSE(obj.has<object::array_type>());
EXPECT_FALSE(obj.has<object::map_type>());
}
@ -85,7 +85,7 @@ TEST(ObjectTest, basic_has_vector) {
EXPECT_FALSE(obj.has<std::vector<float>>());
EXPECT_FALSE(obj.has<std::vector<double>>());
EXPECT_FALSE(obj.has<std::vector<long double>>());
EXPECT_FALSE(obj.has<std::vector<std::string>>());
EXPECT_FALSE(obj.has<std::vector<std::u8string>>());
EXPECT_FALSE(obj.has<std::vector<object>>());
}
@ -103,7 +103,7 @@ TEST(ObjectTest, basic_has_list) {
EXPECT_FALSE(obj.has<std::list<float>>());
EXPECT_FALSE(obj.has<std::list<double>>());
EXPECT_FALSE(obj.has<std::list<long double>>());
EXPECT_FALSE(obj.has<std::list<std::string>>());
EXPECT_FALSE(obj.has<std::list<std::u8string>>());
EXPECT_FALSE(obj.has<std::list<object>>());
}
@ -121,7 +121,7 @@ TEST(ObjectTest, basic_has_forward_list) {
EXPECT_FALSE(obj.has<std::forward_list<float>>());
EXPECT_FALSE(obj.has<std::forward_list<double>>());
EXPECT_FALSE(obj.has<std::forward_list<long double>>());
EXPECT_FALSE(obj.has<std::forward_list<std::string>>());
EXPECT_FALSE(obj.has<std::forward_list<std::u8string>>());
EXPECT_FALSE(obj.has<std::forward_list<object>>());
}
@ -139,7 +139,7 @@ TEST(ObjectTest, basic_has_set) {
EXPECT_FALSE(obj.has<std::set<float>>());
EXPECT_FALSE(obj.has<std::set<double>>());
EXPECT_FALSE(obj.has<std::set<long double>>());
EXPECT_FALSE(obj.has<std::set<std::string>>());
EXPECT_FALSE(obj.has<std::set<std::u8string>>());
EXPECT_FALSE(obj.has<std::set<object>>());
}
@ -157,7 +157,7 @@ TEST(ObjectTest, basic_has_unordered_set) {
EXPECT_FALSE(obj.has<std::unordered_set<float>>());
EXPECT_FALSE(obj.has<std::unordered_set<double>>());
EXPECT_FALSE(obj.has<std::unordered_set<long double>>());
EXPECT_FALSE(obj.has<std::unordered_set<std::string>>());
EXPECT_FALSE(obj.has<std::unordered_set<std::u8string>>());
EXPECT_FALSE(obj.has<std::unordered_set<object>>());
}
@ -199,7 +199,7 @@ TEST(ObjectTest, basic_get) {
EXPECT_EQ(obj.get<float>(), float{});
EXPECT_EQ(obj.get<double>(), double{});
EXPECT_EQ(obj.get<long double>(), long_double_t{});
EXPECT_EQ(obj.get<std::string>(), std::string{});
EXPECT_EQ(obj.get<std::u8string>(), std::u8string{});
EXPECT_TRUE(obj.get<object::array_type>().empty());
EXPECT_TRUE(obj.get<object::map_type>().empty());
}
@ -218,7 +218,7 @@ TEST(ObjectTest, basic_get_vector) {
EXPECT_TRUE(obj.get<std::vector<float>>().empty());
EXPECT_TRUE(obj.get<std::vector<double>>().empty());
EXPECT_TRUE(obj.get<std::vector<long double>>().empty());
EXPECT_TRUE(obj.get<std::vector<std::string>>().empty());
EXPECT_TRUE(obj.get<std::vector<std::u8string>>().empty());
EXPECT_TRUE(obj.get<std::vector<object>>().empty());
}
@ -236,7 +236,7 @@ TEST(ObjectTest, basic_get_list) {
EXPECT_TRUE(obj.get<std::list<float>>().empty());
EXPECT_TRUE(obj.get<std::list<double>>().empty());
EXPECT_TRUE(obj.get<std::list<long double>>().empty());
EXPECT_TRUE(obj.get<std::list<std::string>>().empty());
EXPECT_TRUE(obj.get<std::list<std::u8string>>().empty());
EXPECT_TRUE(obj.get<std::list<object>>().empty());
}
@ -254,7 +254,7 @@ TEST(ObjectTest, basic_get_forward_list) {
EXPECT_TRUE(obj.get<std::forward_list<float>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<double>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<long double>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<std::string>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<std::u8string>>().empty());
EXPECT_TRUE(obj.get<std::forward_list<object>>().empty());
}
@ -272,7 +272,7 @@ TEST(ObjectTest, basic_get_set) {
EXPECT_TRUE(obj.get<std::set<float>>().empty());
EXPECT_TRUE(obj.get<std::set<double>>().empty());
EXPECT_TRUE(obj.get<std::set<long double>>().empty());
EXPECT_TRUE(obj.get<std::set<std::string>>().empty());
EXPECT_TRUE(obj.get<std::set<std::u8string>>().empty());
EXPECT_TRUE(obj.get<std::set<object>>().empty());
}
@ -290,7 +290,7 @@ TEST(ObjectTest, basic_get_multiset) {
EXPECT_TRUE(obj.get<std::multiset<float>>().empty());
EXPECT_TRUE(obj.get<std::multiset<double>>().empty());
EXPECT_TRUE(obj.get<std::multiset<long double>>().empty());
EXPECT_TRUE(obj.get<std::multiset<std::string>>().empty());
EXPECT_TRUE(obj.get<std::multiset<std::u8string>>().empty());
EXPECT_TRUE(obj.get<std::multiset<object>>().empty());
}
@ -308,7 +308,7 @@ TEST(ObjectTest, basic_get_unordered_set) {
EXPECT_TRUE(obj.get<std::unordered_set<float>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<double>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<long double>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<std::string>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<std::u8string>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<object>>().empty());
}
@ -326,7 +326,7 @@ TEST(ObjectTest, basic_get_unordered_multiset) {
EXPECT_TRUE(obj.get<std::unordered_multiset<float>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<double>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<long double>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<std::string>>().empty());
EXPECT_TRUE(obj.get<std::unordered_multiset<std::u8string>>().empty());
EXPECT_TRUE(obj.get<std::unordered_set<object>>().empty());
}
@ -351,21 +351,21 @@ TEST(ObjectTest, basic_value_constructor) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(float);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(double);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(long_double_t);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::string);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::u8string);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(object::array_type);
// const char*
{
object obj{ "" };
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
object obj{ u8"" };
EXPECT_TRUE(obj.has<std::u8string>());
EXPECT_EQ(obj.get<std::u8string>(), std::u8string{});
}
// std::string_view
// std::u8string_view
{
object obj{ ""sv };
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
object obj{ u8""sv };
EXPECT_TRUE(obj.has<std::u8string>());
EXPECT_EQ(obj.get<std::u8string>(), std::u8string{});
}
}
@ -381,7 +381,7 @@ TEST(ObjectTest, basic_value_constructor_vector) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<std::u8string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<object>);
}
@ -397,7 +397,7 @@ TEST(ObjectTest, basic_value_constructor_list) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<std::u8string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<object>);
}
@ -413,7 +413,7 @@ TEST(ObjectTest, basic_value_constructor_forward_list) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<std::u8string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<object>);
}
@ -429,7 +429,7 @@ TEST(ObjectTest, basic_value_constructor_set) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<std::u8string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<object>);
}
@ -445,7 +445,7 @@ TEST(ObjectTest, basic_value_constructor_multiset) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<std::u8string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<object>);
}
@ -461,7 +461,7 @@ TEST(ObjectTest, basic_value_constructor_unordered_set) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<std::u8string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<object>);
}
@ -477,7 +477,7 @@ TEST(ObjectTest, basic_value_constructor_unordered_multiset) {
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<float>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<long double>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<std::string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<std::u8string>);
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<object>);
}
@ -502,18 +502,18 @@ TEST(ObjectTest, basic_set) {
OBJECT_BASIC_SET_TEST(obj, float);
OBJECT_BASIC_SET_TEST(obj, double);
OBJECT_BASIC_SET_TEST(obj, long_double_t);
OBJECT_BASIC_SET_TEST(obj, std::string);
OBJECT_BASIC_SET_TEST(obj, std::u8string);
OBJECT_BASIC_SET_TEST(obj, object::array_type);
// const char*
obj.set("");
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
obj.set(u8"");
EXPECT_TRUE(obj.has<std::u8string>());
EXPECT_EQ(obj.get<std::u8string>(), std::u8string{});
// std::string_view
obj.set(""sv);
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
// std::u8string_view
obj.set(u8""sv);
EXPECT_TRUE(obj.has<std::u8string>());
EXPECT_EQ(obj.get<std::u8string>(), std::u8string{});
}
TEST(ObjectTest, basic_set_vector) {
@ -530,7 +530,7 @@ TEST(ObjectTest, basic_set_vector) {
OBJECT_BASIC_SET_TEST(obj, std::vector<float>);
OBJECT_BASIC_SET_TEST(obj, std::vector<double>);
OBJECT_BASIC_SET_TEST(obj, std::vector<long double>);
OBJECT_BASIC_SET_TEST(obj, std::vector<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::vector<std::u8string>);
OBJECT_BASIC_SET_TEST(obj, std::vector<object>);
}
@ -548,7 +548,7 @@ TEST(ObjectTest, basic_set_list) {
OBJECT_BASIC_SET_TEST(obj, std::list<float>);
OBJECT_BASIC_SET_TEST(obj, std::list<double>);
OBJECT_BASIC_SET_TEST(obj, std::list<long double>);
OBJECT_BASIC_SET_TEST(obj, std::list<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::list<std::u8string>);
OBJECT_BASIC_SET_TEST(obj, std::list<object>);
}
@ -566,7 +566,7 @@ TEST(ObjectTest, basic_set_forward_list) {
OBJECT_BASIC_SET_TEST(obj, std::forward_list<float>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<double>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<long double>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<std::u8string>);
OBJECT_BASIC_SET_TEST(obj, std::forward_list<object>);
}
@ -584,7 +584,7 @@ TEST(ObjectTest, basic_set_set) {
OBJECT_BASIC_SET_TEST(obj, std::set<float>);
OBJECT_BASIC_SET_TEST(obj, std::set<double>);
OBJECT_BASIC_SET_TEST(obj, std::set<long double>);
OBJECT_BASIC_SET_TEST(obj, std::set<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::set<std::u8string>);
OBJECT_BASIC_SET_TEST(obj, std::set<object>);
}
@ -602,7 +602,7 @@ TEST(ObjectTest, basic_set_multiset) {
OBJECT_BASIC_SET_TEST(obj, std::multiset<float>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<double>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<long double>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<std::u8string>);
OBJECT_BASIC_SET_TEST(obj, std::multiset<object>);
}
@ -620,7 +620,7 @@ TEST(ObjectTest, basic_set_unordered_set) {
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<float>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<double>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<long double>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<std::u8string>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<object>);
}
@ -638,7 +638,7 @@ TEST(ObjectTest, basic_set_unordered_multiset) {
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<float>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<double>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<long double>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<std::string>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<std::u8string>);
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<object>);
}
@ -663,18 +663,18 @@ TEST(ObjectTest, basic_assignment_operator) {
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, float);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, double);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, long_double_t);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::string);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::u8string);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, object::array_type);
// const char*
obj = "";
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
obj = u8"";
EXPECT_TRUE(obj.has<std::u8string>());
EXPECT_EQ(obj.get<std::u8string>(), std::u8string{});
// std::string_view
obj = ""sv;
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), std::string{});
// std::u8string_view
obj = u8""sv;
EXPECT_TRUE(obj.has<std::u8string>());
EXPECT_EQ(obj.get<std::u8string>(), std::u8string{});
}
TEST(ObjectTest, basic_assignment_operator_vector) {
@ -691,7 +691,7 @@ TEST(ObjectTest, basic_assignment_operator_vector) {
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<std::u8string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<object>);
}
@ -709,7 +709,7 @@ TEST(ObjectTest, basic_assignment_operator_list) {
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<std::u8string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<object>);
}
@ -727,7 +727,7 @@ TEST(ObjectTest, basic_assignment_operator_forward_list) {
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<std::u8string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<object>);
}
@ -745,7 +745,7 @@ TEST(ObjectTest, basic_assignment_operator_set) {
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<std::u8string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<object>);
}
@ -763,7 +763,7 @@ TEST(ObjectTest, basic_assignment_operator_multiset) {
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<std::u8string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<object>);
}
@ -781,7 +781,7 @@ TEST(ObjectTest, basic_assignment_operator_unordered_set) {
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<std::u8string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<object>);
}
@ -799,7 +799,7 @@ TEST(ObjectTest, basic_assignment_operator_unordered_multiset) {
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<float>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<long double>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<std::string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<std::u8string>);
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<object>);
}
@ -808,17 +808,17 @@ TEST(ObjectTest, basic_assignment_operator_unordered_multiset) {
TEST(ObjectTest, basic_map_access_operator) {
object obj;
obj["test"] = 1234;
EXPECT_EQ(obj["test"].get<int>(), 1234);
EXPECT_EQ(obj["test2"].get<int>(), 0);
obj[u8"test"] = 1234;
EXPECT_EQ(obj[u8"test"].get<int>(), 1234);
EXPECT_EQ(obj[u8"test2"].get<int>(), 0);
obj["test"] = 4567;
EXPECT_EQ(obj["test"].get<int>(), 4567);
EXPECT_EQ(obj["test2"].get<int>(), 0);
obj[u8"test"] = 4567;
EXPECT_EQ(obj[u8"test"].get<int>(), 4567);
EXPECT_EQ(obj[u8"test2"].get<int>(), 0);
obj["test2"] = 1234;
EXPECT_EQ(obj["test"].get<int>(), 4567);
EXPECT_EQ(obj["test2"].get<int>(), 1234);
obj[u8"test2"] = 1234;
EXPECT_EQ(obj[u8"test"].get<int>(), 4567);
EXPECT_EQ(obj[u8"test2"].get<int>(), 1234);
}
TEST(ObjectTest, basic_array_access_operator) {
@ -914,31 +914,31 @@ TEST(ObjectTest, set_float) {
TEST(ObjectTest, set_string) {
object obj;
obj.set("Jessica");
obj.set(u8"Jessica");
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), "Jessica");
EXPECT_TRUE(obj.has<std::u8string>());
EXPECT_EQ(obj.get<std::u8string>(), u8"Jessica");
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set("was"s);
obj.set(u8"was"s);
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), "was");
EXPECT_TRUE(obj.has<std::u8string>());
EXPECT_EQ(obj.get<std::u8string>(), u8"was");
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set("here"sv);
obj.set(u8"here"sv);
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), "here");
EXPECT_TRUE(obj.has<std::u8string>());
EXPECT_EQ(obj.get<std::u8string>(), u8"here");
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
obj.set("");
obj.set(u8"");
EXPECT_TRUE(obj.has<std::string>());
EXPECT_EQ(obj.get<std::string>(), "");
EXPECT_TRUE(obj.has<std::u8string>());
EXPECT_EQ(obj.get<std::u8string>(), u8"");
EXPECT_FALSE(obj.has<bool>());
EXPECT_FALSE(obj.get<bool>());
}

21
src/test/parser.cpp

@ -20,6 +20,7 @@
#include "test.hpp"
#include "jessilib/parser.hpp"
#include "jessilib/serialize.hpp"
#include "jessilib/unicode.hpp"
using namespace jessilib;
using namespace std::literals;
@ -45,15 +46,15 @@ public:
/** default serialize/deserialize implementations */
static std::string serialize_default(const object& in_object) {
if (in_object.has<std::string>()) {
return in_object.get<std::string>();
if (in_object.has<std::u8string>()) {
return string_cast<char>(in_object.get<std::u8string>());
}
return static_cast<std::string>(DEFAULT_SERIALIZE_RESULT);
}
static object deserialize_default(std::string_view in_data) {
return object{ in_data };
return object{ string_view_cast<char8_t>(in_data) };
}
/** static members */
@ -82,31 +83,31 @@ class ParserTest : public base_test {
/** Parser tests */
TEST_F(ParserTest, find_parser) {
EXPECT_NO_THROW(serialize_object("test_data", "test"));
EXPECT_NO_THROW(serialize_object(u8"test_data", "test"));
EXPECT_NO_THROW(deserialize_object("test_data"sv, "test"));
EXPECT_THROW(serialize_object("test_data", "invalid_format_test"), format_not_available);
EXPECT_THROW(serialize_object(u8"test_data", "invalid_format_test"), format_not_available);
EXPECT_THROW(deserialize_object("test_data"sv, "invalid_format_test"), format_not_available);
}
TEST_F(ParserTest, temp_parser) {
EXPECT_THROW(serialize_object("test_data", "test_tmp"), format_not_available);
EXPECT_THROW(serialize_object(u8"test_data", "test_tmp"), format_not_available);
EXPECT_THROW(deserialize_object("test_data"sv, "test_tmp"), format_not_available);
{
parser_registration<test_parser> test_tmp_registration{ "test_tmp" };
EXPECT_NO_THROW(serialize_object("test_data", "test_tmp"));
EXPECT_NO_THROW(serialize_object(u8"test_data", "test_tmp"));
EXPECT_NO_THROW(deserialize_object("test_data"sv, "test_tmp"));
}
EXPECT_THROW(serialize_object("test_data", "test_tmp"), format_not_available);
EXPECT_THROW(serialize_object(u8"test_data", "test_tmp"), format_not_available);
EXPECT_THROW(deserialize_object("test_data"sv, "test_tmp"), format_not_available);
}
TEST_F(ParserTest, serialize) {
EXPECT_EQ(serialize_object("test_data", "test"), "test_data");
EXPECT_EQ(serialize_object(u8"test_data", "test"), "test_data");
}
TEST_F(ParserTest, deserialize) {
EXPECT_EQ(deserialize_object("test_data"sv, "test").get<std::string>(), "test_data");
EXPECT_EQ(deserialize_object("test_data"sv, "test").get<std::u8string>(), u8"test_data");
}

67
src/test/parsers/json.cpp

@ -56,9 +56,10 @@ void expect_eq(LeftT in_left, RightT in_right) {
TEST(JsonParser, serialize_string) {
json_parser parser;
EXPECT_EQ(parser.serialize("text"), R"json("text")json");
expect_eq(parser.serialize("\"text\""), R"json("\"text\"")json");
expect_eq(parser.serialize("\"te\x10xt\""), R"json("\"te\u0010xt\"")json");
EXPECT_EQ(parser.serialize(u8"text"), R"json("text")json");
expect_eq(parser.serialize(u8"\"text\""), R"json("\"text\"")json");
expect_eq(parser.serialize(u8"\"te\x01xt\""), R"json("\"te\u0001xt\"")json");
expect_eq(parser.serialize(u8"\"te\x10xt\""), R"json("\"te\u0010xt\"")json");
}
TEST(JsonParser, serialize_array) {
@ -66,7 +67,7 @@ TEST(JsonParser, serialize_array) {
std::vector<object> array {
true,
1234,
"text",
u8"text",
object{}
};
@ -78,10 +79,10 @@ TEST(JsonParser, serialize_map) {
json_parser parser;
object obj;
obj["some_bool"] = true;
obj["some_int"] = 1234;
obj["some_string"] = "text";
obj["some_null"];
obj[u8"some_bool"] = true;
obj[u8"some_int"] = 1234;
obj[u8"some_string"] = u8"text";
obj[u8"some_null"];
EXPECT_EQ(parser.serialize(obj),
R"json({"some_bool":true,"some_int":1234,"some_null":null,"some_string":"text"})json");
@ -120,7 +121,7 @@ TEST(JsonParser, deserialize_decimal) {
TEST(JsonParser, deserialize_string) {
json_parser parser;
EXPECT_EQ(parser.deserialize(R"json("text")json"sv), "text");
EXPECT_EQ(parser.deserialize(R"json("text")json"sv), u8"text");
}
TEST(JsonParser, deserialize_array) {
@ -142,7 +143,7 @@ TEST(JsonParser, deserialize_array) {
EXPECT_EQ(array[2], 1234);
EXPECT_DOUBLE_EQ(array[3].get<double>(), 12.34);
EXPECT_DOUBLE_EQ(array[4].get<double>(), 0.1234);
EXPECT_EQ(array[5], "text");
EXPECT_EQ(array[5], u8"text");
}
TEST(JsonParser, deserialize_array_nested) {
@ -174,11 +175,11 @@ TEST(JsonParser, deserialize_array_nested) {
EXPECT_EQ(array[4].size(), 0U);
EXPECT_FALSE(array[5].null());
ASSERT_EQ(array[5].size(), 1U);
EXPECT_EQ(array[5], std::vector<object>{ " text " });
EXPECT_EQ(array[5], std::vector<std::string>{ " text " });
EXPECT_EQ(array[5], std::vector<object>{ u8" text " });
EXPECT_EQ(array[5], std::vector<std::u8string>{ u8" text " });
EXPECT_DOUBLE_EQ(array[6].get<double>(), 12.34);
EXPECT_DOUBLE_EQ(array[7].get<double>(), 0.1234);
EXPECT_EQ(array[8], "text");
EXPECT_EQ(array[8], u8"text");
auto nested_array = array[3].get<std::vector<object>>();
ASSERT_EQ(nested_array.size(), 6U);
@ -186,7 +187,7 @@ TEST(JsonParser, deserialize_array_nested) {
EXPECT_EQ(nested_array[1], 2);
EXPECT_EQ(nested_array[2], 3);
EXPECT_TRUE(nested_array[3].null());
EXPECT_EQ(nested_array[4], "text");
EXPECT_EQ(nested_array[4],u8"text");
std::vector<int> expected{ 5, 6, 7 };
EXPECT_EQ(nested_array[5], expected);
}
@ -205,12 +206,12 @@ TEST(JsonParser, deserialize_map) {
object obj = parser.deserialize(json_data);
EXPECT_EQ(obj.size(), 6U);
EXPECT_EQ(obj["some_true"], true);
EXPECT_EQ(obj["some_false"], false);
EXPECT_EQ(obj["some_int"], 1234);
EXPECT_DOUBLE_EQ(obj["some_double"].get<double>(), 12.34);
EXPECT_DOUBLE_EQ(obj["some_other_double"].get<double>(), 0.1234);
EXPECT_EQ(obj["some_text"], "text");
EXPECT_EQ(obj[u8"some_true"], true);
EXPECT_EQ(obj[u8"some_false"], false);
EXPECT_EQ(obj[u8"some_int"], 1234);
EXPECT_DOUBLE_EQ(obj[u8"some_double"].get<double>(), 12.34);
EXPECT_DOUBLE_EQ(obj[u8"some_other_double"].get<double>(), 0.1234);
EXPECT_EQ(obj[u8"some_text"], u8"text");
}
TEST(JsonParser, deserialize_map_nested) {
@ -233,21 +234,21 @@ TEST(JsonParser, deserialize_map_nested) {
object obj = parser.deserialize(json_data);
EXPECT_EQ(obj.size(), 4U);
EXPECT_EQ(obj["some_text"], "text");
EXPECT_EQ(obj["some other text"], " asdf ");
EXPECT_EQ(obj[u8"some_text"], u8"text");
EXPECT_EQ(obj[u8"some other text"], u8" asdf ");
// some_object
EXPECT_FALSE(obj["some_object"].null());
EXPECT_EQ(obj["some_object"].size(), 1U);
EXPECT_FALSE(obj["some_object"]["some_null_object"].null());
EXPECT_EQ(obj["some_object"]["some_null_object"].size(), 0U);
EXPECT_FALSE(obj[u8"some_object"].null());
EXPECT_EQ(obj[u8"some_object"].size(), 1U);
EXPECT_FALSE(obj[u8"some_object"][u8"some_null_object"].null());
EXPECT_EQ(obj[u8"some_object"][u8"some_null_object"].size(), 0U);
// some_other_object
EXPECT_FALSE(obj["some_other_object"].null());
EXPECT_EQ(obj["some_other_object"].size(), 1U);
EXPECT_FALSE(obj["some_other_object"]["beans"].null());
EXPECT_EQ(obj["some_other_object"]["beans"].size(), 3U);
EXPECT_EQ(obj["some_other_object"]["beans"]["fruit"], true);
EXPECT_EQ(obj["some_other_object"]["beans"]["magical"], true);
EXPECT_EQ(obj["some_other_object"]["beans"]["makes toot"], true);
EXPECT_FALSE(obj[u8"some_other_object"].null());
EXPECT_EQ(obj[u8"some_other_object"].size(), 1U);
EXPECT_FALSE(obj[u8"some_other_object"][u8"beans"].null());
EXPECT_EQ(obj[u8"some_other_object"][u8"beans"].size(), 3U);
EXPECT_EQ(obj[u8"some_other_object"][u8"beans"][u8"fruit"], true);
EXPECT_EQ(obj[u8"some_other_object"][u8"beans"][u8"magical"], true);
EXPECT_EQ(obj[u8"some_other_object"][u8"beans"][u8"makes toot"], true);
}

Loading…
Cancel
Save