diff C++/modules/Xdg/Xdg.cpp @ 334:0b576ee64d45

* Create brand new hierarchy * Rename DynLib to Dynlib * Remove some warnings
author David Demelier <markand@malikania.fr>
date Sun, 08 Mar 2015 14:26:33 +0100
parents C++/Xdg.cpp@f6d9fdb5eeeb
children d5ec1174b707
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C++/modules/Xdg/Xdg.cpp	Sun Mar 08 14:26:33 2015 +0100
@@ -0,0 +1,125 @@
+/*
+ * Xdg.cpp -- XDG directory specifications
+ *
+ * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cstdlib>
+#include <stdexcept>
+#include <sstream>
+
+#include "Xdg.h"
+
+namespace {
+
+bool isabsolute(const std::string &path)
+{
+	return path.length() > 0 && path[0] == '/';
+}
+
+std::vector<std::string> split(const std::string &arg)
+{
+	std::stringstream iss(arg);
+	std::string item;
+	std::vector<std::string> elems;
+
+	while (std::getline(iss, item, ':'))
+		if (isabsolute(item))
+			elems.push_back(item);
+
+	return elems;
+}
+
+std::string envOrHome(const std::string &var, const std::string &repl)
+{
+	auto value = getenv(var.c_str());
+
+	if (value == nullptr || !isabsolute(value)) {
+		auto home = getenv("HOME");
+
+		if (home == nullptr)
+			throw std::runtime_error("could not get home directory");
+
+		return std::string(home) + "/" + repl;
+	}
+
+	return value;
+}
+
+std::vector<std::string> listOrDefaults(const std::string &var, const std::vector<std::string> &list)
+{
+	auto value = getenv(var.c_str());
+
+	if (!value)
+		return list;
+
+	// No valid item at all? Use defaults
+	auto result = split(value);
+
+	return (result.size() == 0) ? list : result;
+}
+
+} // !namespace
+
+Xdg::Xdg()
+{
+	m_configHome	= envOrHome("XDG_CONFIG_HOME", ".config");
+	m_dataHome	= envOrHome("XDG_DATA_HOME", ".local/share");
+	m_cacheHome	= envOrHome("XDG_CACHE_HOME", ".cache");
+
+	m_configDirs	= listOrDefaults("XDG_CONFIG_DIRS", { "/etc/xdg" });
+	m_dataDirs	= listOrDefaults("XDG_DATA_DIRS", { "/usr/local/share", "/usr/share" });
+
+	/*
+	 * Runtime directory is a special case and does not have a replacement, the
+	 * application should manage this by itself.
+	 */
+	auto runtime = getenv("XDG_RUNTIME_DIR");
+	if (runtime && isabsolute(runtime))
+		m_runtimeDir = runtime;
+}
+
+const std::string &Xdg::configHome() const noexcept
+{
+	return m_configHome;
+}
+
+const std::string &Xdg::dataHome() const noexcept
+{
+	return m_dataHome;
+}
+
+const std::string &Xdg::cacheHome() const noexcept
+{
+	return m_cacheHome;
+}
+
+const std::string &Xdg::runtimeDir() const
+{
+	if (m_runtimeDir.size() == 0)
+		throw std::runtime_error("XDG_RUNTIME_DIR is not set");
+
+	return m_runtimeDir;
+}
+
+const Xdg::List &Xdg::configDirs() const noexcept
+{
+	return m_configDirs;
+}
+
+const Xdg::List &Xdg::dataDirs() const noexcept
+{
+	return m_dataDirs;
+}