From 5cf7ae14e44af42aea731163fccc1e3f859d61d3 Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Thu, 6 Oct 2016 20:15:31 +0100 Subject: [PATCH] Remove liblo_error error code Instead define a libloadorder_category error category to identify libloadorder errors. This allows the libloadorder error code to be preserved, and is more standard-c++-like. --- CMakeLists.txt | 3 ++ docs/api/reference.rst | 8 ++++ include/loot/api.h | 1 + include/loot/error.h | 2 - include/loot/error_categories.h | 41 ++++++++++++++++ src/backend/error_categories.cpp | 48 +++++++++++++++++++ src/backend/game/load_order_handler.cpp | 9 ++-- src/tests/backend/game/game_test.h | 4 +- .../backend/game/load_order_handler_test.h | 9 ++-- 9 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 include/loot/error_categories.h create mode 100644 src/backend/error_categories.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d16a6952..9c05dde6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -166,6 +166,7 @@ set (LOOT_SRC "${CMAKE_SOURCE_DIR}/src/backend/app/loot_paths.cpp" "${CMAKE_SOURCE_DIR}/src/backend/app/loot_settings.cpp" "${CMAKE_SOURCE_DIR}/src/backend/app/loot_state.cpp" "${CMAKE_BINARY_DIR}/generated/loot_version.cpp" + "${CMAKE_SOURCE_DIR}/src/backend/error_categories.cpp" "${CMAKE_SOURCE_DIR}/src/backend/metadata/condition_evaluator.cpp" "${CMAKE_SOURCE_DIR}/src/backend/metadata/conditional_metadata.cpp" "${CMAKE_SOURCE_DIR}/src/backend/metadata/file.cpp" @@ -219,6 +220,7 @@ set (LOOT_HEADERS "${CMAKE_SOURCE_DIR}/src/backend/app/loot_paths.h" "${CMAKE_SOURCE_DIR}/src/backend/helpers/yaml_set_helpers.h" "${CMAKE_SOURCE_DIR}/include/loot/api_decorator.h" "${CMAKE_SOURCE_DIR}/include/loot/error.h" + "${CMAKE_SOURCE_DIR}/include/loot/error_categories.h" "${CMAKE_SOURCE_DIR}/include/loot/game_type.h" "${CMAKE_SOURCE_DIR}/include/loot/language_code.h" "${CMAKE_SOURCE_DIR}/include/loot/loot_version.h" @@ -277,6 +279,7 @@ set (LOOT_API_HEADERS "${CMAKE_SOURCE_DIR}/include/loot/api.h" "${CMAKE_SOURCE_DIR}/include/loot/api_decorator.h" "${CMAKE_SOURCE_DIR}/include/loot/database_interface.h" "${CMAKE_SOURCE_DIR}/include/loot/error.h" + "${CMAKE_SOURCE_DIR}/include/loot/error_categories.h" "${CMAKE_SOURCE_DIR}/include/loot/game_type.h" "${CMAKE_SOURCE_DIR}/include/loot/language_code.h" "${CMAKE_SOURCE_DIR}/include/loot/loot_version.h" diff --git a/docs/api/reference.rst b/docs/api/reference.rst index c90ad33e..77f7bd91 100644 --- a/docs/api/reference.rst +++ b/docs/api/reference.rst @@ -48,3 +48,11 @@ Classes .. doxygenclass:: loot::LootVersion :members: + +Error Categories +================ + +LOOT uses error category objects to identify errors with codes that originate in +lower-level libraries. + +.. doxygenfunction:: loot::libloadorder_category diff --git a/include/loot/api.h b/include/loot/api.h index 6ae95a38..337096bd 100644 --- a/include/loot/api.h +++ b/include/loot/api.h @@ -31,6 +31,7 @@ #include "loot/api_decorator.h" #include "loot/database_interface.h" #include "loot/error.h" +#include "loot/error_categories.h" #include "loot/game_type.h" #include "loot/loot_version.h" diff --git a/include/loot/error.h b/include/loot/error.h index 5a67c476..94aa0a96 100644 --- a/include/loot/error.h +++ b/include/loot/error.h @@ -46,8 +46,6 @@ public: * failed, but its failure was not fatal to the task being performed. */ ok = 0, - /** An error was encountered when reading or writing the load order. */ - liblo_error = 1, /** An error was encountered when writing a file. */ path_write_fail = 2, /** An error was encountered when reading a file. */ diff --git a/include/loot/error_categories.h b/include/loot/error_categories.h new file mode 100644 index 00000000..5e4f0bba --- /dev/null +++ b/include/loot/error_categories.h @@ -0,0 +1,41 @@ +/* LOOT + + A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and + Fallout: New Vegas. + + Copyright (C) 2012-2016 WrinklyNinja + + This file is part of LOOT. + + LOOT is free software: you can redistribute + it and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + LOOT is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LOOT. If not, see + . + */ + +#ifndef LOOT_ERROR_CATEGORIES +#define LOOT_ERROR_CATEGORIES + +#include + +#include "loot/api_decorator.h" + +namespace loot { +/** @brief Get the error category that can be used to identify system_error + * exceptions that are due to libloadorder errors. + * @returns A reference to the static object of unspecified runtime type, + derived from std::error_category. + */ +LOOT_API const std::error_category& libloadorder_category(); +} + +#endif diff --git a/src/backend/error_categories.cpp b/src/backend/error_categories.cpp new file mode 100644 index 00000000..a49a5dcc --- /dev/null +++ b/src/backend/error_categories.cpp @@ -0,0 +1,48 @@ +/* LOOT + + A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and + Fallout: New Vegas. + + Copyright (C) 2012-2016 WrinklyNinja + + This file is part of LOOT. + + LOOT is free software: you can redistribute + it and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + LOOT is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LOOT. If not, see + . + */ + +#include "loot/error_categories.h" + +namespace loot { +namespace detail { +class libloadorder_category : public std::error_category { + virtual const char* name() const noexcept { + return "libloadorder"; + } + + virtual std::string message(int ev) const { + return "Libloadorder error"; + } + + virtual bool equivalent(const std::error_code& code, int condition) const noexcept { + return code.category().name() == name(); + } +}; +} + +LOOT_API const std::error_category& libloadorder_category() { + static detail::libloadorder_category instance; + return instance; +} +} diff --git a/src/backend/game/load_order_handler.cpp b/src/backend/game/load_order_handler.cpp index e2e24931..4e6b9913 100644 --- a/src/backend/game/load_order_handler.cpp +++ b/src/backend/game/load_order_handler.cpp @@ -29,6 +29,7 @@ #include #include "loot/error.h" +#include "loot/error_categories.h" using boost::locale::translate; using std::string; @@ -91,7 +92,7 @@ void LoadOrderHandler::Init(const GameSettings& game, const boost::filesystem::p err = translate("libloadorder failed to create a game handle. Details:").str() + " " + e; } lo_cleanup(); - throw Error(Error::Code::liblo_error, err); + throw std::system_error(ret, libloadorder_category(), err); } } @@ -112,7 +113,7 @@ bool LoadOrderHandler::IsPluginActive(const std::string& pluginName) const { err = translate("libloadorder failed to check if a plugin is active. Details:").str() + " " + e; } lo_cleanup(); - throw Error(Error::Code::liblo_error, err); + throw std::system_error(ret, libloadorder_category(), err); } return result; @@ -137,7 +138,7 @@ std::vector LoadOrderHandler::GetLoadOrder() const { err = translate("libloadorder failed to get the load order. Details:").str() + " " + e; } lo_cleanup(); - throw Error(Error::Code::liblo_error, err); + throw std::system_error(ret, libloadorder_category(), err); } std::vector loadOrder; @@ -163,7 +164,7 @@ void LoadOrderHandler::SetLoadOrder(const char * const * const loadOrder, const err = translate("libloadorder failed to set the load order. Details:").str() + " " + e; } lo_cleanup(); - throw Error(Error::Code::liblo_error, err); + throw std::system_error(ret, libloadorder_category(), err); } } diff --git a/src/tests/backend/game/game_test.h b/src/tests/backend/game/game_test.h index 45ec6218..db86be54 100644 --- a/src/tests/backend/game/game_test.h +++ b/src/tests/backend/game/game_test.h @@ -98,7 +98,7 @@ TEST_P(GameTest, initShouldThrowOnLinuxIfGamePathIsNotGiven) { TEST_P(GameTest, initShouldThrowOnLinuxIfLocalPathIsNotGiven) { Game game = Game(GetParam()).SetGamePath(dataPath.parent_path()); ASSERT_FALSE(boost::filesystem::exists(LootPaths::getLootDataPath() / game.FolderName())); - EXPECT_THROW(game.Init(false), Error); + EXPECT_THROW(game.Init(false), std::system_error); } // Testing on Windows will find real LOOT installs, and they shouldn't be @@ -139,7 +139,7 @@ TEST_P(GameTest, redatePluginsShouldThrowIfTheGameHasNotYetBeenInitialisedForSky game.SetGamePath(dataPath.parent_path()); if (GetParam() == GameType::tes5) - EXPECT_THROW(game.RedatePlugins(), Error); + EXPECT_THROW(game.RedatePlugins(), std::system_error); else EXPECT_NO_THROW(game.RedatePlugins()); } diff --git a/src/tests/backend/game/load_order_handler_test.h b/src/tests/backend/game/load_order_handler_test.h index 454b559f..71455483 100644 --- a/src/tests/backend/game/load_order_handler_test.h +++ b/src/tests/backend/game/load_order_handler_test.h @@ -27,7 +27,6 @@ along with LOOT. If not, see #include "backend/game/load_order_handler.h" -#include "loot/error.h" #include "tests/common_game_test_fixture.h" namespace loot { @@ -62,7 +61,7 @@ TEST_P(LoadOrderHandlerTest, initShouldThrowOnLinuxIfNoLocalPathIsSet) { GameSettings game(GetParam()); game.SetGamePath(dataPath.parent_path()); - EXPECT_THROW(loadOrderHandler_.Init(game), Error); + EXPECT_THROW(loadOrderHandler_.Init(game), std::system_error); } #endif @@ -74,7 +73,7 @@ TEST_P(LoadOrderHandlerTest, initShouldNotThrowIfAValidGameIdAndGamePathAndLocal } TEST_P(LoadOrderHandlerTest, isPluginActiveShouldThrowIfTheHandlerHasNotBeenInitialised) { - EXPECT_THROW(loadOrderHandler_.IsPluginActive(masterFile), Error); + EXPECT_THROW(loadOrderHandler_.IsPluginActive(masterFile), std::system_error); } TEST_P(LoadOrderHandlerTest, isPluginActiveShouldReturnCorrectPluginStatesAfterInitialisation) { @@ -88,7 +87,7 @@ TEST_P(LoadOrderHandlerTest, isPluginActiveShouldReturnCorrectPluginStatesAfterI } TEST_P(LoadOrderHandlerTest, getLoadOrderShouldThrowIfTheHandlerHasNotBeenInitialised) { - EXPECT_THROW(loadOrderHandler_.GetLoadOrder(), Error); + EXPECT_THROW(loadOrderHandler_.GetLoadOrder(), std::system_error); } TEST_P(LoadOrderHandlerTest, getLoadOrderShouldReturnTheCurrentLoadOrder) { @@ -114,7 +113,7 @@ TEST_P(LoadOrderHandlerTest, setLoadOrderShouldThrowIfTheHandlerHasNotBeenInitia blankPluginDependentEsp, }); - EXPECT_THROW(loadOrderHandler_.SetLoadOrder(loadOrder), Error); + EXPECT_THROW(loadOrderHandler_.SetLoadOrder(loadOrder), std::system_error); } TEST_P(LoadOrderHandlerTest, setLoadOrderShouldSetTheLoadOrder) {