/* ************************************************************************** Author: Stefan Reutter Created: August 2013 ****************************************************************************/ #ifndef DAMARIS_backend_config_reader_h #define DAMARIS_backend_config_reader_h #include #include namespace DAMARIS { /** * \defgroup BackendConfigReader Backend Config Reader * \ingroup machines * * Allows reading in a backend configuration file implemented as a Glib Key-Value file */ /*@{*/ /** * Exception class for the config file. */ class BackendConfigException : public std::runtime_error { public: explicit BackendConfigException(const std::string& msg) throw() : std::runtime_error(msg) {}; explicit BackendConfigException(const char* msg) throw() : std::runtime_error(msg) {}; virtual ~BackendConfigException() throw() {}; }; /** * Class for reading a backend configuration file. Must be constructed with a c string providing the relative path to the config file. * * BackendConfigReader will first look in the XDG user config folder for the file, then in all system config folders. If no * config file is found in any of these locations, a BackendConfigException will be thrown. * * Example: * \code * DAMARIS::BackendConfigReader cfgReader("/damaris/backend.conf"); * std::cout << cfgReader.getInteger("ADC", "id") << "\n"; * \endcode * */ class BackendConfigReader { public: /** * \param configPath C String containing the relative path to the config file */ BackendConfigReader(const gchar *configPath); ~BackendConfigReader() { g_key_file_free(_keyFile); }; // I hope this is exception safe /* -------------------------------------------------------------------- */ /* The following functions are encapsulating the underlying GKeyFile functionality */ inline gboolean getBoolean(const gchar *groupName, const gchar *key) {GError* err = NULL; bool ret = g_key_file_get_boolean(_keyFile, groupName, key, &err); if (err) {g_error("GLib Error code %i, message: %s", err->code, err->message);} return ret;}; inline gdouble getDouble(const gchar *groupName, const gchar *key) {GError* err = NULL; double ret = g_key_file_get_double(_keyFile, groupName, key, &err); if (err) {g_error("GLib Error code %i, message: %s", err->code, err->message);} return ret;}; inline gint getInteger(const gchar *groupName, const gchar *key) {GError* err = NULL; int ret = g_key_file_get_integer(_keyFile, groupName, key, &err); if (err) {g_error("GLib Error code %i, message: %s", err->code, err->message);} return ret;}; inline gchar* getValue(const gchar *groupName, const gchar *key) {GError* err = NULL; gchar* ret = g_key_file_get_value(_keyFile, groupName, key, &err); if (err) {g_error("GLib Error code %i, message: %s", err->code, err->message);} return ret;}; inline gchar* getString(const gchar *groupName, const gchar *key) {GError* err = NULL; gchar* ret = g_key_file_get_string(_keyFile, groupName, key, &err); if (err) {g_error("GLib Error code %i, message: %s", err->code, err->message);} return ret;}; /** * This allows you to pass a function pointer to BackendConfigReader in order to call one of the functions on GKeyFile that are not driectly provided. * * Because a function pointer needs to know the full signature, the function pointer must reflect this. * * Example usage: * \code * gchar* groupName; // initialized * gchar* key; // initialized * gint64 (*f)(GKeyFile*, const gchar *, const gchar *, GError*) = &g_key_file_get_int64; * gint64 value = getSomething (f, groupName, key); * \endcode */ template returnType getSomething(returnType (*func)(GKeyFile*, const gchar *, const gchar *, GError*), const gchar *groupName, const gchar *key) { GError* err = NULL; returnType ret = func(_keyFile, groupName, key, &err); if (err) {g_error("GLib Error code %i, message: %s", err->code, err->message);} return ret; } /* -------------------------------------------------------------------- */ private: /** * Attempt to load the defined relative config path. * * First, attempt to load the file from the user config dir. If that fails, attempt to load from the system config dir. If that fails as well, exit the program. */ void loadConfig(); /** * Load a specific config file. Returns true on success, false on file not found. Throws an error otherwise. */ bool loadConfigFile(const gchar *keyFileName, GKeyFileFlags flags, GError *error); /** * (Relative) Path to the damaris backend config */ const gchar *_damarisConfigPath; GKeyFile *_keyFile; }; /*@}*/ } // namespace DAMARIS #endif // include guard