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) {