diff --git a/libaegisub/common/cajun/elements.cpp b/libaegisub/common/cajun/elements.cpp index 44103655a..b8f5a0174 100644 --- a/libaegisub/common/cajun/elements.cpp +++ b/libaegisub/common/cajun/elements.cpp @@ -12,80 +12,59 @@ Author: Terry Caton #include 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 - struct CastVisitor final : public CastVisitorBase { - T *element = nullptr; - void Visit(T& ele) { element = &ele; } - }; +template +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 -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(*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 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())) {} +UnknownElement::UnknownElement(UnknownElement&& unknown) : m_pImp(std::move(unknown.m_pImp)) {} +UnknownElement::UnknownElement(int number) : m_pImp(new Imp_T(number)) {} +UnknownElement::UnknownElement(const char *string) : m_pImp(new Imp_T(string)) {} -UnknownElement::UnknownElement() : m_pImp(new Imp_T(Null())) {} -UnknownElement::UnknownElement(const UnknownElement& unknown) : m_pImp(unknown.m_pImp->Clone()) {} -UnknownElement::UnknownElement(int number) : m_pImp(new Imp_T(number)) {} -UnknownElement::UnknownElement(const char *string) : m_pImp(new Imp_T(string)) {} UnknownElement::~UnknownElement() { } #define DEFINE_UE_TYPE(Type) \ - UnknownElement::UnknownElement(Type const& val) : m_pImp(new Imp_T(val)) { } \ + UnknownElement::UnknownElement(Type val) : m_pImp(new Imp_T(std::move(val))) { } \ UnknownElement::operator Type const&() const { return CastTo(); } \ UnknownElement::operator Type&() { return CastTo(); } @@ -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()[key]; -} - -const UnknownElement& UnknownElement::operator[] (const std::string& key) const -{ - // throws if we aren't an object - Object const& obj = CastTo(); - Object::const_iterator it = obj.find(key); - if (it == obj.end()) - throw Exception("Object member not found: " + key); - return it->second; -} - template -ElementTypeT const& UnknownElement::CastTo() const -{ - CastVisitor castVisitor; - Accept(castVisitor); +ElementTypeT const& UnknownElement::CastTo() const { + CastVisitor castVisitor; + const_cast(this)->Accept(castVisitor); if (!castVisitor.element) throw Exception("Bad cast"); return *castVisitor.element; } template -ElementTypeT& UnknownElement::CastTo() -{ +ElementTypeT& UnknownElement::CastTo() { CastVisitor 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 diff --git a/libaegisub/common/cajun/reader.cpp b/libaegisub/common/cajun/reader.cpp index 0f2102c83..27247ddaf 100644 --- a/libaegisub/common/cajun/reader.cpp +++ b/libaegisub/common/cajun/reader.cpp @@ -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) { diff --git a/libaegisub/common/hotkey.cpp b/libaegisub/common/hotkey.cpp index 538beb1bf..f420f5d7a 100644 --- a/libaegisub/common/hotkey.cpp +++ b/libaegisub/common/hotkey.cpp @@ -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 default_config) +Hotkey::Hotkey(fs::path const& file, std::pair 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(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 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) { diff --git a/libaegisub/common/mru.cpp b/libaegisub/common/mru.cpp index 1d589f388..ac5520ce7 100644 --- a/libaegisub/common/mru.cpp +++ b/libaegisub/common/mru.cpp @@ -38,8 +38,8 @@ MRUManager::MRUManager(agi::fs::path const& config, std::pair(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."); diff --git a/libaegisub/common/option.cpp b/libaegisub/common/option.cpp index 43689fac4..0fda90e4f 100644 --- a/libaegisub/common/option.cpp +++ b/libaegisub/common/option.cpp @@ -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 @@ -163,7 +163,7 @@ void put_array(json::Object &obj, const std::string &path, const char *element_k static_cast(array.back())[element_key] = (json::UnknownElement)elem; } - put_option(obj, path, array); + put_option(obj, path, std::move(array)); } struct option_name_cmp { diff --git a/libaegisub/include/libaegisub/cajun/elements.h b/libaegisub/include/libaegisub/cajun/elements.h index 490c6a987..1ba4b0696 100644 --- a/libaegisub/include/libaegisub/cajun/elements.h +++ b/libaegisub/include/libaegisub/cajun/elements.h @@ -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 - UnknownElement& operator[] (const char(&key)[N]) { return operator[](std::string(key)); } - template - 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 - class Imp_T; +private: + UnknownElement(UnknownElement const& unknown) = delete; template 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 diff --git a/src/dialog_shift_times.cpp b/src/dialog_shift_times.cpp index 8d7f00799..c30c86f6a 100644 --- a/src/dialog_shift_times.cpp +++ b/src/dialog_shift_times.cpp @@ -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(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(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(); } diff --git a/src/menu.cpp b/src/menu.cpp index ee251bfc8..3f83154da 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -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(agi::json_util::file(config::path->Decode("?user/menu.json"), GET_DEFAULT_CONFIG(default_menu)))); return root; } catch (json::Reader::ParseException const& e) { diff --git a/src/toolbar.cpp b/src/toolbar.cpp index 9ad945056..5718b19d5 100644 --- a/src/toolbar.cpp +++ b/src/toolbar.cpp @@ -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(agi::json_util::parse(stream))); } return root; } diff --git a/tests/options/all_types.json b/tests/options/all_types.json deleted file mode 100644 index 6cfc5865d..000000000 --- a/tests/options/all_types.json +++ /dev/null @@ -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 } ] - } -} diff --git a/tests/options/array_bool.json b/tests/options/array_bool.json deleted file mode 100644 index 8b5122fcc..000000000 --- a/tests/options/array_bool.json +++ /dev/null @@ -1 +0,0 @@ -{"Bool" : [{"bool" : true}, {"bool" : true}]} diff --git a/tests/options/array_double.json b/tests/options/array_double.json deleted file mode 100644 index 8e0102f90..000000000 --- a/tests/options/array_double.json +++ /dev/null @@ -1 +0,0 @@ -{"Double" : [{"double" : 2.1}, {"double" : 2.1}]} diff --git a/tests/options/array_integer.json b/tests/options/array_integer.json deleted file mode 100644 index b6282a061..000000000 --- a/tests/options/array_integer.json +++ /dev/null @@ -1 +0,0 @@ -{"Integer" : [{"int" : 1}, {"int" : 1}]} diff --git a/tests/options/array_string.json b/tests/options/array_string.json deleted file mode 100644 index 480a475c4..000000000 --- a/tests/options/array_string.json +++ /dev/null @@ -1 +0,0 @@ -{"String" : [{"string" : "This is a test"}, {"string" : "This is a test"}]} diff --git a/tests/options/bool.json b/tests/options/bool.json deleted file mode 100644 index 5a0d659d7..000000000 --- a/tests/options/bool.json +++ /dev/null @@ -1 +0,0 @@ -{"Bool" : true} diff --git a/tests/options/double.json b/tests/options/double.json deleted file mode 100644 index f90527a79..000000000 --- a/tests/options/double.json +++ /dev/null @@ -1 +0,0 @@ -{"Double" : 2.1} diff --git a/tests/options/integer.json b/tests/options/integer.json deleted file mode 100644 index 2e0b3ebc4..000000000 --- a/tests/options/integer.json +++ /dev/null @@ -1 +0,0 @@ -{"Integer" : 1} diff --git a/tests/tests/cajun.cpp b/tests/tests/cajun.cpp index b843cd8e9..f968c6879 100644 --- a/tests/tests/cajun.cpp +++ b/tests/tests/cajun.cpp @@ -25,78 +25,9 @@ #include #include -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(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(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(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(obj["Integer"])); @@ -177,7 +94,7 @@ TEST_F(lagi_cajun, ObjectStoreInteger) { EXPECT_THROW(static_cast(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(obj["Double"])); @@ -189,7 +106,7 @@ TEST_F(lagi_cajun, ObjectStoreDouble) { EXPECT_THROW(static_cast(obj["Double"]), json::Exception); } -TEST_F(lagi_cajun, ObjectStoreString) { +TEST(lagi_cajun, ObjectStoreString) { json::Object obj; obj["String"] = "test"; EXPECT_STREQ("test", static_cast(obj["String"]).c_str()); @@ -201,7 +118,7 @@ TEST_F(lagi_cajun, ObjectStoreString) { EXPECT_THROW(static_cast(obj["String"]), json::Exception); } -TEST_F(lagi_cajun, ObjectStoreBoolean) { +TEST(lagi_cajun, ObjectStoreBoolean) { json::Object obj; obj["Boolean"] = true; EXPECT_TRUE(static_cast(obj["Boolean"])); @@ -213,7 +130,7 @@ TEST_F(lagi_cajun, ObjectStoreBoolean) { EXPECT_THROW(static_cast(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(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(array[0]["Inside"]).c_str()); + EXPECT_STREQ("", static_cast(static_cast(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(obj["String"]).c_str()); EXPECT_FALSE(static_cast(obj["Boolean"])); EXPECT_NO_THROW(static_cast(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()); } diff --git a/tests/tests/option.cpp b/tests/tests/option.cpp index efa8d45bf..334c5b4c4 100644 --- a/tests/tests/option.cpp +++ b/tests/tests/option.cpp @@ -22,6 +22,20 @@ #include 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 int_arr; int_arr.push_back(1); - EXPECT_NO_THROW(opt.Get("Array/Integer")->SetListInt(int_arr)); - std::vector double_arr; double_arr.push_back(1.1); - EXPECT_NO_THROW(opt.Get("Array/Double")->SetListDouble(double_arr)); - std::vector str_arr; str_arr.push_back("hello"); - EXPECT_NO_THROW(opt.Get("Array/String")->SetListString(str_arr)); - std::vector 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_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); \