Make UnknownElement moveable and not copyable
And remove the unused comparison functionality.
This commit is contained in:
parent
4c0e578eda
commit
4c88449e4c
19 changed files with 155 additions and 392 deletions
|
@ -12,80 +12,59 @@ Author: Terry Caton
|
|||
#include <utility>
|
||||
|
||||
namespace {
|
||||
using namespace json;
|
||||
using namespace json;
|
||||
|
||||
class CastVisitorBase : public Visitor, public ConstVisitor {
|
||||
void Visit(Array&) { }
|
||||
void Visit(Object&) { }
|
||||
void Visit(Integer&) { }
|
||||
void Visit(Double&) { }
|
||||
void Visit(String&) { }
|
||||
void Visit(Boolean&) { }
|
||||
void Visit(Null&) { is_null = true; }
|
||||
void Visit(Array const&) { }
|
||||
void Visit(Object const&) { }
|
||||
void Visit(Integer) { }
|
||||
void Visit(Double) { }
|
||||
void Visit(String const&) { }
|
||||
void Visit(Boolean) { }
|
||||
void Visit(Null const&) { is_null = true; }
|
||||
public:
|
||||
bool is_null = false;
|
||||
};
|
||||
class CastVisitorBase : public Visitor {
|
||||
void Visit(Array&) override { }
|
||||
void Visit(Object&) override { }
|
||||
void Visit(Integer&) override { }
|
||||
void Visit(Double&) override { }
|
||||
void Visit(String&) override { }
|
||||
void Visit(Boolean&) override { }
|
||||
void Visit(Null&) override { is_null = true; }
|
||||
public:
|
||||
bool is_null = false;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct CastVisitor final : public CastVisitorBase {
|
||||
T *element = nullptr;
|
||||
void Visit(T& ele) { element = &ele; }
|
||||
};
|
||||
template<typename T>
|
||||
struct CastVisitor final : public CastVisitorBase {
|
||||
T *element = nullptr;
|
||||
void Visit(T& ele) override { element = &ele; }
|
||||
};
|
||||
}
|
||||
|
||||
namespace json
|
||||
{
|
||||
|
||||
/////////////////////////
|
||||
// UnknownElement members
|
||||
class UnknownElement::Imp
|
||||
{
|
||||
namespace json {
|
||||
class UnknownElement::Imp {
|
||||
public:
|
||||
virtual ~Imp() {}
|
||||
virtual Imp* Clone() const = 0;
|
||||
|
||||
virtual bool Compare(const Imp& imp) const = 0;
|
||||
|
||||
virtual void Accept(ConstVisitor& visitor) const = 0;
|
||||
virtual void Accept(Visitor& visitor) = 0;
|
||||
virtual ~Imp() {}
|
||||
virtual void Accept(ConstVisitor& visitor) const = 0;
|
||||
virtual void Accept(Visitor& visitor) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename ElementTypeT>
|
||||
class UnknownElement::Imp_T final : public UnknownElement::Imp
|
||||
{
|
||||
class Imp_T final : public UnknownElement::Imp {
|
||||
ElementTypeT m_Element;
|
||||
|
||||
public:
|
||||
Imp_T(const ElementTypeT& element) : m_Element(element) { }
|
||||
Imp* Clone() const { return new Imp_T<ElementTypeT>(*this); }
|
||||
Imp_T(ElementTypeT element) : m_Element(std::move(element)) { }
|
||||
|
||||
void Accept(ConstVisitor& visitor) const { visitor.Visit(m_Element); }
|
||||
void Accept(Visitor& visitor) { visitor.Visit(m_Element); }
|
||||
|
||||
bool Compare(const Imp& imp) const
|
||||
{
|
||||
CastVisitor<const ElementTypeT> castVisitor;
|
||||
imp.Accept(castVisitor);
|
||||
return castVisitor.element && m_Element == *castVisitor.element;
|
||||
}
|
||||
|
||||
private:
|
||||
ElementTypeT m_Element;
|
||||
void Accept(ConstVisitor& visitor) const { visitor.Visit(m_Element); }
|
||||
void Accept(Visitor& visitor) { visitor.Visit(m_Element); }
|
||||
};
|
||||
}
|
||||
|
||||
namespace json {
|
||||
UnknownElement::UnknownElement() : m_pImp(new Imp_T<Null>(Null())) {}
|
||||
UnknownElement::UnknownElement(UnknownElement&& unknown) : m_pImp(std::move(unknown.m_pImp)) {}
|
||||
UnknownElement::UnknownElement(int number) : m_pImp(new Imp_T<Integer>(number)) {}
|
||||
UnknownElement::UnknownElement(const char *string) : m_pImp(new Imp_T<String>(string)) {}
|
||||
|
||||
UnknownElement::UnknownElement() : m_pImp(new Imp_T<Null>(Null())) {}
|
||||
UnknownElement::UnknownElement(const UnknownElement& unknown) : m_pImp(unknown.m_pImp->Clone()) {}
|
||||
UnknownElement::UnknownElement(int number) : m_pImp(new Imp_T<Integer>(number)) {}
|
||||
UnknownElement::UnknownElement(const char *string) : m_pImp(new Imp_T<String>(string)) {}
|
||||
UnknownElement::~UnknownElement() { }
|
||||
|
||||
#define DEFINE_UE_TYPE(Type) \
|
||||
UnknownElement::UnknownElement(Type const& val) : m_pImp(new Imp_T<Type>(val)) { } \
|
||||
UnknownElement::UnknownElement(Type val) : m_pImp(new Imp_T<Type>(std::move(val))) { } \
|
||||
UnknownElement::operator Type const&() const { return CastTo<Type>(); } \
|
||||
UnknownElement::operator Type&() { return CastTo<Type>(); }
|
||||
|
||||
|
@ -97,40 +76,22 @@ DEFINE_UE_TYPE(Boolean)
|
|||
DEFINE_UE_TYPE(String)
|
||||
DEFINE_UE_TYPE(Null)
|
||||
|
||||
UnknownElement& UnknownElement::operator =(const UnknownElement& unknown)
|
||||
{
|
||||
m_pImp.reset(unknown.m_pImp->Clone());
|
||||
UnknownElement& UnknownElement::operator=(UnknownElement&& unknown) {
|
||||
m_pImp = std::move(unknown.m_pImp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
UnknownElement& UnknownElement::operator[](const std::string& key)
|
||||
{
|
||||
return CastTo<Object>()[key];
|
||||
}
|
||||
|
||||
const UnknownElement& UnknownElement::operator[] (const std::string& key) const
|
||||
{
|
||||
// throws if we aren't an object
|
||||
Object const& obj = CastTo<Object>();
|
||||
Object::const_iterator it = obj.find(key);
|
||||
if (it == obj.end())
|
||||
throw Exception("Object member not found: " + key);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
template <typename ElementTypeT>
|
||||
ElementTypeT const& UnknownElement::CastTo() const
|
||||
{
|
||||
CastVisitor<const ElementTypeT> castVisitor;
|
||||
Accept(castVisitor);
|
||||
ElementTypeT const& UnknownElement::CastTo() const {
|
||||
CastVisitor<ElementTypeT> castVisitor;
|
||||
const_cast<UnknownElement *>(this)->Accept(castVisitor);
|
||||
if (!castVisitor.element)
|
||||
throw Exception("Bad cast");
|
||||
return *castVisitor.element;
|
||||
}
|
||||
|
||||
template <typename ElementTypeT>
|
||||
ElementTypeT& UnknownElement::CastTo()
|
||||
{
|
||||
ElementTypeT& UnknownElement::CastTo() {
|
||||
CastVisitor<ElementTypeT> castVisitor;
|
||||
Accept(castVisitor);
|
||||
|
||||
|
@ -148,10 +109,4 @@ ElementTypeT& UnknownElement::CastTo()
|
|||
|
||||
void UnknownElement::Accept(ConstVisitor& visitor) const { m_pImp->Accept(visitor); }
|
||||
void UnknownElement::Accept(Visitor& visitor) { m_pImp->Accept(visitor); }
|
||||
|
||||
bool UnknownElement::operator == (const UnknownElement& element) const
|
||||
{
|
||||
return m_pImp->Compare(*element.m_pImp);
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
|
|
@ -288,7 +288,7 @@ UnknownElement Reader::ParseObject(Reader::TokenStream& tokenStream) {
|
|||
|
||||
MatchExpectedToken(Token::TOKEN_OBJECT_END, tokenStream);
|
||||
|
||||
return object;
|
||||
return std::move(object);
|
||||
}
|
||||
|
||||
UnknownElement Reader::ParseArray(Reader::TokenStream& tokenStream) {
|
||||
|
@ -296,8 +296,7 @@ UnknownElement Reader::ParseArray(Reader::TokenStream& tokenStream) {
|
|||
|
||||
Array array;
|
||||
|
||||
while (!tokenStream.EOS() && tokenStream.Peek().nType != Token::TOKEN_ARRAY_END)
|
||||
{
|
||||
while (!tokenStream.EOS() && tokenStream.Peek().nType != Token::TOKEN_ARRAY_END) {
|
||||
array.push_back(Parse(tokenStream));
|
||||
|
||||
if (!tokenStream.EOS() && tokenStream.Peek().nType != Token::TOKEN_ARRAY_END)
|
||||
|
@ -306,7 +305,7 @@ UnknownElement Reader::ParseArray(Reader::TokenStream& tokenStream) {
|
|||
|
||||
MatchExpectedToken(Token::TOKEN_ARRAY_END, tokenStream);
|
||||
|
||||
return array;
|
||||
return std::move(array);
|
||||
}
|
||||
|
||||
UnknownElement Reader::ParseString(Reader::TokenStream& tokenStream) {
|
||||
|
|
|
@ -44,13 +44,13 @@ void Hotkey::ComboInsert(Combo const& combo) {
|
|||
cmd_map.insert(make_pair(combo.CmdName(), combo));
|
||||
}
|
||||
|
||||
Hotkey::Hotkey(agi::fs::path const& file, std::pair<const char *, size_t> default_config)
|
||||
Hotkey::Hotkey(fs::path const& file, std::pair<const char *, size_t> default_config)
|
||||
: config_file(file)
|
||||
{
|
||||
LOG_D("hotkey/init") << "Generating hotkeys.";
|
||||
|
||||
const json::Object object(agi::json_util::file(config_file, default_config));
|
||||
for (auto const& hotkey_context : object)
|
||||
auto root = json_util::file(config_file, default_config);
|
||||
for (auto const& hotkey_context : static_cast<json::Object const&>(root))
|
||||
BuildHotkey(hotkey_context.first, hotkey_context.second);
|
||||
}
|
||||
|
||||
|
@ -58,19 +58,26 @@ void Hotkey::BuildHotkey(std::string const& context, json::Object const& hotkeys
|
|||
for (auto const& command : hotkeys) {
|
||||
const json::Array& command_hotkeys = command.second;
|
||||
|
||||
for (auto const& hotkey : command_hotkeys) {
|
||||
for (json::Object const& hotkey : command_hotkeys) {
|
||||
std::vector<std::string> keys;
|
||||
|
||||
try {
|
||||
const json::Array& arr_mod = hotkey["modifiers"];
|
||||
keys.reserve(arr_mod.size() + 1);
|
||||
copy(arr_mod.begin(), arr_mod.end(), back_inserter(keys));
|
||||
keys.push_back(hotkey["key"]);
|
||||
}
|
||||
catch (json::Exception const& e) {
|
||||
LOG_E("agi/hotkey/load") << "Failed loading hotkey for command '" << command.first << "': " << e.what();
|
||||
auto it = hotkey.find("modifiers");
|
||||
if (it == end(hotkey)) {
|
||||
LOG_E("agi/hotkey/load") << "Hotkey for command '" << command.first << "' is missing modifiers";
|
||||
continue;
|
||||
}
|
||||
|
||||
json::Array const& arr_mod = it->second;
|
||||
keys.reserve(arr_mod.size() + 1);
|
||||
copy(arr_mod.begin(), arr_mod.end(), back_inserter(keys));
|
||||
|
||||
it = hotkey.find("key");
|
||||
if (it == end(hotkey)) {
|
||||
LOG_E("agi/hotkey/load") << "Hotkey for command '" << command.first << "' is missing the key";
|
||||
continue;
|
||||
}
|
||||
|
||||
keys.push_back(it->second);
|
||||
ComboInsert(Combo(context, command.first, keys));
|
||||
}
|
||||
}
|
||||
|
@ -157,12 +164,13 @@ void Hotkey::Flush() {
|
|||
modifiers.insert(modifiers.end(), combo.Get().begin(), combo.Get().end() - 1);
|
||||
}
|
||||
|
||||
json::Array& combo_array = root[combo.Context()][combo.CmdName()];
|
||||
json::Object& context = root[combo.Context()];
|
||||
json::Array& combo_array = context[combo.CmdName()];
|
||||
combo_array.push_back(std::move(hotkey));
|
||||
}
|
||||
|
||||
io::Save file(config_file);
|
||||
agi::JsonWriter::Write(root, file.Get());
|
||||
JsonWriter::Write(root, file.Get());
|
||||
}
|
||||
|
||||
void Hotkey::SetHotkeyMap(HotkeyMap const& new_map) {
|
||||
|
|
|
@ -38,8 +38,8 @@ MRUManager::MRUManager(agi::fs::path const& config, std::pair<const char *, size
|
|||
{
|
||||
LOG_D("agi/mru") << "Loading MRU List";
|
||||
|
||||
json::Object root(json_util::file(config, default_config));
|
||||
for (auto const& it : root)
|
||||
auto root = json_util::file(config, default_config);
|
||||
for (auto const& it : static_cast<json::Object const&>(root))
|
||||
Load(it.first, it.second);
|
||||
}
|
||||
|
||||
|
@ -76,8 +76,7 @@ const MRUManager::MRUListMap* MRUManager::Get(std::string const& key) {
|
|||
}
|
||||
|
||||
agi::fs::path const& MRUManager::GetEntry(std::string const& key, const size_t entry) {
|
||||
const MRUManager::MRUListMap *const map = Get(key);
|
||||
|
||||
const auto map = Get(key);
|
||||
if (entry >= map->size())
|
||||
throw MRUErrorIndexOutOfRange("Requested element index is out of range.");
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ class ConfigVisitor final : public json::ConstVisitor {
|
|||
void Visit(const json::Object& object) {
|
||||
auto old_name = name;
|
||||
for (auto const& obj : object) {
|
||||
name = old_name + (name.empty() ? "" : "/") + obj.first;
|
||||
name = old_name + (old_name.empty() ? "" : "/") + obj.first;
|
||||
obj.second.Accept(*this);
|
||||
}
|
||||
name = old_name;
|
||||
|
@ -144,15 +144,15 @@ public:
|
|||
/// @param[out] obj Parent object
|
||||
/// @param[in] path Path option should be stored in.
|
||||
/// @param[in] value Value to write.
|
||||
void put_option(json::Object &obj, const std::string &path, const json::UnknownElement &value) {
|
||||
void put_option(json::Object &obj, const std::string &path, json::UnknownElement value) {
|
||||
std::string::size_type pos = path.find('/');
|
||||
// Not having a '/' denotes it is a leaf.
|
||||
if (pos == std::string::npos) {
|
||||
assert(obj.find(path) == obj.end());
|
||||
obj[path] = value;
|
||||
obj[path] = std::move(value);
|
||||
}
|
||||
else
|
||||
put_option(obj[path.substr(0, pos)], path.substr(pos + 1), value);
|
||||
put_option(obj[path.substr(0, pos)], path.substr(pos + 1), std::move(value));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
@ -163,7 +163,7 @@ void put_array(json::Object &obj, const std::string &path, const char *element_k
|
|||
static_cast<json::Object&>(array.back())[element_key] = (json::UnknownElement)elem;
|
||||
}
|
||||
|
||||
put_option(obj, path, array);
|
||||
put_option(obj, path, std::move(array));
|
||||
}
|
||||
|
||||
struct option_name_cmp {
|
||||
|
|
|
@ -56,20 +56,20 @@ public:
|
|||
class UnknownElement {
|
||||
public:
|
||||
UnknownElement();
|
||||
UnknownElement(const UnknownElement& unknown);
|
||||
UnknownElement(const Object& object);
|
||||
UnknownElement(const Array& array);
|
||||
UnknownElement(double const& number);
|
||||
UnknownElement(UnknownElement&& unknown);
|
||||
UnknownElement(Object object);
|
||||
UnknownElement(Array array);
|
||||
UnknownElement(double number);
|
||||
UnknownElement(int number);
|
||||
UnknownElement(int64_t const& number);
|
||||
UnknownElement(bool const& boolean);
|
||||
UnknownElement(int64_t number);
|
||||
UnknownElement(bool boolean);
|
||||
UnknownElement(const char *string);
|
||||
UnknownElement(const String& string);
|
||||
UnknownElement(const Null& null);
|
||||
UnknownElement(String string);
|
||||
UnknownElement(Null null);
|
||||
|
||||
~UnknownElement();
|
||||
|
||||
UnknownElement& operator = (const UnknownElement& unknown);
|
||||
UnknownElement& operator=(UnknownElement&& unknown);
|
||||
|
||||
// implicit cast to actual element type. throws on failure
|
||||
operator Object const&() const;
|
||||
|
@ -87,27 +87,14 @@ public:
|
|||
operator String&();
|
||||
operator Null&();
|
||||
|
||||
// provides quick access to children when real element type is object
|
||||
UnknownElement& operator[] (const std::string& key);
|
||||
const UnknownElement& operator[] (const std::string& key) const;
|
||||
template<int N>
|
||||
UnknownElement& operator[] (const char(&key)[N]) { return operator[](std::string(key)); }
|
||||
template<int N>
|
||||
const UnknownElement& operator[] (const char(&key)[N]) const { return operator[](std::string(key)); }
|
||||
|
||||
// implements visitor pattern
|
||||
void Accept(ConstVisitor& visitor) const;
|
||||
void Accept(Visitor& visitor);
|
||||
|
||||
// tests equality. first checks type, then value if possible
|
||||
bool operator ==(const UnknownElement& element) const;
|
||||
bool operator !=(const UnknownElement& element) const { return !(*this == element); }
|
||||
|
||||
private:
|
||||
class Imp;
|
||||
|
||||
template <typename ElementTypeT>
|
||||
class Imp_T;
|
||||
private:
|
||||
UnknownElement(UnknownElement const& unknown) = delete;
|
||||
|
||||
template <typename ElementTypeT>
|
||||
ElementTypeT const& CastTo() const;
|
||||
|
@ -121,8 +108,6 @@ private:
|
|||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Null - doesn't do much of anything but satisfy the JSON spec. It is the default
|
||||
// element type of UnknownElement
|
||||
struct Null {
|
||||
bool operator == (const Null&) const { return true; }
|
||||
};
|
||||
struct Null { };
|
||||
|
||||
} // end namespace
|
||||
|
|
|
@ -68,7 +68,7 @@ class DialogShiftTimes final : public wxDialog {
|
|||
wxRadioBox *time_fields;
|
||||
wxListBox *history_box;
|
||||
|
||||
void SaveHistory(json::Array const& shifted_blocks);
|
||||
void SaveHistory(json::Array shifted_blocks);
|
||||
void LoadHistory();
|
||||
void Process(wxCommandEvent&);
|
||||
int Shift(int initial_time, int shift, bool by_time, agi::vfr::Time type);
|
||||
|
@ -103,19 +103,20 @@ static wxString get_history_string(json::Object &obj) {
|
|||
time_field == 1 ? _("s") :
|
||||
_("e") ;
|
||||
|
||||
json::Array const& sel = obj["selection"];
|
||||
json::Array& sel = obj["selection"];
|
||||
wxString lines;
|
||||
|
||||
int64_t sel_mode = obj["mode"];
|
||||
if (sel_mode == 0)
|
||||
lines = _("all");
|
||||
else if (sel_mode == 2)
|
||||
lines = fmt_tl("from %d onward", (int64_t)sel.front()["start"]);
|
||||
lines = fmt_tl("from %d onward", (int64_t)static_cast<json::Object&>(sel.front())["start"]);
|
||||
else {
|
||||
lines += _("sel ");
|
||||
for (auto it = sel.begin(); it != sel.end(); ++it) {
|
||||
int beg = (int64_t)(*it)["start"];
|
||||
int end = (int64_t)(*it)["end"];
|
||||
json::Object& range = *it;
|
||||
int beg = (int64_t)range["start"];
|
||||
int end = (int64_t)range["end"];
|
||||
if (beg == end)
|
||||
lines += std::to_wstring(beg);
|
||||
else
|
||||
|
@ -306,7 +307,7 @@ void DialogShiftTimes::OnHistoryClick(wxCommandEvent &evt) {
|
|||
time_fields->SetSelection((int64_t)obj["fields"]);
|
||||
}
|
||||
|
||||
void DialogShiftTimes::SaveHistory(json::Array const& shifted_blocks) {
|
||||
void DialogShiftTimes::SaveHistory(json::Array shifted_blocks) {
|
||||
json::Object new_entry;
|
||||
new_entry["filename"] = context->subsController->Filename().filename().string();
|
||||
new_entry["is by time"] = shift_by_time->GetValue();
|
||||
|
@ -314,9 +315,9 @@ void DialogShiftTimes::SaveHistory(json::Array const& shifted_blocks) {
|
|||
new_entry["amount"] = from_wx(shift_by_time->GetValue() ? shift_time->GetValue() : shift_frames->GetValue());
|
||||
new_entry["fields"] = time_fields->GetSelection();
|
||||
new_entry["mode"] = selection_mode->GetSelection();
|
||||
new_entry["selection"] = shifted_blocks;
|
||||
new_entry["selection"] = std::move(shifted_blocks);
|
||||
|
||||
history.insert(history.begin(), new_entry);
|
||||
history.insert(history.begin(), std::move(new_entry));
|
||||
if (history.size() > 50)
|
||||
history.resize(50);
|
||||
|
||||
|
@ -335,7 +336,7 @@ void DialogShiftTimes::LoadHistory() {
|
|||
try {
|
||||
json::UnknownElement root;
|
||||
json::Reader::Read(root, *agi::io::Open(history_filename));
|
||||
history = root;
|
||||
history = std::move(static_cast<json::Array&>(root));
|
||||
|
||||
for (auto& history_entry : history)
|
||||
history_box->Append(get_history_string(history_entry));
|
||||
|
@ -386,7 +387,7 @@ void DialogShiftTimes::Process(wxCommandEvent &) {
|
|||
json::Object block;
|
||||
block["start"] = block_start;
|
||||
block["end"] = line.Row;
|
||||
shifted_blocks.push_back(block);
|
||||
shifted_blocks.push_back(std::move(block));
|
||||
block_start = 0;
|
||||
}
|
||||
if (mode == 1) continue;
|
||||
|
@ -407,10 +408,10 @@ void DialogShiftTimes::Process(wxCommandEvent &) {
|
|||
json::Object block;
|
||||
block["start"] = block_start;
|
||||
block["end"] = context->ass->Events.back().Row + 1;
|
||||
shifted_blocks.push_back(block);
|
||||
shifted_blocks.push_back(std::move(block));
|
||||
}
|
||||
|
||||
SaveHistory(shifted_blocks);
|
||||
SaveHistory(std::move(shifted_blocks));
|
||||
Close();
|
||||
}
|
||||
|
||||
|
|
|
@ -295,7 +295,7 @@ json::Object const& get_menus_root() {
|
|||
if (!root.empty()) return root;
|
||||
|
||||
try {
|
||||
root = agi::json_util::file(config::path->Decode("?user/menu.json"), GET_DEFAULT_CONFIG(default_menu));
|
||||
root = std::move(static_cast<json::Object&>(agi::json_util::file(config::path->Decode("?user/menu.json"), GET_DEFAULT_CONFIG(default_menu))));
|
||||
return root;
|
||||
}
|
||||
catch (json::Reader::ParseException const& e) {
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace {
|
|||
static json::Object root;
|
||||
if (root.empty()) {
|
||||
boost::interprocess::ibufferstream stream((const char *)default_toolbar, sizeof(default_toolbar));
|
||||
root = agi::json_util::parse(stream);
|
||||
root = std::move(static_cast<json::Object&>(agi::json_util::parse(stream)));
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"Integer" : 0,
|
||||
"Double" : 0.1,
|
||||
"String" : "",
|
||||
"Color" : "rgb(0, 0, 0)",
|
||||
"Boolean" : false,
|
||||
"Array" : {
|
||||
"Integer" : [ { "int" : 0 }, {"int" : 0 } ],
|
||||
"Double" : [ { "double" : 0.1 }, {"double" : 0.1 } ],
|
||||
"String" : [ { "string" : "" }, {"string" : "" } ],
|
||||
"Color" : [ { "color" : "rgb(0,0,0)" }, {"color" : "rgb(0,0,0)" } ],
|
||||
"Boolean" : [ { "bool" : false }, {"bool" : false } ]
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
{"Bool" : [{"bool" : true}, {"bool" : true}]}
|
|
@ -1 +0,0 @@
|
|||
{"Double" : [{"double" : 2.1}, {"double" : 2.1}]}
|
|
@ -1 +0,0 @@
|
|||
{"Integer" : [{"int" : 1}, {"int" : 1}]}
|
|
@ -1 +0,0 @@
|
|||
{"String" : [{"string" : "This is a test"}, {"string" : "This is a test"}]}
|
|
@ -1 +0,0 @@
|
|||
{"Bool" : true}
|
|
@ -1 +0,0 @@
|
|||
{"Double" : 2.1}
|
|
@ -1 +0,0 @@
|
|||
{"Integer" : 1}
|
|
@ -25,78 +25,9 @@
|
|||
#include <libaegisub/cajun/elements.h>
|
||||
#include <libaegisub/cajun/visitor.h>
|
||||
|
||||
class lagi_cajun : public libagi {
|
||||
class lagi_cajun : public libagi { };
|
||||
|
||||
protected:
|
||||
// place holder for future code placement
|
||||
};
|
||||
|
||||
TEST_F(lagi_cajun, Compare) {
|
||||
json::UnknownElement Integer1 = 0;
|
||||
json::UnknownElement Integer2 = 1;
|
||||
json::UnknownElement String1 = "1";
|
||||
json::UnknownElement String2 = "2";
|
||||
json::UnknownElement Boolean1 = false;
|
||||
json::UnknownElement Boolean2 = true;
|
||||
json::UnknownElement Array1 = json::Array();
|
||||
json::UnknownElement Array2 = json::Array();
|
||||
json::UnknownElement Object1 = json::Object();
|
||||
json::UnknownElement Object2 = json::Object();
|
||||
json::UnknownElement Null = json::Null();
|
||||
|
||||
static_cast<json::Array&>(Array2).push_back(1);
|
||||
Object2["a"] = "b";
|
||||
|
||||
// Test that things are equal to themselves and mixed comparisons are not errors
|
||||
EXPECT_EQ(Integer1, Integer1);
|
||||
EXPECT_NE(Integer1, Integer2);
|
||||
EXPECT_NE(Integer1, String1);
|
||||
EXPECT_NE(Integer1, Boolean1);
|
||||
EXPECT_NE(Integer1, Array1);
|
||||
EXPECT_NE(Integer1, Object1);
|
||||
EXPECT_NE(Integer1, Null);
|
||||
|
||||
EXPECT_EQ(String1, String1);
|
||||
EXPECT_NE(String1, Integer2);
|
||||
EXPECT_NE(String1, String2);
|
||||
EXPECT_NE(String1, Boolean1);
|
||||
EXPECT_NE(String1, Array1);
|
||||
EXPECT_NE(String1, Object1);
|
||||
EXPECT_NE(String1, Null);
|
||||
|
||||
EXPECT_EQ(Boolean1, Boolean1);
|
||||
EXPECT_NE(Boolean1, Integer2);
|
||||
EXPECT_NE(Boolean1, String1);
|
||||
EXPECT_NE(Boolean1, Boolean2);
|
||||
EXPECT_NE(Boolean1, Array1);
|
||||
EXPECT_NE(Boolean1, Object1);
|
||||
EXPECT_NE(Boolean1, Null);
|
||||
|
||||
EXPECT_EQ(Array1, Array1);
|
||||
EXPECT_NE(Array1, Integer2);
|
||||
EXPECT_NE(Array1, String1);
|
||||
EXPECT_NE(Array1, Boolean1);
|
||||
EXPECT_NE(Array1, Array2);
|
||||
EXPECT_NE(Array1, Object1);
|
||||
EXPECT_NE(Array1, Null);
|
||||
|
||||
EXPECT_EQ(Object1, Object1);
|
||||
EXPECT_NE(Object1, Integer2);
|
||||
EXPECT_NE(Object1, String1);
|
||||
EXPECT_NE(Object1, Boolean1);
|
||||
EXPECT_NE(Object1, Array2);
|
||||
EXPECT_NE(Object1, Object2);
|
||||
EXPECT_NE(Object1, Null);
|
||||
|
||||
EXPECT_EQ(Null, Null);
|
||||
EXPECT_NE(Null, Integer2);
|
||||
EXPECT_NE(Null, String1);
|
||||
EXPECT_NE(Null, Boolean1);
|
||||
EXPECT_NE(Null, Array2);
|
||||
EXPECT_NE(Null, Object2);
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, CastNonConst) {
|
||||
TEST(lagi_cajun, CastNonConst) {
|
||||
json::UnknownElement Integer = 0;
|
||||
json::UnknownElement Double = 0.0;
|
||||
json::UnknownElement String = "1";
|
||||
|
@ -119,7 +50,7 @@ TEST_F(lagi_cajun, CastNonConst) {
|
|||
EXPECT_NO_THROW(static_cast<json::Object const&>(Object));
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, CastConst) {
|
||||
TEST(lagi_cajun, CastConst) {
|
||||
const json::UnknownElement Integer = 10;
|
||||
const json::UnknownElement Double = 10.0;
|
||||
const json::UnknownElement String = "1";
|
||||
|
@ -151,21 +82,7 @@ TEST_F(lagi_cajun, CastConst) {
|
|||
EXPECT_TRUE(static_cast<json::Object const&>(Object).empty());
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, UnknownIsIndexable) {
|
||||
json::Object obj;
|
||||
obj["Integer"] = 1;
|
||||
json::UnknownElement unk_obj = obj;
|
||||
|
||||
EXPECT_NO_THROW(unk_obj["Integer"]);
|
||||
EXPECT_EQ(1, (json::Integer)unk_obj["Integer"]);
|
||||
EXPECT_NO_THROW(unk_obj["Nonexistent Key"]);
|
||||
|
||||
json::UnknownElement const& const_unk_obj = obj;
|
||||
EXPECT_NO_THROW(const_unk_obj["Integer"]);
|
||||
EXPECT_THROW(const_unk_obj["Another nonexistent Key"], json::Exception);
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, ObjectStoreInteger) {
|
||||
TEST(lagi_cajun, ObjectStoreInteger) {
|
||||
json::Object obj;
|
||||
obj["Integer"] = 1;
|
||||
EXPECT_EQ(1, static_cast<json::Integer>(obj["Integer"]));
|
||||
|
@ -177,7 +94,7 @@ TEST_F(lagi_cajun, ObjectStoreInteger) {
|
|||
EXPECT_THROW(static_cast<json::Object const&>(obj["Integer"]), json::Exception);
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, ObjectStoreDouble) {
|
||||
TEST(lagi_cajun, ObjectStoreDouble) {
|
||||
json::Object obj;
|
||||
obj["Double"] = 1.0;
|
||||
EXPECT_EQ(1.0, static_cast<json::Double>(obj["Double"]));
|
||||
|
@ -189,7 +106,7 @@ TEST_F(lagi_cajun, ObjectStoreDouble) {
|
|||
EXPECT_THROW(static_cast<json::Object const&>(obj["Double"]), json::Exception);
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, ObjectStoreString) {
|
||||
TEST(lagi_cajun, ObjectStoreString) {
|
||||
json::Object obj;
|
||||
obj["String"] = "test";
|
||||
EXPECT_STREQ("test", static_cast<std::string>(obj["String"]).c_str());
|
||||
|
@ -201,7 +118,7 @@ TEST_F(lagi_cajun, ObjectStoreString) {
|
|||
EXPECT_THROW(static_cast<json::Object const&>(obj["String"]), json::Exception);
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, ObjectStoreBoolean) {
|
||||
TEST(lagi_cajun, ObjectStoreBoolean) {
|
||||
json::Object obj;
|
||||
obj["Boolean"] = true;
|
||||
EXPECT_TRUE(static_cast<json::Boolean>(obj["Boolean"]));
|
||||
|
@ -213,7 +130,7 @@ TEST_F(lagi_cajun, ObjectStoreBoolean) {
|
|||
EXPECT_THROW(static_cast<json::Object const&>(obj["Boolean"]), json::Exception);
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, ObjectStoreNull) {
|
||||
TEST(lagi_cajun, ObjectStoreNull) {
|
||||
json::Object obj;
|
||||
obj["Null"] = json::Null();
|
||||
|
||||
|
@ -241,41 +158,27 @@ TEST_F(lagi_cajun, ObjectStoreNull) {
|
|||
EXPECT_THROW(static_cast<json::Null>(obj["Null"]), json::Exception);
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, ObjectCreateArray) {
|
||||
TEST(lagi_cajun, ObjectCreateArray) {
|
||||
json::Object obj;
|
||||
obj["Inside"] = "";
|
||||
json::Array array;
|
||||
array.push_back(obj);
|
||||
array.push_back(std::move(obj));
|
||||
|
||||
EXPECT_STREQ("", static_cast<std::string>(array[0]["Inside"]).c_str());
|
||||
EXPECT_STREQ("", static_cast<std::string>(static_cast<json::Object&>(array[0])["Inside"]).c_str());
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, ObjectEquality) {
|
||||
json::Object obj;
|
||||
obj["Inside"] = "";
|
||||
json::Array array;
|
||||
array.push_back(obj);
|
||||
obj["Array"] = array;
|
||||
json::Object obj_dupe = obj;
|
||||
|
||||
EXPECT_TRUE(obj_dupe == obj);
|
||||
|
||||
obj_dupe["NotEqual"] = array;
|
||||
EXPECT_FALSE(obj_dupe == obj);
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, Read) {
|
||||
json::UnknownElement obj;
|
||||
TEST(lagi_cajun, Read) {
|
||||
json::UnknownElement root;
|
||||
std::istringstream doc("{\"String\" : \"This is a test\", \"Boolean\" : false, \"Null\" : null }");
|
||||
EXPECT_NO_THROW(json::Reader::Read(obj, doc));
|
||||
EXPECT_NO_THROW(json::Reader::Read(root, doc));
|
||||
json::Object& obj = root;
|
||||
EXPECT_NO_THROW(obj["String"]);
|
||||
EXPECT_STREQ("This is a test", static_cast<std::string>(obj["String"]).c_str());
|
||||
EXPECT_FALSE(static_cast<json::Boolean>(obj["Boolean"]));
|
||||
EXPECT_NO_THROW(static_cast<json::Null>(obj["Null"]));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(lagi_cajun, Write) {
|
||||
TEST(lagi_cajun, Write) {
|
||||
json::Object obj;
|
||||
obj["Boolean"] = true;
|
||||
obj["String"] = "This \"is\" \\a \t test";
|
||||
|
@ -305,7 +208,7 @@ TEST_F(lagi_cajun, Write) {
|
|||
EXPECT_STREQ("null", stream.str().c_str());
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, ReaderParserErrors) {
|
||||
TEST(lagi_cajun, ReaderParserErrors) {
|
||||
json::UnknownElement ue;
|
||||
|
||||
std::istringstream missing_comma("[1 2]");
|
||||
|
@ -333,7 +236,7 @@ TEST_F(lagi_cajun, ReaderParserErrors) {
|
|||
EXPECT_NO_THROW(json::Reader::Read(ue, unique_keys));
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, ReaderScanErrors) {
|
||||
TEST(lagi_cajun, ReaderScanErrors) {
|
||||
json::UnknownElement ue;
|
||||
|
||||
std::istringstream doc("[true, false, thiswontwork]");
|
||||
|
@ -359,23 +262,23 @@ std::string roundtrip_test(const char *in) {
|
|||
return oss.str();
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, round_double_roundtrips) {
|
||||
TEST(lagi_cajun, round_double_roundtrips) {
|
||||
EXPECT_STREQ("1.0", roundtrip_test("1.0").c_str());
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, representable_double_roundtrips) {
|
||||
TEST(lagi_cajun, representable_double_roundtrips) {
|
||||
EXPECT_STREQ("1.5", roundtrip_test("1.5").c_str());
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, int_roundtrips) {
|
||||
TEST(lagi_cajun, int_roundtrips) {
|
||||
EXPECT_STREQ("1", roundtrip_test("1").c_str());
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, bool_roundtrips) {
|
||||
TEST(lagi_cajun, bool_roundtrips) {
|
||||
EXPECT_STREQ("true", roundtrip_test("true").c_str());
|
||||
EXPECT_STREQ("false", roundtrip_test("false").c_str());
|
||||
}
|
||||
|
||||
TEST_F(lagi_cajun, null_roundtrips) {
|
||||
TEST(lagi_cajun, null_roundtrips) {
|
||||
EXPECT_STREQ("null", roundtrip_test("null").c_str());
|
||||
}
|
||||
|
|
|
@ -22,6 +22,20 @@
|
|||
#include <fstream>
|
||||
|
||||
static const char default_opt[] = "{\"Valid\" : \"This is valid\"}";
|
||||
static const char all_types[] = R"raw({
|
||||
"Integer" : 0,
|
||||
"Double" : 0.1,
|
||||
"String" : "",
|
||||
"Color" : "rgb(0, 0, 0)",
|
||||
"Boolean" : false,
|
||||
"Array" : {
|
||||
"Integer" : [{ "int" : 0 }, {"int" : 0}],
|
||||
"Double" : [{ "double" : 0.1 }, {"double" : 0.1}],
|
||||
"String" : [{ "string" : "" }, {"string" : ""}],
|
||||
"Color" : [{ "color" : "rgb(0,0,0)" }, {"color" : "rgb(0,0,0)"}],
|
||||
"Boolean" : [{ "bool" : false }, {"bool" : false}]
|
||||
}
|
||||
})raw";
|
||||
|
||||
class lagi_option : public libagi {
|
||||
protected:
|
||||
|
@ -76,30 +90,14 @@ TEST_F(lagi_option, existent_but_invalid_file_uses_default) {
|
|||
EXPECT_THROW(opt.Get("Null"), agi::Exception);
|
||||
}
|
||||
|
||||
TEST_F(lagi_option, load_several_config_files) {
|
||||
agi::Options opt("", default_opt, agi::Options::FLUSH_SKIP);
|
||||
{ std::ifstream f("data/options/string.json"); EXPECT_NO_THROW(opt.ConfigNext(f)); }
|
||||
{ std::ifstream f("data/options/integer.json"); EXPECT_NO_THROW(opt.ConfigNext(f)); }
|
||||
{ std::ifstream f("data/options/double.json"); EXPECT_NO_THROW(opt.ConfigNext(f)); }
|
||||
{ std::ifstream f("data/options/bool.json"); EXPECT_NO_THROW(opt.ConfigNext(f)); }
|
||||
|
||||
EXPECT_NO_THROW(opt.Get("String")->GetString());
|
||||
EXPECT_NO_THROW(opt.Get("Integer")->GetInt());
|
||||
EXPECT_NO_THROW(opt.Get("Double")->GetDouble());
|
||||
EXPECT_NO_THROW(opt.Get("Bool")->GetBool());
|
||||
}
|
||||
|
||||
TEST_F(lagi_option, arrays) {
|
||||
agi::Options opt("", default_opt, agi::Options::FLUSH_SKIP);
|
||||
{ std::ifstream f("data/options/array_string.json"); EXPECT_NO_THROW(opt.ConfigNext(f)); }
|
||||
{ std::ifstream f("data/options/array_integer.json"); EXPECT_NO_THROW(opt.ConfigNext(f)); }
|
||||
{ std::ifstream f("data/options/array_double.json"); EXPECT_NO_THROW(opt.ConfigNext(f)); }
|
||||
{ std::ifstream f("data/options/array_bool.json"); EXPECT_NO_THROW(opt.ConfigNext(f)); }
|
||||
agi::Options opt("", all_types, agi::Options::FLUSH_SKIP);
|
||||
|
||||
EXPECT_NO_THROW(opt.Get("String")->GetListString());
|
||||
EXPECT_NO_THROW(opt.Get("Integer")->GetListInt());
|
||||
EXPECT_NO_THROW(opt.Get("Double")->GetListDouble());
|
||||
EXPECT_NO_THROW(opt.Get("Bool")->GetListBool());
|
||||
EXPECT_NO_THROW(opt.Get("Array/String")->GetListString());
|
||||
EXPECT_NO_THROW(opt.Get("Array/Integer")->GetListInt());
|
||||
EXPECT_NO_THROW(opt.Get("Array/Double")->GetListDouble());
|
||||
EXPECT_NO_THROW(opt.Get("Array/Boolean")->GetListBool());
|
||||
EXPECT_NO_THROW(opt.Get("Array/Color")->GetListColor());
|
||||
}
|
||||
|
||||
TEST_F(lagi_option, bad_default_throws_and_null_is_rejected) {
|
||||
|
@ -107,7 +105,7 @@ TEST_F(lagi_option, bad_default_throws_and_null_is_rejected) {
|
|||
}
|
||||
|
||||
TEST_F(lagi_option, nested_options) {
|
||||
const char conf[] = "{ \"a\" : { \"b\" : { \"c\" : { \"c\" : \"value\" } } } }";
|
||||
const char conf[] = R"raw({ "a" : { "b" : { "c" : { "c" : "value" } } } })raw";
|
||||
ASSERT_NO_THROW(agi::Options("", conf, agi::Options::FLUSH_SKIP));
|
||||
agi::Options opt("", conf, agi::Options::FLUSH_SKIP);
|
||||
ASSERT_NO_THROW(opt.Get("a/b/c/c"));
|
||||
|
@ -134,28 +132,22 @@ TEST_F(lagi_option, flush_roundtrip) {
|
|||
agi::fs::Remove("data/options/tmp");
|
||||
|
||||
{
|
||||
agi::Options opt("data/options/tmp", "{}");
|
||||
{ std::ifstream f("data/options/all_types.json"); EXPECT_NO_THROW(opt.ConfigNext(f)); }
|
||||
agi::Options opt("data/options/tmp", all_types);
|
||||
EXPECT_NO_THROW(opt.Get("Integer")->SetInt(1));
|
||||
EXPECT_NO_THROW(opt.Get("Double")->SetDouble(1.1));
|
||||
EXPECT_NO_THROW(opt.Get("String")->SetString("hello"));
|
||||
EXPECT_NO_THROW(opt.Get("Color")->SetColor(agi::Color("rgb(255,255,255)")));
|
||||
EXPECT_NO_THROW(opt.Get("Boolean")->SetBool(true));
|
||||
|
||||
std::vector<int64_t> int_arr; int_arr.push_back(1);
|
||||
EXPECT_NO_THROW(opt.Get("Array/Integer")->SetListInt(int_arr));
|
||||
std::vector<double> double_arr; double_arr.push_back(1.1);
|
||||
EXPECT_NO_THROW(opt.Get("Array/Double")->SetListDouble(double_arr));
|
||||
std::vector<std::string> str_arr; str_arr.push_back("hello");
|
||||
EXPECT_NO_THROW(opt.Get("Array/String")->SetListString(str_arr));
|
||||
std::vector<agi::Color> clr_arr; clr_arr.push_back(agi::Color("rgb(255,255,255)"));
|
||||
EXPECT_NO_THROW(opt.Get("Array/Color")->SetListColor(clr_arr));
|
||||
std::vector<bool> bool_arr; bool_arr.push_back(true);
|
||||
EXPECT_NO_THROW(opt.Get("Array/Boolean")->SetListBool(bool_arr));
|
||||
EXPECT_NO_THROW(opt.Get("Array/Integer")->SetListInt({1}));
|
||||
EXPECT_NO_THROW(opt.Get("Array/Double")->SetListDouble({1.1}));
|
||||
EXPECT_NO_THROW(opt.Get("Array/String")->SetListString({"hello"}));
|
||||
EXPECT_NO_THROW(opt.Get("Array/Color")->SetListColor({agi::Color("rgb(255,255,255)")}));
|
||||
EXPECT_NO_THROW(opt.Get("Array/Boolean")->SetListBool({true}));
|
||||
}
|
||||
|
||||
{
|
||||
agi::Options opt("data/options/tmp", "{}");
|
||||
agi::Options opt("data/options/tmp", all_types);
|
||||
ASSERT_NO_THROW(opt.ConfigUser());
|
||||
|
||||
EXPECT_EQ(1, opt.Get("Integer")->GetInt());
|
||||
|
@ -187,10 +179,6 @@ TEST_F(lagi_option, mixed_valid_and_invalid_in_user_conf_loads_all_valid) {
|
|||
EXPECT_EQ(true, opt.Get("3")->GetBool());
|
||||
}
|
||||
|
||||
TEST_F(lagi_option, empty_array_works) {
|
||||
EXPECT_NO_THROW(agi::Options("", "{ \"arr\" : [] }", agi::Options::FLUSH_SKIP));
|
||||
}
|
||||
|
||||
TEST_F(lagi_option, empty_object_works) {
|
||||
EXPECT_NO_THROW(agi::Options("", "{ \"obj\" : {} }", agi::Options::FLUSH_SKIP));
|
||||
}
|
||||
|
@ -215,60 +203,6 @@ struct empty_arr_options : public agi::Options {
|
|||
empty_arr_options() : agi::Options("", "{ \"arr\" : [] }", agi::Options::FLUSH_SKIP) { }
|
||||
};
|
||||
|
||||
TEST_F(lagi_option, empty_array_decays_to_first_used_type) {
|
||||
ASSERT_NO_THROW(empty_arr_options());
|
||||
|
||||
{
|
||||
empty_arr_options opt;
|
||||
EXPECT_NO_THROW(opt.Get("arr")->GetListBool());
|
||||
|
||||
EXPECT_THROW(opt.Get("arr")->GetListColor(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListDouble(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListInt(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListString(), agi::InternalError);
|
||||
}
|
||||
|
||||
{
|
||||
empty_arr_options opt;
|
||||
EXPECT_NO_THROW(opt.Get("arr")->GetListColor());
|
||||
|
||||
EXPECT_THROW(opt.Get("arr")->GetListBool(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListDouble(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListInt(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListString(), agi::InternalError);
|
||||
}
|
||||
|
||||
{
|
||||
empty_arr_options opt;
|
||||
EXPECT_NO_THROW(opt.Get("arr")->GetListDouble());
|
||||
|
||||
EXPECT_THROW(opt.Get("arr")->GetListBool(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListColor(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListInt(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListString(), agi::InternalError);
|
||||
}
|
||||
|
||||
{
|
||||
empty_arr_options opt;
|
||||
EXPECT_NO_THROW(opt.Get("arr")->GetListInt());
|
||||
|
||||
EXPECT_THROW(opt.Get("arr")->GetListBool(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListColor(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListDouble(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListString(), agi::InternalError);
|
||||
}
|
||||
|
||||
{
|
||||
empty_arr_options opt;
|
||||
EXPECT_NO_THROW(opt.Get("arr")->GetListString());
|
||||
|
||||
EXPECT_THROW(opt.Get("arr")->GetListBool(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListColor(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListDouble(), agi::InternalError);
|
||||
EXPECT_THROW(opt.Get("arr")->GetListInt(), agi::InternalError);
|
||||
}
|
||||
}
|
||||
|
||||
#define CHECK_TYPE(str, type) \
|
||||
do { \
|
||||
agi::Options opt("", "{ \"" str "\" : \"" str "\" }", agi::Options::FLUSH_SKIP); \
|
||||
|
|
Loading…
Reference in a new issue