mirror of https://github.com/JAJames/jessilib.git
Jessica James
6 years ago
16 changed files with 2351 additions and 13 deletions
@ -0,0 +1,147 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#include "config.hpp" |
||||
|
#include <cstring> |
||||
|
#include <fstream> |
||||
|
#include "assert.hpp" |
||||
|
#include "serialize.hpp" |
||||
|
|
||||
|
namespace jessilib { |
||||
|
|
||||
|
/** Error types */ |
||||
|
|
||||
|
config::file_error::file_error() |
||||
|
: std::runtime_error{ std::strerror(errno) } { |
||||
|
// Empty ctor body
|
||||
|
} |
||||
|
|
||||
|
config::file_error::file_error(const std::filesystem::path& in_filename) |
||||
|
: std::runtime_error{ "Error openening file \"" + std::string{ in_filename } + "\". Error: " + std::strerror(errno) } { |
||||
|
// Empty ctor body
|
||||
|
}; |
||||
|
|
||||
|
/** config */ |
||||
|
|
||||
|
object config::data() const { |
||||
|
std::shared_lock<std::shared_mutex> guard{ m_mutex }; |
||||
|
return m_data; |
||||
|
} |
||||
|
|
||||
|
std::filesystem::path config::filename() const { |
||||
|
std::shared_lock<std::shared_mutex> guard{ m_mutex }; |
||||
|
return m_filename; |
||||
|
} |
||||
|
|
||||
|
std::string config::format() const { |
||||
|
std::shared_lock<std::shared_mutex> guard{ m_mutex }; |
||||
|
return m_format; |
||||
|
} |
||||
|
|
||||
|
/** Modifiers */ |
||||
|
void config::set_data(const object& in_data) { |
||||
|
std::lock_guard<std::shared_mutex> guard{ m_mutex }; |
||||
|
m_data = in_data; |
||||
|
} |
||||
|
|
||||
|
/** File I/O */ |
||||
|
void config::load(const std::filesystem::path& in_filename, const std::string& in_format) { |
||||
|
jessilib_assert(!in_filename.empty()); |
||||
|
std::lock_guard<std::shared_mutex> guard{ m_mutex }; |
||||
|
|
||||
|
// Determine format
|
||||
|
m_filename = in_filename; |
||||
|
m_format = get_format(m_filename, in_format); |
||||
|
|
||||
|
// Load
|
||||
|
m_data = read_object(m_filename, m_format); |
||||
|
} |
||||
|
|
||||
|
void config::reload() { |
||||
|
std::lock_guard<std::shared_mutex> guard{ m_mutex }; |
||||
|
|
||||
|
if (jessilib_debug_assert(!m_filename.empty()) |
||||
|
&& jessilib_debug_assert(!m_format.empty())) { |
||||
|
// Load data from disk
|
||||
|
m_data = read_object(m_filename, m_format); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void config::write() const { |
||||
|
std::shared_lock<std::shared_mutex> guard{ m_mutex }; |
||||
|
|
||||
|
if (jessilib_debug_assert(!m_filename.empty()) |
||||
|
&& jessilib_debug_assert(!m_format.empty())) { |
||||
|
// Write data to disk
|
||||
|
write_object(m_data, m_filename, m_format); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void config::write(const std::filesystem::path& in_filename , const std::string& in_format) { |
||||
|
jessilib_assert(!in_filename.empty()); |
||||
|
std::lock_guard<std::shared_mutex> guard{ m_mutex }; |
||||
|
|
||||
|
// Setup
|
||||
|
m_filename = in_filename; |
||||
|
m_format = get_format(m_filename, in_format); |
||||
|
|
||||
|
// Write
|
||||
|
write_object(m_data, m_filename, m_format); |
||||
|
} |
||||
|
|
||||
|
/** Static File I/O */ |
||||
|
object config::read_object(const std::filesystem::path& in_filename, const std::string& in_format) { |
||||
|
// Open up file for reading
|
||||
|
std::ifstream file{ in_filename, std::ios::in | std::ios::binary }; |
||||
|
if (!file) { |
||||
|
// Failed to open the file; throw file_error
|
||||
|
throw file_error( in_filename ); |
||||
|
} |
||||
|
|
||||
|
// Deserialize1
|
||||
|
return deserialize_object(file, in_format); |
||||
|
} |
||||
|
|
||||
|
void config::write_object(const object& in_object, const std::filesystem::path& in_filename, const std::string& in_format) { |
||||
|
// Open up file for writing
|
||||
|
std::ofstream file{ in_filename, std::ios::out | std::ios::binary }; |
||||
|
if (!file) { |
||||
|
// Failed to open the file; throw file_error
|
||||
|
throw file_error( in_filename ); |
||||
|
} |
||||
|
|
||||
|
// Deserialize1
|
||||
|
return serialize_object(file, in_object, in_format); |
||||
|
} |
||||
|
|
||||
|
std::string get_format(const std::filesystem::path& in_filename, const std::string& in_format) { |
||||
|
if (!in_format.empty()) { |
||||
|
// Use specified format
|
||||
|
return in_format; |
||||
|
} |
||||
|
|
||||
|
// Try to determine format from filename
|
||||
|
std::string extension = in_filename.extension(); |
||||
|
if jessilib_assert(!extension.empty()) { |
||||
|
return extension.substr(1); |
||||
|
} |
||||
|
|
||||
|
return extension; |
||||
|
} |
||||
|
|
||||
|
} // namespace jessilib
|
@ -0,0 +1,102 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#include "object.hpp" |
||||
|
|
||||
|
namespace jessilib { |
||||
|
|
||||
|
object::object(const object& in_object) { |
||||
|
m_value = in_object.m_value; |
||||
|
} |
||||
|
|
||||
|
object::object(object&& in_object) { |
||||
|
m_value = std::move(in_object.m_value); |
||||
|
} |
||||
|
|
||||
|
object::object(const char* in_str) |
||||
|
: m_value{ std::string{ in_str } } { |
||||
|
// Empty ctor body
|
||||
|
} |
||||
|
|
||||
|
object::object(const std::string_view& in_str) |
||||
|
: m_value{ std::string{ in_str.begin(), in_str.end() } } { |
||||
|
// Empty ctor body
|
||||
|
} |
||||
|
|
||||
|
/** Accessors */ |
||||
|
|
||||
|
bool object::null() const { |
||||
|
// There's something funny about variants holding nullptr_t
|
||||
|
return std::holds_alternative<nullptr_t>(m_value); |
||||
|
} |
||||
|
|
||||
|
size_t object::size() const { |
||||
|
// If we're null, we don't have any members
|
||||
|
if (null()) { |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
// Try array
|
||||
|
{ |
||||
|
const array_t* array = std::get_if<array_t>(&m_value); |
||||
|
if (array != nullptr) { |
||||
|
return array->size(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Try map
|
||||
|
{ |
||||
|
const map_t* map = std::get_if<map_t>(&m_value); |
||||
|
if (map != nullptr) { |
||||
|
return map->size(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// We're a single value
|
||||
|
return 1; |
||||
|
} |
||||
|
|
||||
|
const object& object::operator[](const std::string& in_key) const { |
||||
|
auto result = std::get_if<map_t>(&m_value); |
||||
|
if (result != nullptr) { |
||||
|
auto itr = result->find(in_key); |
||||
|
if (itr != result->end()) { |
||||
|
return itr->second; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static const object s_null_object; |
||||
|
return s_null_object; |
||||
|
} |
||||
|
|
||||
|
object& object::operator[](const std::string& in_key) { |
||||
|
if (null()) { |
||||
|
return m_value.emplace<map_t>()[in_key]; |
||||
|
} |
||||
|
|
||||
|
auto result = std::get_if<map_t>(&m_value); |
||||
|
if (result != nullptr) { |
||||
|
return result->operator[](in_key); |
||||
|
} |
||||
|
|
||||
|
static thread_local object s_null_object; |
||||
|
s_null_object.m_value.emplace<nullptr_t>(); |
||||
|
return s_null_object; |
||||
|
} |
||||
|
|
||||
|
} // namespace jessilib
|
@ -0,0 +1,42 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#include "parser.hpp" |
||||
|
#include <istream> |
||||
|
|
||||
|
namespace jessilib { |
||||
|
|
||||
|
object parser::deserialize(std::istream& in_stream) { |
||||
|
std::vector<char> data; |
||||
|
|
||||
|
// Read entire stream into data
|
||||
|
char buffer[1024]; |
||||
|
while(!in_stream.eof()) { |
||||
|
in_stream.read(buffer, sizeof(buffer)); |
||||
|
data.insert(data.end(), buffer, buffer + in_stream.gcount()); |
||||
|
} |
||||
|
|
||||
|
// Pass data to deserialize
|
||||
|
return deserialize(std::string_view{ &data.front(), data.size() }); |
||||
|
} |
||||
|
|
||||
|
void parser::serialize(std::ostream& in_stream, const object& in_object) { |
||||
|
in_stream << serialize(in_object); |
||||
|
} |
||||
|
|
||||
|
} // namespace jessilib
|
@ -0,0 +1,121 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#include "impl/parser_manager.hpp" |
||||
|
#include "parser.hpp" |
||||
|
#include "assert.hpp" |
||||
|
|
||||
|
namespace jessilib { |
||||
|
namespace impl { |
||||
|
|
||||
|
parser_manager::registration::registration(id in_id) |
||||
|
: m_id{ in_id } { |
||||
|
// Empty ctor body
|
||||
|
} |
||||
|
|
||||
|
parser_manager::registration::registration(const std::string& in_format) |
||||
|
: m_format{ in_format } { |
||||
|
// Empty ctor body
|
||||
|
} |
||||
|
|
||||
|
parser_manager::registration::registration(id in_id, const std::string& in_format) |
||||
|
: m_id{ in_id }, |
||||
|
m_format{ in_format } { |
||||
|
// Empty ctor body
|
||||
|
} |
||||
|
|
||||
|
bool parser_manager::registration::operator<(const registration& rhs) const { |
||||
|
if (m_id != 0 && rhs.m_id) { |
||||
|
// Both registrations have an ID; this is a search by ID
|
||||
|
return m_id < rhs.m_id; |
||||
|
} |
||||
|
|
||||
|
// One of the registrations lacked an ID; this must be a search by format
|
||||
|
return m_format < rhs.m_format; |
||||
|
} |
||||
|
|
||||
|
parser_manager::id parser_manager::register_parser(std::shared_ptr<parser> in_parser, const std::string& in_format, bool in_force) { |
||||
|
std::lock_guard<std::shared_mutex> guard{ m_mutex }; |
||||
|
|
||||
|
// Check for any existing parser
|
||||
|
auto itr = m_parsers.find(in_format); |
||||
|
if (itr != m_parsers.end()) { |
||||
|
// A parser already exists; return or replace
|
||||
|
if (!in_force) { |
||||
|
return bad_id; |
||||
|
} |
||||
|
|
||||
|
// Remove existing parser and registration
|
||||
|
m_parsers.erase(itr); |
||||
|
m_registrations.erase(registration{ in_format }); |
||||
|
} |
||||
|
|
||||
|
// Register our new parser
|
||||
|
id parser_id = ++m_last_id; |
||||
|
m_parsers.emplace(in_format, in_parser); |
||||
|
m_registrations.emplace(parser_id, in_format); |
||||
|
|
||||
|
// Our parser is registered; return the parser ID we just registered
|
||||
|
return parser_id; |
||||
|
} |
||||
|
|
||||
|
void parser_manager::unregister_parser(id in_id) { |
||||
|
std::lock_guard<std::shared_mutex> guard{ m_mutex }; |
||||
|
|
||||
|
// Search for registration
|
||||
|
auto itr = m_registrations.find(registration{ in_id }); |
||||
|
if (itr == m_registrations.end()) { |
||||
|
// Parser already unregistered; do nothing
|
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// Unregister
|
||||
|
registration removed_registration = *itr; |
||||
|
m_registrations.erase(itr); |
||||
|
m_parsers.erase(removed_registration.m_format); |
||||
|
} |
||||
|
|
||||
|
std::shared_ptr<parser> parser_manager::find_parser(const std::string& in_format) { |
||||
|
std::shared_lock<std::shared_mutex> guard{ m_mutex }; |
||||
|
|
||||
|
// Search for the parser by key
|
||||
|
auto itr = m_parsers.find(in_format); |
||||
|
if (itr != m_parsers.end()) { |
||||
|
// Found our parser; return
|
||||
|
return itr->second; |
||||
|
} |
||||
|
|
||||
|
// No parser exists for the given format
|
||||
|
return nullptr; |
||||
|
} |
||||
|
|
||||
|
void parser_manager::clear() { |
||||
|
std::lock_guard<std::shared_mutex> guard{ m_mutex }; |
||||
|
|
||||
|
m_parsers.clear(); |
||||
|
m_registrations.clear(); |
||||
|
} |
||||
|
|
||||
|
/** Singleton */ |
||||
|
parser_manager& parser_manager::instance() { |
||||
|
static parser_manager s_parser_manager{}; |
||||
|
return s_parser_manager; |
||||
|
} |
||||
|
|
||||
|
} // namespace jessilib
|
||||
|
} // namespace jessilib
|
@ -0,0 +1,69 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#include "serialize.hpp" |
||||
|
#include "impl/parser_manager.hpp" |
||||
|
#include "parser.hpp" |
||||
|
|
||||
|
namespace jessilib { |
||||
|
|
||||
|
/** Exception types */ |
||||
|
|
||||
|
format_not_available::format_not_available(const std::string& in_format) |
||||
|
: std::runtime_error{ "Format \"" + in_format + "\"not recognized" } { |
||||
|
// Empty ctor body
|
||||
|
}; |
||||
|
|
||||
|
/** Helpers */ |
||||
|
|
||||
|
std::shared_ptr<parser> get_parser(const std::string& in_format) { |
||||
|
auto parser = impl::parser_manager::instance().find_parser(in_format); |
||||
|
if (parser == nullptr) { |
||||
|
throw format_not_available{ in_format }; |
||||
|
} |
||||
|
|
||||
|
return parser; |
||||
|
} |
||||
|
|
||||
|
/** Deserialization */ |
||||
|
object deserialize_object(const std::string& in_data, const std::string& in_format) { |
||||
|
return deserialize_object(std::string_view{ &in_data.front(), in_data.size() }, in_format); |
||||
|
} |
||||
|
|
||||
|
object deserialize_object(const std::vector<char>& in_data, const std::string& in_format) { |
||||
|
return deserialize_object(std::string_view{ &in_data.front(), in_data.size() }, in_format); |
||||
|
} |
||||
|
|
||||
|
object deserialize_object(std::string_view in_data, const std::string& in_format) { |
||||
|
return get_parser(in_format)->deserialize(in_data); |
||||
|
} |
||||
|
|
||||
|
object deserialize_object(std::istream& in_stream, const std::string& in_format) { |
||||
|
return get_parser(in_format)->deserialize(in_stream); |
||||
|
} |
||||
|
|
||||
|
/** Serialization */ |
||||
|
std::string serialize_object(const object& in_object, const std::string& in_format) { |
||||
|
return get_parser(in_format)->serialize(in_object); |
||||
|
} |
||||
|
|
||||
|
void serialize_object(std::ostream& in_stream, const object& in_object, const std::string& in_format) { |
||||
|
get_parser(in_format)->serialize(in_stream, in_object); |
||||
|
} |
||||
|
|
||||
|
} // namespace jessilib
|
@ -0,0 +1,68 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <vector> |
||||
|
#include <string> |
||||
|
#include <istream> |
||||
|
#include <filesystem> |
||||
|
#include <shared_mutex> |
||||
|
#include "object.hpp" |
||||
|
|
||||
|
namespace jessilib { |
||||
|
|
||||
|
class config { |
||||
|
public: |
||||
|
/** Types */ |
||||
|
|
||||
|
class file_error : public std::runtime_error { |
||||
|
public: |
||||
|
file_error(); |
||||
|
file_error(const std::filesystem::path& in_filename); |
||||
|
}; |
||||
|
|
||||
|
/** Accessors */ |
||||
|
object data() const; |
||||
|
std::filesystem::path filename() const; |
||||
|
std::string format() const; |
||||
|
|
||||
|
/** Modifiers */ |
||||
|
void set_data(const object& in_data); |
||||
|
|
||||
|
/** File I/O */ |
||||
|
void load(const std::filesystem::path& in_filename, const std::string& in_format = {}); |
||||
|
void reload(); |
||||
|
void write() const; |
||||
|
void write(const std::filesystem::path& in_filename , const std::string& in_format = {}); |
||||
|
|
||||
|
/** Static File I/O */ |
||||
|
static object read_object(const std::filesystem::path& in_filename, const std::string& in_format = {}); |
||||
|
static void write_object(const object& in_object, const std::filesystem::path& in_filename, const std::string& in_format = {}); |
||||
|
|
||||
|
/** Static helpers */ |
||||
|
static std::string get_format(const std::filesystem::path& in_filename, const std::string& in_format = {}); |
||||
|
|
||||
|
private: |
||||
|
mutable std::shared_mutex m_mutex; |
||||
|
object m_data; |
||||
|
std::string m_format; |
||||
|
std::filesystem::path m_filename; |
||||
|
}; |
||||
|
|
||||
|
} // namespace jessilib
|
@ -0,0 +1,77 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <cstdint> |
||||
|
#include <memory> |
||||
|
#include <unordered_map> |
||||
|
#include <set> |
||||
|
#include <shared_mutex> |
||||
|
|
||||
|
namespace jessilib { |
||||
|
|
||||
|
class parser; |
||||
|
|
||||
|
namespace impl { |
||||
|
|
||||
|
class parser_manager { |
||||
|
public: |
||||
|
/** Types */ |
||||
|
using id = size_t; |
||||
|
|
||||
|
/** Constants */ |
||||
|
static constexpr id bad_id = 0; |
||||
|
|
||||
|
/** Methods */ |
||||
|
id register_parser(std::shared_ptr<parser> in_parser, const std::string& in_format, bool in_force = false); |
||||
|
void unregister_parser(id in_id); |
||||
|
std::shared_ptr<parser> find_parser(const std::string& in_format); |
||||
|
void clear(); |
||||
|
|
||||
|
/** Singleton */ |
||||
|
static parser_manager& instance(); |
||||
|
|
||||
|
private: |
||||
|
class registration { |
||||
|
public: |
||||
|
registration() = default; |
||||
|
registration(const registration&) = default; |
||||
|
registration(registration&&) = default; |
||||
|
|
||||
|
explicit registration(id in_id); |
||||
|
explicit registration(const std::string& in_format); |
||||
|
registration(id in_id, const std::string& in_format); |
||||
|
|
||||
|
registration& operator=(const registration&) = default; |
||||
|
registration& operator=(registration&&) = default; |
||||
|
|
||||
|
bool operator<(const registration& rhs) const; |
||||
|
|
||||
|
id m_id{}; |
||||
|
std::string m_format; |
||||
|
}; |
||||
|
|
||||
|
std::shared_mutex m_mutex; |
||||
|
id m_last_id{}; |
||||
|
std::set<registration> m_registrations; // This set and map could be condensed into a bimap
|
||||
|
std::unordered_map<std::string, std::shared_ptr<parser>> m_parsers; |
||||
|
}; // parser_manager
|
||||
|
|
||||
|
} // namespace impl
|
||||
|
} // namespace jessilib
|
@ -0,0 +1,436 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <cstdint> |
||||
|
#include <string> |
||||
|
#include <vector> |
||||
|
#include <map> |
||||
|
#include <variant> |
||||
|
#include <utility> |
||||
|
#include "util.hpp" |
||||
|
|
||||
|
namespace jessilib { |
||||
|
|
||||
|
class object { |
||||
|
public: |
||||
|
using array_t = std::vector<object>; |
||||
|
using map_t = std::map<std::string, object>; |
||||
|
|
||||
|
/** is_backing */ |
||||
|
|
||||
|
template<typename T, typename enable = void> |
||||
|
struct is_backing { |
||||
|
static constexpr bool value = false; |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_backing<T, typename std::enable_if<std::is_same<T, bool>::value>::type> { |
||||
|
static constexpr bool value = true; |
||||
|
using type = bool; |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_backing<T, typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value>::type> { |
||||
|
static constexpr bool value = true; |
||||
|
using type = intmax_t; |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_backing<T, typename std::enable_if<std::is_floating_point<T>::value>::type> { |
||||
|
static constexpr bool value = true; |
||||
|
using type = long double; |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_backing<T, typename std::enable_if<std::is_same<T, std::string>::value>::type> { |
||||
|
static constexpr bool value = true; |
||||
|
using type = std::string; |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_backing<T, typename std::enable_if<is_sequence_container<T>::value>::type> { |
||||
|
static constexpr bool value = true; |
||||
|
using type = array_t; |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_backing<T, typename std::enable_if<std::is_same<T, map_t>::value>::type> { |
||||
|
static constexpr bool value = true; |
||||
|
using type = map_t; |
||||
|
}; |
||||
|
|
||||
|
// Standard constructors
|
||||
|
object() = default; |
||||
|
object(const object& in_config); |
||||
|
object(object&& in_config); |
||||
|
~object() = default; |
||||
|
|
||||
|
// Value constructors
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<is_backing<typename std::decay<T>::type>::value |
||||
|
&& !is_sequence_container<typename std::decay<T>::type>::value>::type* = nullptr> |
||||
|
object(T&& in_value) |
||||
|
: m_value{ typename is_backing<typename std::decay<T>::type>::type{ std::forward<T>(in_value) } } { |
||||
|
// Empty ctor body
|
||||
|
} |
||||
|
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<is_sequence_container<typename std::decay<T>::type>::value |
||||
|
&& !std::is_same<typename std::decay<T>::type, std::vector<bool>>::value>::type* = nullptr> |
||||
|
object(T&& in_value) |
||||
|
: m_value{ array_t{ in_value.begin(), in_value.end() } } { |
||||
|
// Empty ctor body
|
||||
|
} |
||||
|
|
||||
|
// std::vector<bool>
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_same<typename std::decay<T>::type, std::vector<bool>>::value>::type* = nullptr> |
||||
|
object(T&& in_value) |
||||
|
: m_value{ array_t{} } { |
||||
|
auto& array = std::get<array_t>(m_value); |
||||
|
array.reserve(in_value.size()); |
||||
|
|
||||
|
for (const auto& item : in_value) { |
||||
|
array.emplace_back(bool{item}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
object(const char* in_str); |
||||
|
object(const std::string_view& in_str); |
||||
|
|
||||
|
// Comparison operators
|
||||
|
bool operator==(const object& rhs) const { |
||||
|
return m_value == rhs.m_value; |
||||
|
} |
||||
|
|
||||
|
bool operator!=(const object& rhs) const { |
||||
|
return m_value != rhs.m_value; |
||||
|
} |
||||
|
|
||||
|
bool operator<(const object& rhs) const { |
||||
|
return m_value < rhs.m_value; |
||||
|
} |
||||
|
|
||||
|
bool operator>(const object& rhs) const { |
||||
|
return m_value > rhs.m_value; |
||||
|
} |
||||
|
|
||||
|
bool operator<=(const object& rhs) const { |
||||
|
return m_value <= rhs.m_value; |
||||
|
} |
||||
|
|
||||
|
bool operator>=(const object& rhs) const { |
||||
|
return m_value >= rhs.m_value; |
||||
|
} |
||||
|
|
||||
|
// Assignment operators
|
||||
|
object& operator=(const object& in_config) = default; |
||||
|
object& operator=(object&& in_config) = default; |
||||
|
|
||||
|
// Non-copy/move assignment operator; forwards to set()
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<!std::is_same<typename std::decay<T>::type, object>::value>::type* = nullptr> |
||||
|
object& operator=(T&& in) { |
||||
|
set(std::forward<T>(in)); |
||||
|
return *this; |
||||
|
} |
||||
|
|
||||
|
const object& operator[](const std::string& in_key) const; |
||||
|
object& operator[](const std::string& in_key); |
||||
|
|
||||
|
/** Accessors */ |
||||
|
|
||||
|
bool null() const; |
||||
|
size_t size() const; |
||||
|
|
||||
|
template<typename T> |
||||
|
bool has() const { |
||||
|
using backing_t = typename is_backing<T>::type; |
||||
|
return std::holds_alternative<backing_t>(m_value); |
||||
|
} |
||||
|
|
||||
|
/** arithmetic types (numbers, bool) */ |
||||
|
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr> |
||||
|
T get(T in_default_value = {}) const { |
||||
|
using backing_t = typename is_backing<T>::type; |
||||
|
|
||||
|
const backing_t* result = std::get_if<backing_t>(&m_value); |
||||
|
if (result != nullptr) { |
||||
|
return static_cast<T>(*result); |
||||
|
} |
||||
|
|
||||
|
return in_default_value; |
||||
|
} |
||||
|
|
||||
|
/** strings */ |
||||
|
|
||||
|
// TODO: support other basic_string types
|
||||
|
template<typename T, typename DefaultT = T, |
||||
|
typename std::enable_if<std::is_same<T, std::string>::value && std::is_convertible<typename std::decay<DefaultT>::type, T>::value>::type* = nullptr> |
||||
|
T get(DefaultT&& in_default_value = {}) const { |
||||
|
const std::string* result = std::get_if<std::string>(&m_value); |
||||
|
if (result != nullptr) { |
||||
|
return *result; |
||||
|
} |
||||
|
|
||||
|
return std::forward<DefaultT>(in_default_value); |
||||
|
} |
||||
|
|
||||
|
// TODO: support other basic_string_view types
|
||||
|
template<typename T, typename DefaultT = T, |
||||
|
typename std::enable_if<std::is_same<T, std::string>::value && std::is_same<typename std::decay<DefaultT>::type, std::string_view>::value>::type* = nullptr> |
||||
|
T get(DefaultT&& in_default_value) const { |
||||
|
const std::string* result = std::get_if<std::string>(&m_value); |
||||
|
if (result != nullptr) { |
||||
|
return *result; |
||||
|
} |
||||
|
|
||||
|
return { in_default_value.begin(), in_default_value.end() }; |
||||
|
} |
||||
|
|
||||
|
/** arrays */ |
||||
|
|
||||
|
// reference getter (array_t)
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_same<T, array_t>::value>::type* = nullptr> |
||||
|
const T& get(const T& in_default_value) const { |
||||
|
const array_t* result = std::get_if<array_t>(&m_value); |
||||
|
if (result != nullptr) { |
||||
|
return *result; |
||||
|
} |
||||
|
|
||||
|
return in_default_value; |
||||
|
} |
||||
|
|
||||
|
// copy getter (array_t)
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_same<T, array_t>::value>::type* = nullptr> |
||||
|
T get(T&& in_default_value = {}) const { |
||||
|
const array_t* result = std::get_if<array_t>(&m_value); |
||||
|
if (result != nullptr) { |
||||
|
return *result; |
||||
|
} |
||||
|
|
||||
|
return std::move(in_default_value); |
||||
|
} |
||||
|
|
||||
|
// conversion getter (non-array_t)
|
||||
|
template<typename T, typename DefaultT = T, |
||||
|
typename std::enable_if<is_sequence_container<T>::value && !std::is_same<T, array_t>::value && std::is_same<typename std::decay<DefaultT>::type, T>::value>::type* = nullptr> |
||||
|
T get(DefaultT&& in_default_value = {}) const { |
||||
|
using backing_t = typename is_sequence_container<T>::type; |
||||
|
|
||||
|
const array_t* array = std::get_if<array_t>(&m_value); |
||||
|
if (array != nullptr) { |
||||
|
T result; |
||||
|
// Expand capacity to fit values (if possible)
|
||||
|
if constexpr (is_vector<T>::value) { |
||||
|
result.reserve(array->size()); |
||||
|
} |
||||
|
|
||||
|
// Populate result from array
|
||||
|
if constexpr (is_forward_list<T>::value) { |
||||
|
// forward_list
|
||||
|
if constexpr (std::is_same<backing_t, class object>::value) { |
||||
|
// forward_list<object>
|
||||
|
result.insert_after(result.begin(), array->begin(), array->end()); |
||||
|
} |
||||
|
else { |
||||
|
for (auto itr = array->rend(); itr != array->rbegin(); ++itr) { |
||||
|
if (itr->has<backing_t>()) { |
||||
|
result.push_front(itr->get<backing_t>()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else if constexpr (is_set<T>::value || is_multiset<T>::value || is_unordered_set<T>::value || is_unordered_multiset<T>::value) { |
||||
|
// set, unordered_set, multiset, unordered_multiset
|
||||
|
if constexpr (std::is_same<backing_t, class object>::value) { |
||||
|
// <object>
|
||||
|
result.insert(array->begin(), array->end()); |
||||
|
} |
||||
|
else { |
||||
|
for (auto& object : *array) { |
||||
|
if (object.has<backing_t>()) { |
||||
|
result.insert(object.get<backing_t>()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else { |
||||
|
// vector, list, etc
|
||||
|
for (auto& object : *array) { |
||||
|
if constexpr (std::is_same<backing_t, class object>::value) { |
||||
|
// <object>
|
||||
|
result.push_back(object); |
||||
|
} |
||||
|
else if (object.has<backing_t>()) { |
||||
|
result.push_back(object.get<backing_t>()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
return std::forward<DefaultT>(in_default_value); |
||||
|
} |
||||
|
|
||||
|
/** maps */ |
||||
|
|
||||
|
// TODO: implement in a way that does not require exposing map_t
|
||||
|
|
||||
|
// reference getter (map_t)
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_same<T, map_t>::value>::type* = nullptr> |
||||
|
const T& get(const T& in_default_value) const { |
||||
|
const map_t* result = std::get_if<map_t>(&m_value); |
||||
|
if (result != nullptr) { |
||||
|
return *result; |
||||
|
} |
||||
|
|
||||
|
return in_default_value; |
||||
|
} |
||||
|
|
||||
|
// copy getter (map_t)
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_same<T, map_t>::value>::type* = nullptr> |
||||
|
T get(T&& in_default_value = {}) const { |
||||
|
const map_t* result = std::get_if<map_t>(&m_value); |
||||
|
if (result != nullptr) { |
||||
|
return *result; |
||||
|
} |
||||
|
|
||||
|
return std::move(in_default_value); |
||||
|
} |
||||
|
|
||||
|
// TODO: conversion getter (non-map_t, i.e: unordered_map)
|
||||
|
|
||||
|
/** set */ |
||||
|
|
||||
|
// arithmetic types
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr> |
||||
|
void set(T in_value) { |
||||
|
using backing_t = typename is_backing<T>::type; |
||||
|
|
||||
|
m_value.emplace<backing_t>(in_value); |
||||
|
} |
||||
|
|
||||
|
// string
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_convertible<typename std::decay<T>::type, std::string>::value>::type* = nullptr> |
||||
|
void set(T&& in_value) { |
||||
|
m_value.emplace<std::string>(std::forward<T>(in_value)); |
||||
|
} |
||||
|
|
||||
|
// string_view
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_same<T, std::string_view>::value>::type* = nullptr> |
||||
|
void set(const T& in_value) { |
||||
|
m_value.emplace<std::string>(in_value.begin(), in_value.end()); |
||||
|
} |
||||
|
|
||||
|
// array_t
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_same<typename std::decay<T>::type, array_t>::value>::type* = nullptr> |
||||
|
void set(T&& in_value) { |
||||
|
m_value.emplace<array_t>(std::forward<T>(in_value)); |
||||
|
} |
||||
|
|
||||
|
// is_sequence_container
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<is_sequence_container<typename std::decay<T>::type>::value |
||||
|
&& !std::is_same<typename std::decay<T>::type, array_t>::value |
||||
|
&& !std::is_same<typename std::decay<T>::type, std::vector<bool>>::value>::type* = nullptr> |
||||
|
void set(T&& in_value) { |
||||
|
m_value.emplace<array_t>(in_value.begin(), in_value.end()); |
||||
|
} |
||||
|
|
||||
|
// std::vector<bool>
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_same<typename std::decay<T>::type, std::vector<bool>>::value>::type* = nullptr> |
||||
|
void set(T&& in_value) { |
||||
|
auto& array = m_value.emplace<array_t>(); |
||||
|
array.reserve(in_value.size()); |
||||
|
|
||||
|
for (const auto& item : in_value) { |
||||
|
array.emplace_back(bool{item}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// object
|
||||
|
template<typename T, |
||||
|
typename std::enable_if<std::is_same<typename std::decay<T>::type, object>::value>::type* = nullptr> |
||||
|
void set(T&& in_value) { |
||||
|
operator=(std::forward<T>(in_value)); |
||||
|
} |
||||
|
|
||||
|
size_t hash() const { |
||||
|
return std::visit([this](auto&& value) -> size_t { |
||||
|
using T = typename std::decay<decltype(value)>::type; |
||||
|
|
||||
|
if constexpr (std::is_same<T, nullptr_t>::value) { |
||||
|
return 0; |
||||
|
} |
||||
|
else if constexpr (std::is_same<T, array_t>::value) { |
||||
|
size_t result{}; |
||||
|
for (auto& obj : value) { |
||||
|
result += obj.hash(); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
else if constexpr (std::is_same<T, map_t>::value) { |
||||
|
size_t result{}; |
||||
|
for (auto& pair : value) { |
||||
|
result += std::hash<std::string>{}(pair.first); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
else { |
||||
|
return std::hash<T>{}(std::forward<decltype(value)>(value)); |
||||
|
} |
||||
|
}, m_value); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
std::variant<nullptr_t, bool, intmax_t, long double, std::string, array_t, map_t> m_value; |
||||
|
}; // object
|
||||
|
|
||||
|
} // namespace jessilib
|
||||
|
|
||||
|
|
||||
|
namespace std { |
||||
|
|
||||
|
template<> |
||||
|
struct hash<jessilib::object> { |
||||
|
using argument_type = jessilib::object; |
||||
|
using result_type = size_t; |
||||
|
|
||||
|
result_type operator()(const argument_type& in_object) const noexcept { |
||||
|
return in_object.hash(); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
} // namepsace std
|
@ -0,0 +1,58 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <memory> |
||||
|
#include "object.hpp" |
||||
|
#include "impl/parser_manager.hpp" |
||||
|
|
||||
|
namespace jessilib { |
||||
|
|
||||
|
class parser { |
||||
|
public: |
||||
|
/** Interface methods */ |
||||
|
|
||||
|
/**
|
||||
|
* Deserializes an object directly from a stream |
||||
|
* May throw: invalid_argument |
||||
|
* |
||||
|
* @param in_stream Stream to deserialize object from |
||||
|
* @return A valid (possibly null) object |
||||
|
*/ |
||||
|
virtual object deserialize(std::istream& in_stream); |
||||
|
virtual object deserialize(std::string_view in_data) = 0; |
||||
|
virtual void serialize(std::ostream& in_stream, const object& in_object); |
||||
|
virtual std::string serialize(const object& in_object) = 0; |
||||
|
}; // parser
|
||||
|
|
||||
|
template<typename T> |
||||
|
class parser_registration { |
||||
|
public: |
||||
|
parser_registration(std::string in_format, bool in_force = false) { |
||||
|
m_id = impl::parser_manager::instance().register_parser(std::make_shared<T>(), in_format, in_force); |
||||
|
} |
||||
|
|
||||
|
~parser_registration() { |
||||
|
impl::parser_manager::instance().unregister_parser(m_id); |
||||
|
} |
||||
|
|
||||
|
impl::parser_manager::id m_id; |
||||
|
}; // parser_registration
|
||||
|
|
||||
|
} // namespace jessilib
|
@ -0,0 +1,41 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <istream> |
||||
|
#include "object.hpp" |
||||
|
|
||||
|
namespace jessilib { |
||||
|
|
||||
|
class format_not_available : public std::runtime_error { |
||||
|
public: |
||||
|
format_not_available(const std::string& in_format); |
||||
|
}; |
||||
|
|
||||
|
/** Deserialization */ |
||||
|
object deserialize_object(const std::string& in_data, const std::string& in_format); |
||||
|
object deserialize_object(const std::vector<char>& in_data, const std::string& in_format); |
||||
|
object deserialize_object(std::string_view in_data, const std::string& in_format); |
||||
|
object deserialize_object(std::istream& in_stream, const std::string& in_format); |
||||
|
|
||||
|
/** Serialization */ |
||||
|
std::string serialize_object(const object& in_object, const std::string& in_format); |
||||
|
void serialize_object(std::ostream& in_stream, const object& in_object, const std::string& in_format); |
||||
|
|
||||
|
} // namespace jessilib
|
@ -0,0 +1,215 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <cstddef> |
||||
|
#include <type_traits> |
||||
|
#include <vector> |
||||
|
#include <list> |
||||
|
#include <forward_list> |
||||
|
#include <set> |
||||
|
#include <unordered_set> |
||||
|
#include <map> |
||||
|
#include <unordered_map> |
||||
|
|
||||
|
/** Macros */ |
||||
|
|
||||
|
#define JESSILIB_FILENAME \ |
||||
|
(::jessilib::impl::filename_from_string(__FILE__)) |
||||
|
|
||||
|
namespace jessilib { |
||||
|
|
||||
|
/** is_vector */ |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_vector : std::false_type {}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_vector<std::vector<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
/** is_list */ |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_list : std::false_type {}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_list<std::list<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
/** is_forward_list */ |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_forward_list : std::false_type {}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_forward_list<std::forward_list<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
/** is_set */ |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_set : std::false_type {}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_set<std::set<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
/** is_multiset */ |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_multiset : std::false_type {}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_multiset<std::multiset<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
/** is_unordered_set */ |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_unordered_set : std::false_type {}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_unordered_set<std::unordered_set<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
/** is_unordered_set */ |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_unordered_multiset : std::false_type {}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_unordered_multiset<std::unordered_multiset<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
/** is_sequence_container */ |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_sequence_container : std::false_type {}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_sequence_container<std::vector<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_sequence_container<std::list<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_sequence_container<std::forward_list<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_sequence_container<std::set<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_sequence_container<std::multiset<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_sequence_container<std::unordered_set<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
template<typename T> |
||||
|
struct is_sequence_container<std::unordered_multiset<T>> { |
||||
|
using type = T; |
||||
|
static constexpr bool value{ true }; |
||||
|
constexpr operator bool() const noexcept { return true; } |
||||
|
constexpr bool operator()() const noexcept { return true; } |
||||
|
}; |
||||
|
|
||||
|
/** Implementation details */ |
||||
|
|
||||
|
|
||||
|
namespace impl { |
||||
|
|
||||
|
template<size_t in_filename_length> |
||||
|
constexpr const char* filename_from_string(const char (&in_filename)[in_filename_length]) { |
||||
|
const char* filename_itr = in_filename; |
||||
|
const char* filename_end = filename_itr + in_filename_length; |
||||
|
const char* result = filename_itr; |
||||
|
|
||||
|
while (filename_itr != filename_end) { |
||||
|
if (*filename_itr == '/' || *filename_itr == '\\') { |
||||
|
++filename_itr; |
||||
|
result = filename_itr; |
||||
|
} |
||||
|
else { |
||||
|
++filename_itr; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
} // namespace impl
|
||||
|
} // namespace jessilib
|
@ -0,0 +1,932 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#include <chrono> |
||||
|
#include "test.hpp" |
||||
|
#include "object.hpp" |
||||
|
|
||||
|
using namespace jessilib; |
||||
|
using namespace std::literals; |
||||
|
|
||||
|
void object_compilation_test() { |
||||
|
object config {}; |
||||
|
|
||||
|
// Map accessor
|
||||
|
config["bob"]["builder"].get<std::string>(""s); |
||||
|
config["bob"]["builder"] = "whatever"; |
||||
|
} |
||||
|
|
||||
|
using signed_char_t = signed char; |
||||
|
using unsigned_char_t = unsigned char; |
||||
|
using long_long_t = long long; |
||||
|
using long_double_t = long double; |
||||
|
|
||||
|
/** basic tests; these test function calls against null objects and heavily test for compilation errors */ |
||||
|
|
||||
|
TEST(ObjectTest, basic) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_TRUE(obj.null()); |
||||
|
EXPECT_EQ(obj.size(), 0U); |
||||
|
} |
||||
|
|
||||
|
/** basic_has tests */ |
||||
|
|
||||
|
TEST(ObjectTest, basic_has) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.has<signed char>()); |
||||
|
EXPECT_FALSE(obj.has<unsigned char>()); |
||||
|
EXPECT_FALSE(obj.has<short>()); |
||||
|
EXPECT_FALSE(obj.has<int>()); |
||||
|
EXPECT_FALSE(obj.has<long>()); |
||||
|
EXPECT_FALSE(obj.has<long long>()); |
||||
|
EXPECT_FALSE(obj.has<intmax_t>()); |
||||
|
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<object::array_t>()); |
||||
|
EXPECT_FALSE(obj.has<object::map_t>()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_has_vector) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_FALSE(obj.has<std::vector<bool>>()); |
||||
|
EXPECT_FALSE(obj.has<std::vector<signed char>>()); |
||||
|
EXPECT_FALSE(obj.has<std::vector<unsigned char>>()); |
||||
|
EXPECT_FALSE(obj.has<std::vector<short>>()); |
||||
|
EXPECT_FALSE(obj.has<std::vector<int>>()); |
||||
|
EXPECT_FALSE(obj.has<std::vector<long>>()); |
||||
|
EXPECT_FALSE(obj.has<std::vector<long long>>()); |
||||
|
EXPECT_FALSE(obj.has<std::vector<intmax_t>>()); |
||||
|
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<object>>()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_has_list) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_FALSE(obj.has<std::list<bool>>()); |
||||
|
EXPECT_FALSE(obj.has<std::list<signed char>>()); |
||||
|
EXPECT_FALSE(obj.has<std::list<unsigned char>>()); |
||||
|
EXPECT_FALSE(obj.has<std::list<short>>()); |
||||
|
EXPECT_FALSE(obj.has<std::list<int>>()); |
||||
|
EXPECT_FALSE(obj.has<std::list<long>>()); |
||||
|
EXPECT_FALSE(obj.has<std::list<long long>>()); |
||||
|
EXPECT_FALSE(obj.has<std::list<intmax_t>>()); |
||||
|
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<object>>()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_has_forward_list) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_FALSE(obj.has<std::forward_list<bool>>()); |
||||
|
EXPECT_FALSE(obj.has<std::forward_list<signed char>>()); |
||||
|
EXPECT_FALSE(obj.has<std::forward_list<unsigned char>>()); |
||||
|
EXPECT_FALSE(obj.has<std::forward_list<short>>()); |
||||
|
EXPECT_FALSE(obj.has<std::forward_list<int>>()); |
||||
|
EXPECT_FALSE(obj.has<std::forward_list<long>>()); |
||||
|
EXPECT_FALSE(obj.has<std::forward_list<long long>>()); |
||||
|
EXPECT_FALSE(obj.has<std::forward_list<intmax_t>>()); |
||||
|
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<object>>()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_has_set) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_FALSE(obj.has<std::set<bool>>()); |
||||
|
EXPECT_FALSE(obj.has<std::set<signed char>>()); |
||||
|
EXPECT_FALSE(obj.has<std::set<unsigned char>>()); |
||||
|
EXPECT_FALSE(obj.has<std::set<short>>()); |
||||
|
EXPECT_FALSE(obj.has<std::set<int>>()); |
||||
|
EXPECT_FALSE(obj.has<std::set<long>>()); |
||||
|
EXPECT_FALSE(obj.has<std::set<long long>>()); |
||||
|
EXPECT_FALSE(obj.has<std::set<intmax_t>>()); |
||||
|
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<object>>()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_has_unordered_set) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_FALSE(obj.has<std::unordered_set<bool>>()); |
||||
|
EXPECT_FALSE(obj.has<std::unordered_set<signed char>>()); |
||||
|
EXPECT_FALSE(obj.has<std::unordered_set<unsigned char>>()); |
||||
|
EXPECT_FALSE(obj.has<std::unordered_set<short>>()); |
||||
|
EXPECT_FALSE(obj.has<std::unordered_set<int>>()); |
||||
|
EXPECT_FALSE(obj.has<std::unordered_set<long>>()); |
||||
|
EXPECT_FALSE(obj.has<std::unordered_set<long long>>()); |
||||
|
EXPECT_FALSE(obj.has<std::unordered_set<intmax_t>>()); |
||||
|
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<object>>()); |
||||
|
} |
||||
|
|
||||
|
/** basic_get tests */ |
||||
|
|
||||
|
TEST(ObjectTest, basic_get) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_EQ(obj.get<bool>(), bool{}); |
||||
|
EXPECT_EQ(obj.get<signed char>(), signed_char_t{}); |
||||
|
EXPECT_EQ(obj.get<unsigned char>(), unsigned_char_t{}); |
||||
|
EXPECT_EQ(obj.get<short>(), short{}); |
||||
|
EXPECT_EQ(obj.get<int>(), int{}); |
||||
|
EXPECT_EQ(obj.get<long>(), long{}); |
||||
|
EXPECT_EQ(obj.get<long long>(), long_long_t{}); |
||||
|
EXPECT_EQ(obj.get<intmax_t>(), intmax_t{}); |
||||
|
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_TRUE(obj.get<object::array_t>().empty()); |
||||
|
EXPECT_TRUE(obj.get<object::map_t>().empty()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_get_vector) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_TRUE(obj.get<std::vector<bool>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::vector<signed char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::vector<unsigned char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::vector<short>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::vector<int>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::vector<long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::vector<long long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::vector<intmax_t>>().empty()); |
||||
|
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<object>>().empty()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_get_list) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_TRUE(obj.get<std::list<bool>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::list<signed char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::list<unsigned char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::list<short>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::list<int>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::list<long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::list<long long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::list<intmax_t>>().empty()); |
||||
|
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<object>>().empty()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_get_forward_list) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_TRUE(obj.get<std::forward_list<bool>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::forward_list<signed char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::forward_list<unsigned char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::forward_list<short>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::forward_list<int>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::forward_list<long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::forward_list<long long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::forward_list<intmax_t>>().empty()); |
||||
|
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<object>>().empty()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_get_set) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_TRUE(obj.get<std::set<bool>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::set<signed char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::set<unsigned char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::set<short>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::set<int>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::set<long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::set<long long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::set<intmax_t>>().empty()); |
||||
|
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<object>>().empty()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_get_multiset) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_TRUE(obj.get<std::multiset<bool>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::multiset<signed char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::multiset<unsigned char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::multiset<short>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::multiset<int>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::multiset<long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::multiset<long long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::multiset<intmax_t>>().empty()); |
||||
|
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<object>>().empty()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_get_unordered_set) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_TRUE(obj.get<std::unordered_set<bool>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_set<signed char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_set<unsigned char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_set<short>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_set<int>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_set<long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_set<long long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_set<intmax_t>>().empty()); |
||||
|
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<object>>().empty()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_get_unordered_multiset) { |
||||
|
object obj; |
||||
|
|
||||
|
EXPECT_TRUE(obj.get<std::unordered_multiset<bool>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_multiset<signed char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_multiset<unsigned char>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_multiset<short>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_multiset<int>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_multiset<long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_multiset<long long>>().empty()); |
||||
|
EXPECT_TRUE(obj.get<std::unordered_multiset<intmax_t>>().empty()); |
||||
|
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_set<object>>().empty()); |
||||
|
} |
||||
|
|
||||
|
/** basic_value_constructor */ |
||||
|
|
||||
|
#define OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(in_type) \ |
||||
|
{ object test_object__{ in_type {} }; \ |
||||
|
EXPECT_TRUE(test_object__ .has< in_type >()); \ |
||||
|
EXPECT_EQ(test_object__.get< in_type >(), in_type {} ); } |
||||
|
|
||||
|
// asdf
|
||||
|
|
||||
|
TEST(ObjectTest, basic_value_constructor) { |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(bool); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(signed_char_t); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(unsigned_char_t); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(short); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(int); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(long); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(long_long_t); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(intmax_t); |
||||
|
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(object::array_t); |
||||
|
|
||||
|
// const char*
|
||||
|
{ |
||||
|
object obj{ "" }; |
||||
|
EXPECT_TRUE(obj.has<std::string>()); |
||||
|
EXPECT_EQ(obj.get<std::string>(), std::string{}); |
||||
|
} |
||||
|
|
||||
|
// std::string_view
|
||||
|
{ |
||||
|
object obj{ ""sv }; |
||||
|
EXPECT_TRUE(obj.has<std::string>()); |
||||
|
EXPECT_EQ(obj.get<std::string>(), std::string{}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_value_constructor_vector) { |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<bool>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<signed char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<unsigned char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<short>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<int>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<long long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::vector<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_value_constructor_list) { |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<bool>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<signed char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<unsigned char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<short>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<int>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<long long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::list<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_value_constructor_forward_list) { |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<bool>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<signed char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<unsigned char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<short>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<int>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<long long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::forward_list<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_value_constructor_set) { |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<bool>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<signed char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<unsigned char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<short>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<int>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<long long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::set<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_value_constructor_multiset) { |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<bool>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<signed char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<unsigned char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<short>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<int>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<long long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::multiset<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_value_constructor_unordered_set) { |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<bool>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<signed char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<unsigned char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<short>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<int>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<long long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_set<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_value_constructor_unordered_multiset) { |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<bool>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<signed char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<unsigned char>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<short>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<int>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<long long>); |
||||
|
OBJECT_BASIC_VALUE_CONSTRUCTOR_TEST(std::unordered_multiset<intmax_t>); |
||||
|
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_set<object>); |
||||
|
} |
||||
|
|
||||
|
/** basic_set */ |
||||
|
|
||||
|
#define OBJECT_BASIC_SET_TEST(in_object, in_type) \ |
||||
|
in_object .set< in_type >( in_type {} ); \ |
||||
|
EXPECT_TRUE(in_object .has< in_type >()); \ |
||||
|
EXPECT_EQ(in_object .get< in_type >(), in_type {} ) |
||||
|
|
||||
|
TEST(ObjectTest, basic_set) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_SET_TEST(obj, bool); |
||||
|
OBJECT_BASIC_SET_TEST(obj, signed_char_t); |
||||
|
OBJECT_BASIC_SET_TEST(obj, unsigned_char_t); |
||||
|
OBJECT_BASIC_SET_TEST(obj, short); |
||||
|
OBJECT_BASIC_SET_TEST(obj, int); |
||||
|
OBJECT_BASIC_SET_TEST(obj, long); |
||||
|
OBJECT_BASIC_SET_TEST(obj, long_long_t); |
||||
|
OBJECT_BASIC_SET_TEST(obj, intmax_t); |
||||
|
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, object::array_t); |
||||
|
|
||||
|
// const char*
|
||||
|
obj.set(""); |
||||
|
EXPECT_TRUE(obj.has<std::string>()); |
||||
|
EXPECT_EQ(obj.get<std::string>(), std::string{}); |
||||
|
|
||||
|
// std::string_view
|
||||
|
obj.set(""sv); |
||||
|
EXPECT_TRUE(obj.has<std::string>()); |
||||
|
EXPECT_EQ(obj.get<std::string>(), std::string{}); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_set_vector) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_SET_TEST(obj, std::vector<bool>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::vector<signed char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::vector<unsigned char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::vector<short>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::vector<int>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::vector<long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::vector<long long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::vector<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_set_list) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_SET_TEST(obj, std::list<bool>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::list<signed char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::list<unsigned char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::list<short>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::list<int>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::list<long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::list<long long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::list<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_set_forward_list) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_SET_TEST(obj, std::forward_list<bool>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::forward_list<signed char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::forward_list<unsigned char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::forward_list<short>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::forward_list<int>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::forward_list<long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::forward_list<long long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::forward_list<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_set_set) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_SET_TEST(obj, std::set<bool>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::set<signed char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::set<unsigned char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::set<short>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::set<int>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::set<long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::set<long long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::set<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_set_multiset) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_SET_TEST(obj, std::multiset<bool>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::multiset<signed char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::multiset<unsigned char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::multiset<short>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::multiset<int>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::multiset<long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::multiset<long long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::multiset<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_set_unordered_set) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<bool>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<signed char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<unsigned char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<short>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<int>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<long long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_set<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_set_unordered_multiset) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<bool>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<signed char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<unsigned char>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<short>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<int>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<long long>); |
||||
|
OBJECT_BASIC_SET_TEST(obj, std::unordered_multiset<intmax_t>); |
||||
|
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_set<object>); |
||||
|
} |
||||
|
|
||||
|
/** basic_assignment_operator */ |
||||
|
|
||||
|
#define OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(in_object, in_type) \ |
||||
|
in_object = in_type {}; \ |
||||
|
EXPECT_TRUE(in_object .has< in_type >()); \ |
||||
|
EXPECT_EQ(in_object .get< in_type >(), in_type {} ) |
||||
|
|
||||
|
TEST(ObjectTest, basic_assignment_operator) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, bool); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, signed_char_t); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, unsigned_char_t); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, short); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, int); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, long); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, long_long_t); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, intmax_t); |
||||
|
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, object::array_t); |
||||
|
|
||||
|
// const char*
|
||||
|
obj = ""; |
||||
|
EXPECT_TRUE(obj.has<std::string>()); |
||||
|
EXPECT_EQ(obj.get<std::string>(), std::string{}); |
||||
|
|
||||
|
// std::string_view
|
||||
|
obj = ""sv; |
||||
|
EXPECT_TRUE(obj.has<std::string>()); |
||||
|
EXPECT_EQ(obj.get<std::string>(), std::string{}); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_assignment_operator_vector) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<bool>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<signed char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<unsigned char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<short>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<int>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<long long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::vector<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_assignment_operator_list) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<bool>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<signed char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<unsigned char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<short>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<int>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<long long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::list<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_assignment_operator_forward_list) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<bool>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<signed char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<unsigned char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<short>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<int>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<long long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::forward_list<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_assignment_operator_set) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<bool>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<signed char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<unsigned char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<short>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<int>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<long long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::set<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_assignment_operator_multiset) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<bool>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<signed char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<unsigned char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<short>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<int>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<long long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::multiset<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_assignment_operator_unordered_set) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<bool>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<signed char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<unsigned char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<short>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<int>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<long long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_set<intmax_t>); |
||||
|
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<object>); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, basic_assignment_operator_unordered_multiset) { |
||||
|
object obj; |
||||
|
|
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<bool>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<signed char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<unsigned char>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<short>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<int>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<long long>); |
||||
|
OBJECT_BASIC_ASSIGNMENT_OPERATOR_TEST(obj, std::unordered_multiset<intmax_t>); |
||||
|
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_set<object>); |
||||
|
} |
||||
|
|
||||
|
/** basic_access_operator */ |
||||
|
|
||||
|
TEST(ObjectTest, basic_access_operator) { |
||||
|
object obj; |
||||
|
|
||||
|
obj["test"] = 1234; |
||||
|
EXPECT_EQ(obj["test"].get<int>(), 1234); |
||||
|
EXPECT_EQ(obj["test2"].get<int>(), 0); |
||||
|
|
||||
|
obj["test"] = 4567; |
||||
|
EXPECT_EQ(obj["test"].get<int>(), 4567); |
||||
|
EXPECT_EQ(obj["test2"].get<int>(), 0); |
||||
|
|
||||
|
obj["test2"] = 1234; |
||||
|
EXPECT_EQ(obj["test"].get<int>(), 4567); |
||||
|
EXPECT_EQ(obj["test2"].get<int>(), 1234); |
||||
|
} |
||||
|
|
||||
|
/** end basic tests */ |
||||
|
|
||||
|
TEST(ObjectTest, set_bool) { |
||||
|
object obj; |
||||
|
|
||||
|
obj.set(true); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<bool>()); |
||||
|
EXPECT_TRUE(obj.get<bool>()); |
||||
|
EXPECT_FALSE(obj.has<int>()); |
||||
|
EXPECT_EQ(obj.get<int>(), 0); |
||||
|
|
||||
|
obj.set(false); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
EXPECT_FALSE(obj.has<int>()); |
||||
|
EXPECT_EQ(obj.get<int>(), 0); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, set_int) { |
||||
|
object obj; |
||||
|
|
||||
|
obj.set(1337); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<int>()); |
||||
|
EXPECT_EQ(obj.get<int>(), 1337); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
|
||||
|
obj.set(7331); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<int>()); |
||||
|
EXPECT_EQ(obj.get<int>(), 7331); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
|
||||
|
obj.set(0); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<int>()); |
||||
|
EXPECT_EQ(obj.get<int>(), 0); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, set_float) { |
||||
|
object obj; |
||||
|
|
||||
|
obj.set(13.37); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<double>()); |
||||
|
EXPECT_EQ(obj.get<double>(), 13.37); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
|
||||
|
obj.set(73.31); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<double>()); |
||||
|
EXPECT_EQ(obj.get<double>(), 73.31); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
|
||||
|
obj.set(0.0); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<double>()); |
||||
|
EXPECT_EQ(obj.get<double>(), 0.0); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, set_string) { |
||||
|
object obj; |
||||
|
|
||||
|
obj.set("Jessica"); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<std::string>()); |
||||
|
EXPECT_EQ(obj.get<std::string>(), "Jessica"); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
|
||||
|
obj.set("was"s); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<std::string>()); |
||||
|
EXPECT_EQ(obj.get<std::string>(), "was"); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
|
||||
|
obj.set("here"sv); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<std::string>()); |
||||
|
EXPECT_EQ(obj.get<std::string>(), "here"); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
|
||||
|
obj.set(""); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<std::string>()); |
||||
|
EXPECT_EQ(obj.get<std::string>(), ""); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, set_vector) { |
||||
|
object obj; |
||||
|
|
||||
|
obj.set(std::vector<bool>{ true }); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<std::vector<bool>>()); |
||||
|
EXPECT_EQ(obj.get<std::vector<bool>>(), std::vector<bool>{ true }); |
||||
|
EXPECT_TRUE(obj.has<std::vector<object>>()); |
||||
|
EXPECT_EQ(obj.get<std::vector<object>>().size(), 1U); |
||||
|
EXPECT_TRUE(obj.has<std::vector<int>>()); |
||||
|
EXPECT_EQ(obj.get<std::vector<int>>().size(), 0U); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
|
||||
|
obj.set(std::vector<bool>{}); |
||||
|
|
||||
|
EXPECT_TRUE(obj.has<std::vector<bool>>()); |
||||
|
EXPECT_EQ(obj.get<std::vector<bool>>().size(), 0U); |
||||
|
EXPECT_TRUE(obj.has<std::vector<object>>()); |
||||
|
EXPECT_EQ(obj.get<std::vector<object>>().size(), 0U); |
||||
|
EXPECT_TRUE(obj.has<std::vector<int>>()); |
||||
|
EXPECT_EQ(obj.get<std::vector<int>>().size(), 0U); |
||||
|
EXPECT_FALSE(obj.has<bool>()); |
||||
|
EXPECT_FALSE(obj.get<bool>()); |
||||
|
} |
||||
|
|
||||
|
TEST(ObjectTest, set_object) { |
||||
|
object obj1, obj2; |
||||
|
|
||||
|
obj1.set(true); |
||||
|
obj2.set(obj1); |
||||
|
|
||||
|
EXPECT_EQ(obj1, obj2); |
||||
|
} |
@ -0,0 +1,32 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2018 Jessica James. |
||||
|
* |
||||
|
* Permission to use, copy, modify, and/or distribute this software for any |
||||
|
* purpose with or without fee is hereby granted, provided that the above |
||||
|
* copyright notice and this permission notice appear in all copies. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
* |
||||
|
* Written by Jessica James <jessica.aj@outlook.com> |
||||
|
*/ |
||||
|
|
||||
|
#include "util.hpp" |
||||
|
#include "test.hpp" |
||||
|
#include "object.hpp" |
||||
|
|
||||
|
using namespace jessilib; |
||||
|
using namespace std::literals; |
||||
|
|
||||
|
TEST(UtilTest, filename) { |
||||
|
constexpr const char* filename = JESSILIB_FILENAME; |
||||
|
EXPECT_STREQ(filename, "util.cpp"); |
||||
|
} |
||||
|
|
||||
|
// Non-virtual using variant: 48
|
||||
|
//
|
Loading…
Reference in new issue