irccd  3.0.3
xdg.hpp
1 /*
2  * xdg.hpp -- XDG directory specifications
3  *
4  * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #ifndef IRCCD_XDG_HPP
20 #define IRCCD_XDG_HPP
21 
28 #include <cstdlib>
29 #include <sstream>
30 #include <stdexcept>
31 #include <string>
32 #include <vector>
33 
34 namespace irccd {
35 
44 class xdg {
45 private:
46  std::string config_home_;
47  std::string data_home_;
48  std::string cache_home_;
49  std::string runtime_dir_;
50  std::vector<std::string> config_dirs_;
51  std::vector<std::string> data_dirs_;
52 
53  auto is_absolute(const std::string& path) const noexcept -> bool
54  {
55  return path.length() > 0 && path[0] == '/';
56  }
57 
58  auto split(const std::string& arg) const -> std::vector<std::string>
59  {
60  std::stringstream iss(arg);
61  std::string item;
62  std::vector<std::string> elems;
63 
64  while (std::getline(iss, item, ':')) {
65  if (is_absolute(item))
66  elems.push_back(item);
67  }
68 
69  return elems;
70  }
71 
72  auto env_or_home(const std::string& var, const std::string& repl) const -> std::string
73  {
74  auto value = std::getenv(var.c_str());
75 
76  if (value == nullptr || !is_absolute(value)) {
77  auto home = std::getenv("HOME");
78 
79  if (home == nullptr)
80  throw std::runtime_error("could not get home directory");
81 
82  return std::string(home) + "/" + repl;
83  }
84 
85  return value;
86  }
87 
88  auto list_or_defaults(const std::string& var,
89  const std::vector<std::string>& list) const -> std::vector<std::string>
90  {
91  const auto value = std::getenv(var.c_str());
92 
93  if (!value)
94  return list;
95 
96  // No valid item at all? Use defaults.
97  if (const auto result = split(value); !result.empty())
98  return result;
99 
100  return list;
101  }
102 
103 public:
109  xdg()
110  : config_home_(env_or_home("XDG_CONFIG_HOME", ".config"))
111  , data_home_(env_or_home("XDG_DATA_HOME", ".local/share"))
112  , cache_home_(env_or_home("XDG_CACHE_HOME", ".cache"))
113  , config_dirs_(list_or_defaults("XDG_CONFIG_DIRS", { "/etc/xdg" }))
114  , data_dirs_(list_or_defaults("XDG_DATA_DIRS", { "/usr/local/share", "/usr/share" }))
115  {
116 
117  /*
118  * Runtime directory is a special case and does not have a replacement,
119  * the application should manage this by itself.
120  */
121  if (const auto runtime = std::getenv("XDG_RUNTIME_DIR"); runtime && is_absolute(runtime))
122  runtime_dir_ = runtime;
123  }
124 
130  auto get_config_home() const noexcept -> const std::string&
131  {
132  return config_home_;
133  }
134 
140  auto get_data_home() const noexcept -> const std::string&
141  {
142  return data_home_;
143  }
144 
150  auto get_cache_home() const noexcept -> const std::string&
151  {
152  return cache_home_;
153  }
154 
163  auto get_runtime_dir() const noexcept -> const std::string&
164  {
165  return runtime_dir_;
166  }
167 
173  auto get_config_dirs() const noexcept -> const std::vector<std::string>&
174  {
175  return config_dirs_;
176  }
177 
184  auto get_data_dirs() const noexcept -> const std::vector<std::string>&
185  {
186  return data_dirs_;
187  }
188 };
189 
190 } // !irccd
191 
192 #endif // !IRCCD_XDG_HPP
irccd::xdg::get_data_dirs
auto get_data_dirs() const noexcept -> const std::vector< std::string > &
Definition: xdg.hpp:184
irccd::xdg::xdg
xdg()
Definition: xdg.hpp:109
irccd::xdg::get_cache_home
auto get_cache_home() const noexcept -> const std::string &
Definition: xdg.hpp:150
irccd::xdg::get_config_home
auto get_config_home() const noexcept -> const std::string &
Definition: xdg.hpp:130
irccd::xdg::get_config_dirs
auto get_config_dirs() const noexcept -> const std::vector< std::string > &
Definition: xdg.hpp:173
irccd::xdg::get_runtime_dir
auto get_runtime_dir() const noexcept -> const std::string &
Definition: xdg.hpp:163
irccd
Parent namespace.
Definition: acceptor.hpp:43
std
Definition: bot.hpp:253
irccd::xdg::get_data_home
auto get_data_home() const noexcept -> const std::string &
Definition: xdg.hpp:140
irccd::xdg
XDG directory specifications.
Definition: xdg.hpp:44