diff --git a/docs/BOSS API Readme.html b/docs/BOSS API Readme.html
index b05fc890..bff43ed7 100644
--- a/docs/BOSS API Readme.html
+++ b/docs/BOSS API Readme.html
@@ -135,6 +135,7 @@ This documentation is a work in progress, covering an API that is also still a w
| BOSS_API_RETURN_MAX | Matches the value of the highest-numbered return code.
The following codes are used with boss_create_db to specify the game that the API acts for.
@@ -159,7 +160,7 @@ This documentation is a work in progress, covering an API that is also still a w
Error Handling Functions
- unsigned int boss_get_error_message (char ** message);
+ unsigned int boss_get_error_message (const char ** const message);
Outputs a string detailing the last error encountered.
- message - A pointer to the error string outputted.
@@ -183,9 +184,9 @@ This documentation is a work in progress, covering an API that is also still a w
- unsigned int boss_get_version (unsigned int * versionMajor,
- unsigned int * versionMinor,
- unsigned int * versionPatch);
+ unsigned int boss_get_version (unsigned int * const versionMajor,
+ unsigned int * const versionMinor,
+ unsigned int * const versionPatch);
Gets the version numbers of the API in use.
- versionMajor - A pointer to the major version number (major.minor.patch).
@@ -196,9 +197,9 @@ This documentation is a work in progress, covering an API that is also still a w
Lifecycle Management Functions
- unsigned int boss_create_db (boss_db * db,
+unsigned int boss_create_db (boss_db * const db,
const unsigned int clientGame,
- const char * gamePath);
+ const char * const gamePath);
Creates a database for the specified game. You can create multiple databases.
- db - A pointer to the database to be created.
@@ -217,8 +218,8 @@ This documentation is a work in progress, covering an API that is also still a w
Database Loading Functions
unsigned int boss_load_lists (boss_db db,
- const char * masterlistPath,
- const char * userlistPath);
+ const char * const masterlistPath,
+ const char * const userlistPath);
Loads the given masterlist and userlist for the game specified when the given database was created. Also frees any memory currently allocated to the given database by any access functions previously called. Can be called multiple times. If an error is encountered, the database remains unchanged.
- db - The database the function acts on.
@@ -237,8 +238,8 @@ This documentation is a work in progress, covering an API that is also still a w
Database Access Functions
unsigned int boss_get_tag_map (boss_db db,
- char *** tagMap,
- size_t * numTags);
+ char *** const tagMap,
+ size_t * const numTags);
Outputs an array of the Bash Tags that are suggested in the masterlist and userlist. This function must be called prior to calling boss_get_plugin_tags to ensure that the latter can return the Tags using the correct array indicies.
- db - The database the function acts on.
@@ -248,12 +249,12 @@ This documentation is a work in progress, covering an API that is also still a w
unsigned int boss_get_plugin_messages (boss_db db,
- const char * plugin,
- boss_message ** messages,
- size_t * numMessages);
+ const char * const plugin,
+ boss_message ** const messages,
+ size_t * const numMessages);
Outputs the messages associated with the given plugin in the masterlist and/or userlist.
- db - The database the function acts on.
@@ -280,7 +281,7 @@ This documentation is a work in progress, covering an API that is also still a w
unsigned int boss_write_minimal_list (boss_db db,
- const char * outputFile,
+ const char * const outputFile,
const bool overwrite);
Writes a minimal metadata file that only contains plugins with Bash Tag suggestions and/or warning messages about dirtiness, plus the suggestions and messages themselves.
diff --git a/src/api.cpp b/src/api.cpp
index 21ab2a55..e55cfac1 100644
--- a/src/api.cpp
+++ b/src/api.cpp
@@ -26,6 +26,7 @@
#include "game.h"
#include "metadata.h"
#include "parsers.h"
+#include "error.h"
#include
@@ -42,22 +43,23 @@
#include
#include
-const unsigned int BOSS_API_OK = 0;
-const unsigned int BOSS_API_ERROR_LIBLO_ERROR = 1;
-const unsigned int BOSS_API_ERROR_FILE_WRITE_FAIL = 2;
-const unsigned int BOSS_API_ERROR_PARSE_FAIL = 3;
-const unsigned int BOSS_API_ERROR_CONDITION_EVAL_FAIL = 4;
-const unsigned int BOSS_API_ERROR_REGEX_EVAL_FAIL = 5;
-const unsigned int BOSS_API_ERROR_NO_MEM = 6;
-const unsigned int BOSS_API_ERROR_INVALID_ARGS = 7;
-const unsigned int BOSS_API_ERROR_NO_TAG_MAP = 8;
-const unsigned int BOSS_API_RETURN_MAX = BOSS_API_ERROR_NO_TAG_MAP;
+const unsigned int BOSS_API_OK = boss::OK;
+const unsigned int BOSS_API_ERROR_LIBLO_ERROR = boss::ERROR_LIBLO_ERROR;
+const unsigned int BOSS_API_ERROR_FILE_WRITE_FAIL = boss::ERROR_PATH_WRITE_FAIL;
+const unsigned int BOSS_API_ERROR_PARSE_FAIL = boss::ERROR_PATH_READ_FAIL;
+const unsigned int BOSS_API_ERROR_CONDITION_EVAL_FAIL = boss::ERROR_CONDITION_EVAL_FAIL;
+const unsigned int BOSS_API_ERROR_REGEX_EVAL_FAIL = boss::ERROR_REGEX_EVAL_FAIL;
+const unsigned int BOSS_API_ERROR_NO_MEM = boss::ERROR_NO_MEM;
+const unsigned int BOSS_API_ERROR_INVALID_ARGS = boss::ERROR_INVALID_ARGS;
+const unsigned int BOSS_API_ERROR_NO_TAG_MAP = boss::ERROR_NO_TAG_MAP;
+const unsigned int BOSS_API_ERROR_PATH_NOT_FOUND = boss::ERROR_PATH_NOT_FOUND;
+const unsigned int BOSS_API_RETURN_MAX = BOSS_API_ERROR_PATH_NOT_FOUND;
// The following are the games identifiers used by the API.
-const unsigned int BOSS_API_GAME_TES4 = BOSS_GAME_TES4;
-const unsigned int BOSS_API_GAME_TES5 = BOSS_GAME_TES5;
-const unsigned int BOSS_API_GAME_FO3 = BOSS_GAME_FO3;
-const unsigned int BOSS_API_GAME_FONV = BOSS_GAME_FONV;
+const unsigned int BOSS_API_GAME_TES4 = boss::GAME_TES4;
+const unsigned int BOSS_API_GAME_TES5 = boss::GAME_TES5;
+const unsigned int BOSS_API_GAME_FO3 = boss::GAME_FO3;
+const unsigned int BOSS_API_GAME_FONV = boss::GAME_FONV;
// BOSS message types.
const unsigned int BOSS_API_MESSAGE_SAY = 1;
@@ -104,7 +106,7 @@ struct _boss_db_int {
size_t extMessageArraySize;
};
-char * extMessageStr;
+const char * extMessageStr = NULL;
// std::string to null-terminated char string converter.
char * ToNewCString(std::string str) {
@@ -119,18 +121,18 @@ char * ToNewCString(std::string str) {
// Outputs a string giving the details of the last time an error or
// warning return code was returned by a function. The string exists
// until this function is called again or until CleanUpAPI is called.
-BOSS_API unsigned int boss_get_error_message (char ** message) {
+BOSS_API unsigned int boss_get_error_message (const char ** const message) {
if (message == NULL)
return BOSS_API_ERROR_INVALID_ARGS;
- *message = "Something went wrong.";
+ *message = extMessageStr;
return BOSS_API_OK;
}
// Frees memory allocated to error string.
BOSS_API void boss_cleanup () {
- delete[] extMessageStr;
+ delete [] extMessageStr;
}
@@ -141,19 +143,19 @@ BOSS_API void boss_cleanup () {
// Returns whether this version of BOSS supports the API from the given
// BOSS version. Abstracts BOSS API stability policy away from clients.
BOSS_API bool boss_is_compatible (const unsigned int versionMajor, const unsigned int versionMinor, const unsigned int versionPatch) {
- return versionMajor == BOSS_VERSION_MAJOR && versionMinor == BOSS_VERSION_MINOR;
+ return versionMajor == boss::VERSION_MAJOR && versionMinor == boss::VERSION_MINOR;
}
// Returns the version string for this version of BOSS.
// The string exists until this function is called again or until
// CleanUpAPI is called.
-BOSS_API unsigned int boss_get_version (unsigned int * versionMajor, unsigned int * versionMinor, unsigned int * versionPatch) {
+BOSS_API unsigned int boss_get_version (unsigned int * const versionMajor, unsigned int * const versionMinor, unsigned int * const versionPatch) {
if (versionMajor == NULL || versionMinor == NULL || versionPatch == NULL)
return BOSS_API_ERROR_INVALID_ARGS;
- *versionMajor = BOSS_VERSION_MAJOR;
- *versionMinor = BOSS_VERSION_MINOR;
- *versionPatch = BOSS_VERSION_PATCH;
+ *versionMajor = boss::VERSION_MAJOR;
+ *versionMinor = boss::VERSION_MINOR;
+ *versionPatch = boss::VERSION_PATCH;
return BOSS_API_OK;
}
@@ -170,7 +172,7 @@ BOSS_API unsigned int boss_get_version (unsigned int * versionMajor, unsigned in
// plugins.txt and loadorder.txt (if they both exist) are in sync. If
// dataPath == NULL then the API will attempt to detect the data path of
// the specified game.
-BOSS_API unsigned int boss_create_db (boss_db * db, const unsigned int clientGame, const char * gamePath) {
+BOSS_API unsigned int boss_create_db (boss_db * const db, const unsigned int clientGame, const char * const gamePath) {
if (db == NULL || (clientGame != BOSS_API_GAME_TES4 && clientGame != BOSS_API_GAME_TES5 && clientGame != BOSS_API_GAME_FO3 && clientGame != BOSS_API_GAME_FONV))
return BOSS_API_ERROR_INVALID_ARGS;
@@ -187,15 +189,17 @@ BOSS_API unsigned int boss_create_db (boss_db * db, const unsigned int clientGam
boss::Game game;
try {
game = boss::Game(clientGame, game_path); //This also checks to see if the game is installed if game_path is empty and throws an exception if it is not detected.
- } catch (std::runtime_error& e) {
- return BOSS_API_ERROR_INVALID_ARGS;
+ } catch (boss::error& e) {
+ extMessageStr = e.what();
+ return e.code();
}
boss_db retVal;
try {
retVal = new _boss_db_int;
- } catch (std::bad_alloc /*&e*/) {
- return BOSS_API_ERROR_INVALID_ARGS;
+ } catch (std::bad_alloc& e) {
+ extMessageStr = e.what();
+ return BOSS_API_ERROR_NO_MEM;
}
retVal->game = game;
*db = retVal;
@@ -217,8 +221,8 @@ BOSS_API void boss_destroy_db (boss_db db) {
// Can be called multiple times. On error, the database is unchanged.
// Paths are case-sensitive if the underlying filesystem is case-sensitive.
// masterlistPath and userlistPath are files.
-BOSS_API unsigned int boss_load_lists (boss_db db, const char * masterlistPath,
- const char * userlistPath) {
+BOSS_API unsigned int boss_load_lists (boss_db db, const char * const masterlistPath,
+ const char * const userlistPath) {
if (db == NULL || masterlistPath == NULL)
return BOSS_API_ERROR_INVALID_ARGS;
@@ -230,8 +234,9 @@ BOSS_API unsigned int boss_load_lists (boss_db db, const char * masterlistPath,
tempNode = YAML::LoadFile(userlistPath);
userTemp = tempNode["plugins"].as< std::list >();
- } catch (YAML::Exception &e) {
- return BOSS_API_ERROR_INVALID_ARGS;
+ } catch (YAML::Exception& e) {
+ extMessageStr = e.what();
+ return BOSS_API_ERROR_PARSE_FAIL;
}
//Also free memory.
@@ -276,8 +281,9 @@ BOSS_API unsigned int boss_eval_lists (boss_db db) {
boost::regex regex;
try {
regex = boost::regex(it->Name(), boost::regex::extended|boost::regex::icase);
- } catch (boost::regex_error e) {
- return BOSS_API_ERROR_INVALID_ARGS;
+ } catch (boost::regex_error& e) {
+ extMessageStr = e.what();
+ return BOSS_API_ERROR_REGEX_EVAL_FAIL;
}
for (boost::filesystem::directory_iterator itr(db->game.DataPath()); itr != boost::filesystem::directory_iterator(); ++itr) {
@@ -292,8 +298,9 @@ BOSS_API unsigned int boss_eval_lists (boss_db db) {
--it;
}
}
- } catch (std::runtime_error& e) {
- return BOSS_API_ERROR_INVALID_ARGS;
+ } catch (boss::error& e) {
+ extMessageStr = e.what();
+ return e.code();
}
db->metadata = temp;
@@ -305,7 +312,8 @@ BOSS_API unsigned int boss_eval_lists (boss_db db) {
boost::regex regex;
try {
regex = boost::regex(it->Name(), boost::regex::extended|boost::regex::icase);
- } catch (boost::regex_error e) {
+ } catch (boost::regex_error& e) {
+ extMessageStr = e.what();
return BOSS_API_ERROR_INVALID_ARGS;
}
@@ -321,8 +329,9 @@ BOSS_API unsigned int boss_eval_lists (boss_db db) {
--it;
}
}
- } catch (std::runtime_error& e) {
- return BOSS_API_ERROR_INVALID_ARGS;
+ } catch (boss::error& e) {
+ extMessageStr = e.what();
+ return e.code();
}
db->userMetadata = temp;
@@ -337,7 +346,7 @@ BOSS_API unsigned int boss_eval_lists (boss_db db) {
// Returns an array of the Bash Tags encounterred when loading the masterlist
// and userlist, and the number of tags in the returned array. The array and
// its contents are static and should not be freed by the client.
-BOSS_API unsigned int boss_get_tag_map (boss_db db, char *** tagMap, size_t * numTags) {
+BOSS_API unsigned int boss_get_tag_map (boss_db db, char *** const tagMap, size_t * const numTags) {
if (db == NULL || tagMap == NULL || numTags == NULL)
return BOSS_API_ERROR_INVALID_ARGS;
@@ -373,8 +382,9 @@ BOSS_API unsigned int boss_get_tag_map (boss_db db, char *** tagMap, size_t * nu
try {
db->extTagMap = new char*[allTags.size()];
- } catch (std::bad_alloc /*&e*/) {
- return BOSS_API_ERROR_INVALID_ARGS;
+ } catch (std::bad_alloc& e) {
+ extMessageStr = e.what();
+ return BOSS_API_ERROR_NO_MEM;
}
unsigned int UID = 0;
@@ -385,8 +395,9 @@ BOSS_API unsigned int boss_get_tag_map (boss_db db, char *** tagMap, size_t * nu
db->extTagMap[UID] = ToNewCString(*it);
UID++;
}
- } catch (std::bad_alloc /*&e*/) {
- return BOSS_API_ERROR_INVALID_ARGS;
+ } catch (std::bad_alloc& e) {
+ extMessageStr = e.what();
+ return BOSS_API_ERROR_NO_MEM;
}
*tagMap = db->extTagMap;
@@ -402,12 +413,12 @@ BOSS_API unsigned int boss_get_tag_map (boss_db db, char *** tagMap, size_t * nu
// case-insensitive. If no Tags are found for an array, the array pointer (*tagIds)
// will be NULL. The userlistModified bool is true if the userlist contains Bash Tag
// suggestion message additions.
-BOSS_API unsigned int boss_get_plugin_tags (boss_db db, const char * plugin,
- unsigned int ** tagIds_added,
- size_t * numTags_added,
- unsigned int **tagIds_removed,
- size_t * numTags_removed,
- bool * userlistModified) {
+BOSS_API unsigned int boss_get_plugin_tags (boss_db db, const char * const plugin,
+ unsigned int ** const tagIds_added,
+ size_t * const numTags_added,
+ unsigned int ** const tagIds_removed,
+ size_t * const numTags_removed,
+ bool * const userlistModified) {
if (db == NULL || plugin == NULL || tagIds_added == NULL || numTags_added == NULL || tagIds_removed == NULL || numTags_removed == NULL || userlistModified == NULL)
return BOSS_API_ERROR_INVALID_ARGS;
@@ -469,8 +480,9 @@ BOSS_API unsigned int boss_get_plugin_tags (boss_db db, const char * plugin,
for (size_t i=0; i < numRemoved; i++)
db->extRemovedTagIds[i] = tagsRemovedIDs[i];
}
- } catch (std::bad_alloc /*&e*/) {
- return BOSS_API_ERROR_INVALID_ARGS;
+ } catch (std::bad_alloc& e) {
+ extMessageStr = e.what();
+ return BOSS_API_ERROR_NO_MEM;
}
//Set outputs.
@@ -485,9 +497,9 @@ BOSS_API unsigned int boss_get_plugin_tags (boss_db db, const char * plugin,
// Returns the messages attached to the given plugin. Messages are valid until Load,
// DestroyBossDb or GetPluginMessages are next called. plugin is case-insensitive.
// If no messages are attached, *messages will be NULL and numMessages will equal 0.
-BOSS_API unsigned int boss_get_plugin_messages (boss_db db, const char * plugin,
- boss_message ** messages,
- size_t * numMessages) {
+BOSS_API unsigned int boss_get_plugin_messages (boss_db db, const char * const plugin,
+ boss_message ** const messages,
+ size_t * const numMessages) {
if (db == NULL || plugin == NULL || messages == NULL || numMessages == NULL)
return BOSS_API_ERROR_INVALID_ARGS;
@@ -526,8 +538,9 @@ BOSS_API unsigned int boss_get_plugin_messages (boss_db db, const char * plugin,
db->extMessageArray[i].type = BOSS_API_MESSAGE_ERROR;
db->extMessageArray[i].message = ToNewCString(it->Content());
}
- } catch (std::bad_alloc /*&e*/) {
- return BOSS_API_ERROR_INVALID_ARGS;
+ } catch (std::bad_alloc& e) {
+ extMessageStr = e.what();
+ return BOSS_API_ERROR_NO_MEM;
}
*messages = db->extMessageArray;
@@ -540,7 +553,7 @@ BOSS_API unsigned int boss_get_plugin_messages (boss_db db, const char * plugin,
// and/or dirty messages, plus the Tag suggestions and/or messages themselves and their
// conditions, in order to create the Wrye Bash taglist. outputFile is the path to use
// for output. If outputFile already exists, it will only be overwritten if overwrite is true.
-BOSS_API unsigned int boss_write_minimal_list (boss_db db, const char * outputFile, const bool overwrite) {
+BOSS_API unsigned int boss_write_minimal_list (boss_db db, const char * const outputFile, const bool overwrite) {
if (db == NULL || outputFile == NULL)
return BOSS_API_ERROR_INVALID_ARGS;
diff --git a/src/api.h b/src/api.h
index 2f72c245..59779dd4 100644
--- a/src/api.h
+++ b/src/api.h
@@ -92,6 +92,7 @@ BOSS_API extern const unsigned int BOSS_API_ERROR_REGEX_EVAL_FAIL;
BOSS_API extern const unsigned int BOSS_API_ERROR_NO_MEM;
BOSS_API extern const unsigned int BOSS_API_ERROR_INVALID_ARGS;
BOSS_API extern const unsigned int BOSS_API_ERROR_NO_TAG_MAP;
+BOSS_API extern const unsigned int BOSS_API_ERROR_PATH_NOT_FOUND;
BOSS_API extern const unsigned int BOSS_API_RETURN_MAX;
// The following are the games identifiers used by the API.
@@ -114,7 +115,7 @@ BOSS_API extern const unsigned int BOSS_API_MESSAGE_ERROR;
// Outputs a string giving the details of the last time an error or
// warning return code was returned by a function. The string exists
// until this function is called again or until boss_cleanup is called.
-BOSS_API unsigned int boss_get_error_message (char ** message);
+BOSS_API unsigned int boss_get_error_message (const char ** const message);
// Frees memory allocated to error string.
BOSS_API void boss_cleanup ();
@@ -131,7 +132,7 @@ BOSS_API bool boss_is_compatible (const unsigned int versionMajor, const unsigne
// Returns the version string for this version of BOSS.
// The string exists until this function is called again or until
// CleanUpAPI is called.
-BOSS_API unsigned int boss_get_version (unsigned int * versionMajor, unsigned int * versionMinor, unsigned int * versionPatch);
+BOSS_API unsigned int boss_get_version (unsigned int * const versionMajor, unsigned int * const versionMinor, unsigned int * const versionPatch);
////////////////////////////////////
@@ -145,7 +146,7 @@ BOSS_API unsigned int boss_get_version (unsigned int * versionMajor, unsigned in
// plugins.txt and loadorder.txt (if they both exist) are in sync. If
// dataPath == NULL then the API will attempt to detect the data path of
// the specified game.
-BOSS_API unsigned int boss_create_db (boss_db * db, const unsigned int clientGame, const char * gamePath);
+BOSS_API unsigned int boss_create_db (boss_db * const db, const unsigned int clientGame, const char * const gamePath);
// Destroys the given DB, freeing any memory allocated as part of its use.
BOSS_API void boss_destroy_db (boss_db db);
@@ -159,8 +160,8 @@ BOSS_API void boss_destroy_db (boss_db db);
// Can be called multiple times. On error, the database is unchanged.
// Paths are case-sensitive if the underlying filesystem is case-sensitive.
// masterlistPath and userlistPath are files.
-BOSS_API unsigned int boss_load_lists (boss_db db, const char * masterlistPath,
- const char * userlistPath);
+BOSS_API unsigned int boss_load_lists (boss_db db, const char * const masterlistPath,
+ const char * const userlistPath);
// Evaluates all conditional lines and regex mods the loaded masterlist.
// This exists so that Load() doesn't need to be called whenever the mods
@@ -179,7 +180,7 @@ BOSS_API unsigned int boss_eval_lists (boss_db db);
// and userlist, and the number of tags in the returned array. The array and
// its contents are static and should not be freed by the client.
// The indices of the tagMap are each tag's UID.
-BOSS_API unsigned int boss_get_tag_map (boss_db db, char *** tagMap, size_t * numTags);
+BOSS_API unsigned int boss_get_tag_map (boss_db db, char *** const tagMap, size_t * const numTags);
// Returns arrays of Bash Tag UIDs for Bash Tags suggested for addition and removal
// by BOSS's masterlist and userlist, and the number of tags in each array.
@@ -188,25 +189,25 @@ BOSS_API unsigned int boss_get_tag_map (boss_db db, char *** tagMap, size_t * nu
// case-insensitive. If no Tags are found for an array, the array pointer (*tagIds)
// will be NULL. The userlistModified bool is true if the userlist contains Bash Tag
// suggestion message additions.
-BOSS_API unsigned int boss_get_plugin_tags (boss_db db, const char * plugin,
- unsigned int ** tags_added,
- size_t * numTags_added,
- unsigned int ** tags_removed,
- size_t * numTags_removed,
- bool * userlistModified);
+BOSS_API unsigned int boss_get_plugin_tags (boss_db db, const char * const plugin,
+ unsigned int ** const tags_added,
+ size_t * const numTags_added,
+ unsigned int ** const tags_removed,
+ size_t * const numTags_removed,
+ bool * const userlistModified);
// Returns the messages attached to the given plugin. Messages are valid until Load,
// DestroyBossDb or GetPluginMessages are next called. plugin is case-insensitive.
// If no messages are attached, *messages will be NULL and numMessages will equal 0.
-BOSS_API unsigned int boss_get_plugin_messages (boss_db db, const char * plugin,
- boss_message ** messages,
- size_t * numMessages);
+BOSS_API unsigned int boss_get_plugin_messages (boss_db db, const char * const plugin,
+ boss_message ** const messages,
+ size_t * const numMessages);
// Writes a minimal masterlist that only contains mods that have Bash Tag suggestions,
// and/or dirty messages, plus the Tag suggestions and/or messages themselves and their
// conditions, in order to create the Wrye Bash taglist. outputFile is the path to use
// for output. If outputFile already exists, it will only be overwritten if overwrite is true.
-BOSS_API unsigned int boss_write_minimal_list (boss_db db, const char * outputFile, const bool overwrite);
+BOSS_API unsigned int boss_write_minimal_list (boss_db db, const char * const outputFile, const bool overwrite);
#ifdef __cplusplus
diff --git a/src/error.h b/src/error.h
new file mode 100644
index 00000000..68a18117
--- /dev/null
+++ b/src/error.h
@@ -0,0 +1,56 @@
+/* BOSS
+
+ A plugin load order optimiser for games that use the esp/esm plugin system.
+
+ Copyright (C) 2012 WrinklyNinja
+
+ This file is part of BOSS.
+
+ BOSS 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.
+
+ BOSS 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 BOSS. If not, see
+ .
+*/
+
+#ifndef __BOSS_ERROR__
+#define __BOSS_ERROR__
+
+#include
+
+namespace boss {
+
+ const unsigned int OK = 0;
+ const unsigned int ERROR_LIBLO_ERROR = 1;
+ const unsigned int ERROR_PATH_WRITE_FAIL = 2;
+ const unsigned int ERROR_PATH_READ_FAIL = 3;
+ const unsigned int ERROR_CONDITION_EVAL_FAIL = 4;
+ const unsigned int ERROR_REGEX_EVAL_FAIL = 5;
+ const unsigned int ERROR_NO_MEM = 6;
+ const unsigned int ERROR_INVALID_ARGS = 7;
+ const unsigned int ERROR_NO_TAG_MAP = 8;
+ const unsigned int ERROR_PATH_NOT_FOUND = 9;
+
+ class error : public std::exception {
+ public:
+ error(const int code_arg, const std::string& what_arg) : _code(code_arg), _what(what_arg) {}
+ ~error() throw() {};
+
+ unsigned int code() const { return _code; }
+ const char * what() const throw() { return _what.c_str(); }
+ private:
+ std::string _what;
+ unsigned int _code;
+ };
+
+}
+
+#endif
diff --git a/src/game.cpp b/src/game.cpp
index da083523..b63086a3 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -24,6 +24,7 @@
#include "game.h"
#include "globals.h"
#include "helpers.h"
+#include "error.h"
#include
@@ -42,12 +43,13 @@ namespace fs = boost::filesystem;
namespace boss {
- Game::Game()
- : id(BOSS_GAME_AUTODETECT) {}
+ Game::Game() {
+ throw error(ERROR_INVALID_ARGS, "No arguments supplied.");
+ }
Game::Game(const unsigned int gameCode, const string path, const bool noPathInit)
: id(gameCode) {
- if (Id() == BOSS_GAME_TES4) {
+ if (Id() == GAME_TES4) {
name = "TES IV: Oblivion";
registryKey = "Software\\Bethesda Softworks\\Oblivion";
@@ -55,7 +57,7 @@ namespace boss {
bossFolderName = "Oblivion";
pluginsFolderName = "Data";
- } else if (Id() == BOSS_GAME_TES5) {
+ } else if (Id() == GAME_TES5) {
name = "TES V: Skyrim";
registryKey = "Software\\Bethesda Softworks\\Skyrim";
@@ -63,7 +65,7 @@ namespace boss {
bossFolderName = "Skyrim";
pluginsFolderName = "Data";
- } else if (Id() == BOSS_GAME_FO3) {
+ } else if (Id() == GAME_FO3) {
name = "Fallout 3";
registryKey = "Software\\Bethesda Softworks\\Fallout3";
@@ -71,7 +73,7 @@ namespace boss {
bossFolderName = "Fallout 3";
pluginsFolderName = "Data";
- } else if (Id() == BOSS_GAME_FONV) {
+ } else if (Id() == GAME_FONV) {
name = "Fallout: New Vegas";
registryKey = "Software\\Bethesda Softworks\\FalloutNV";
@@ -80,7 +82,7 @@ namespace boss {
bossFolderName = "Fallout New Vegas";
pluginsFolderName = "Data";
} else
- throw runtime_error("Invalid game ID supplied.");
+ throw error(ERROR_INVALID_ARGS, "Invalid game ID supplied.");
if (!noPathInit) {
if (path.empty()) {
@@ -90,7 +92,7 @@ namespace boss {
else if (RegKeyExists("HKEY_LOCAL_MACHINE", registryKey, registrySubKey))
gamePath = fs::path(RegKeyStringValue("HKEY_LOCAL_MACHINE", registryKey, registrySubKey));
else
- throw runtime_error("Game path could not be detected.");
+ throw error(ERROR_PATH_NOT_FOUND, "Game path could not be detected.");
} else
gamePath = fs::path(path);
@@ -127,20 +129,20 @@ namespace boss {
int ret;
char ** pluginArr;
size_t pluginArrSize;
- if (id == BOSS_GAME_TES4)
+ if (id == GAME_TES4)
ret = lo_create_handle(&gh, LIBLO_GAME_TES4, gamePath.string().c_str());
- else if (id == BOSS_GAME_TES5)
+ else if (id == GAME_TES5)
ret = lo_create_handle(&gh, LIBLO_GAME_TES5, gamePath.string().c_str());
- else if (id == BOSS_GAME_FO3)
+ else if (id == GAME_FO3)
ret = lo_create_handle(&gh, LIBLO_GAME_FO3, gamePath.string().c_str());
- else if (id == BOSS_GAME_FONV)
+ else if (id == GAME_FONV)
ret = lo_create_handle(&gh, LIBLO_GAME_FNV, gamePath.string().c_str());
if (ret != LIBLO_OK)
- throw runtime_error("Active plugin list lookup failed.");
+ throw error(ERROR_LIBLO_ERROR, "libloadorder game handle creation failed.");
else {
if (lo_get_active_plugins(gh, &pluginArr, &pluginArrSize) != LIBLO_OK)
- throw runtime_error("Active plugin list lookup failed.");
+ throw error(ERROR_LIBLO_ERROR, "Active plugin list lookup failed.");
else {
for (size_t i=0; i < pluginArrSize; ++i) {
activePlugins.insert(string(pluginArr[i]));
@@ -158,8 +160,8 @@ namespace boss {
try {
if (!fs::exists(bossFolderName))
fs::create_directory(bossFolderName);
- } catch (fs::filesystem_error e) {
- throw runtime_error("Could not create BOSS folder for game.");
+ } catch (fs::filesystem_error& e) {
+ throw error(ERROR_PATH_WRITE_FAIL, "Could not create BOSS folder for game.");
}
}
diff --git a/src/globals.h b/src/globals.h
index e04fa717..c574624a 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -23,14 +23,18 @@
#ifndef __BOSS_GLOBALS__
#define __BOSS_GLOBALS__
-const unsigned int BOSS_GAME_AUTODETECT = 0;
-const unsigned int BOSS_GAME_TES4 = 1;
-const unsigned int BOSS_GAME_TES5 = 2;
-const unsigned int BOSS_GAME_FO3 = 3;
-const unsigned int BOSS_GAME_FONV = 4;
+namespace boss {
-const unsigned int BOSS_VERSION_MAJOR = 3;
-const unsigned int BOSS_VERSION_MINOR = 0;
-const unsigned int BOSS_VERSION_PATCH = 0;
+ const unsigned int GAME_AUTODETECT = 0;
+ const unsigned int GAME_TES4 = 1;
+ const unsigned int GAME_TES5 = 2;
+ const unsigned int GAME_FO3 = 3;
+ const unsigned int GAME_FONV = 4;
+
+ const unsigned int VERSION_MAJOR = 3;
+ const unsigned int VERSION_MINOR = 0;
+ const unsigned int VERSION_PATCH = 0;
+
+}
#endif
diff --git a/src/helpers.cpp b/src/helpers.cpp
index 941b86b0..49156628 100644
--- a/src/helpers.cpp
+++ b/src/helpers.cpp
@@ -27,6 +27,7 @@
#include "helpers.h"
#include "plugin/ModFormat.h"
+#include "error.h"
#include
#include
@@ -78,7 +79,7 @@ namespace boss {
} while (ifile);
chksum = result.checksum();
} else {
- throw runtime_error("Unable to open \"" + filename.string() + "\" for CRC calculation.");
+ throw error(ERROR_PATH_READ_FAIL, "Unable to open \"" + filename.string() + "\" for CRC calculation.");
}
// LOG_DEBUG("CRC32('%s'): 0x%x", filename.string().c_str(), chksum);
return chksum;
diff --git a/src/parsers.h b/src/parsers.h
index 328bd49f..63a04cf8 100644
--- a/src/parsers.h
+++ b/src/parsers.h
@@ -30,6 +30,7 @@
#include "metadata.h"
#include "helpers.h"
+#include "error.h"
#include
#include
@@ -383,7 +384,7 @@ namespace boss {
void CheckFile(bool& result, const std::string& file) {
if (!IsSafePath(file))
- throw std::runtime_error("The file path \"" + file + "\" is invalid.");
+ throw boss::error(boss::ERROR_INVALID_ARGS, "The file path \"" + file + "\" is invalid.");
if (IsPlugin(file))
result = boost::filesystem::exists(game->DataPath() / file) || boost::filesystem::exists(game->DataPath() / (file + ".ghost"));
@@ -422,7 +423,7 @@ namespace boss {
}
if (boost::contains(parent, "../../"))
- throw std::runtime_error("The folder path \"" + parent + "\" is invalid.");
+ throw boss::error(boss::ERROR_INVALID_ARGS, "The folder path \"" + parent + "\" is invalid.");
//Now we have a valid parent path and a regex filename. Check that
//the parent path exists and is a directory.
@@ -434,8 +435,8 @@ namespace boss {
boost::regex regex;
try {
regex = boost::regex(filename, boost::regex::extended|boost::regex::icase);
- } catch (boost::regex_error e) {
- throw std::runtime_error("The regex string \"" + filename + "\" is invalid.");
+ } catch (boost::regex_error& e) {
+ throw boss::error(boss::ERROR_INVALID_ARGS, "The regex string \"" + filename + "\" is invalid.");
}
for (fs::directory_iterator itr(parent_path); itr != fs::directory_iterator(); ++itr) {
@@ -449,7 +450,7 @@ namespace boss {
void CheckSum(bool& result, const std::string& file, const uint32_t checksum) {
if (!IsSafePath(file))
- throw std::runtime_error("The file path \"" + file + "\" is invalid.");
+ throw boss::error(boss::ERROR_INVALID_ARGS, "The file path \"" + file + "\" is invalid.");
uint32_t crc;
boost::unordered_map::iterator it = game->crcCache.find(boost::to_lower_copy(file));
@@ -506,7 +507,7 @@ namespace boss {
std::string context(errorpos, min(errorpos +50, last));
boost::trim(context);
- throw std::runtime_error("Error parsing condition at \"" + context + "\", expected \"" + what.tag + "\"");
+ throw boss::error(boss::ERROR_CONDITION_EVAL_FAIL, "Error parsing condition at \"" + context + "\", expected \"" + what.tag + "\"");
}
//Checks that the path (not regex) doesn't go outside any game folders.
@@ -541,10 +542,15 @@ namespace boss {
begin = condition.begin();
end = condition.end();
- bool r = qi::phrase_parse(begin, end, grammar, skipper, eval);
+ bool r;
+ try {
+ r = qi::phrase_parse(begin, end, grammar, skipper, eval);
+ } catch (boss::error& e) {
+ throw boss::error(boss::ERROR_PATH_READ_FAIL, "Parsing of condition \"" + condition + "\" failed: " + e.what());
+ }
if (!r || begin != end)
- throw std::runtime_error("Parsing of condition \"" + condition + "\" failed!");
+ throw boss::error(boss::ERROR_PATH_READ_FAIL, "Parsing of condition \"" + condition + "\" failed!");
game.conditionCache.emplace(boost::to_lower_copy(condition), eval);
diff --git a/src/plugin/ModFormat.cpp b/src/plugin/ModFormat.cpp
index 046dbbb0..cad802ec 100644
--- a/src/plugin/ModFormat.cpp
+++ b/src/plugin/ModFormat.cpp
@@ -137,7 +137,6 @@ namespace boss {
ifstream file(filename.string().c_str(), ios_base::binary | ios_base::in);
if (file.bad())
- //throw boss_error(BOSS_ERROR_FILE_READ_FAIL, filename.string());
return false;
// Reads the first MAXLENGTH bytes into the buffer
diff --git a/src/tester.cpp b/src/tester.cpp
index e38b3349..8abeede4 100644
--- a/src/tester.cpp
+++ b/src/tester.cpp
@@ -3,6 +3,7 @@
#include "metadata.h"
#include "parsers.h"
#include "game.h"
+#include "error.h"
#include "globals.h"
#include
@@ -47,12 +48,12 @@ int main() {
cout << "Testing game settings structure." << endl;
- boss::Game game(BOSS_GAME_TES5, "/media/oliver/6CF05918F058EA3A/Program Files (x86)/Steam/steamapps/common/skyrim");
+ boss::Game game(boss::GAME_TES5, "/media/oliver/6CF05918F058EA3A/Program Files (x86)/Steam/steamapps/common/skyrim");
for (list::iterator it=pluginData.begin(), endIt=pluginData.end(); it != endIt; ++it) {
try {
it->EvalAllConditions(game);
- } catch (std::runtime_error& e) {
+ } catch (boss::error& e) {
cout << e.what() << endl;
}
}
|