TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / external / xdg / xdg.cpp
1 // Copyright (C) 2015 Thomas Voß <thomas.voss.bochum@gmail.com>
2 // 
3 // This library is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU Lesser General Public License as published
5 // by the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 #include <xdg.h>
17
18 #include <boost/algorithm/string.hpp>
19
20 #include <cstdlib>
21 #include <stdexcept>
22
23 namespace fs = boost::filesystem;
24
25 namespace
26 {
27
28 fs::path throw_if_not_absolute(const fs::path& p)
29 {
30     if (p.has_root_directory())
31         return p;
32
33     throw std::runtime_error{"Directores MUST be absolute."};
34 }
35
36 namespace env
37 {
38 std::string get(const std::string& key, const std::string& default_value)
39 {
40     if (auto value = std::getenv(key.c_str()))
41         return value;
42     return default_value;
43 }
44
45 std::string get_or_throw(const std::string& key)
46 {
47     if (auto value = std::getenv(key.c_str()))
48     {
49         return value;
50     }
51
52     throw std::runtime_error{key + " not set in environment"};
53 }
54
55 constexpr const char* xdg_data_home{"XDG_DATA_HOME"};
56 constexpr const char* xdg_data_dirs{"XDG_DATA_DIRS"};
57 constexpr const char* xdg_config_home{"XDG_CONFIG_HOME"};
58 constexpr const char* xdg_config_dirs{"XDG_CONFIG_DIRS"};
59 constexpr const char* xdg_cache_home{"XDG_CACHE_HOME"};
60 }
61
62 namespace impl
63 {
64 class BaseDirSpecification : public xdg::BaseDirSpecification
65 {
66 public:
67     static const BaseDirSpecification& instance()
68     {
69         static const BaseDirSpecification spec;
70         return spec;
71     }
72
73     BaseDirSpecification()
74     {
75     }
76
77     const xdg::Data& data() const override
78     {
79         return data_;
80     }
81
82     const xdg::Config& config() const override
83     {
84         return config_;
85     }
86
87     const xdg::Cache& cache() const override
88     {
89         return cache_;
90     }
91
92     const xdg::Runtime& runtime() const override
93     {
94         return runtime_;
95     }
96
97 private:
98     xdg::Data data_;
99     xdg::Config config_;
100     xdg::Cache cache_;
101     xdg::Runtime runtime_;
102 };
103 }
104 }
105
106 fs::path xdg::Data::home() const
107 {
108     auto v = env::get(env::xdg_data_home, "");
109     if (v.empty())
110         return throw_if_not_absolute(fs::path{env::get_or_throw("HOME")} / ".local" / "share");
111
112     return throw_if_not_absolute(fs::path(v));
113 }
114
115 std::vector<fs::path> xdg::Data::dirs() const
116 {
117     auto v = env::get(env::xdg_data_dirs, "");
118     if (v.empty())
119         return {fs::path{"/usr/local/share"}, fs::path{"/usr/share"}};
120
121     std::vector<std::string> tokens;
122     tokens = boost::split(tokens, v, boost::is_any_of(":"));
123     std::vector<fs::path> result;
124     for (const auto& token : tokens)
125     {
126         result.push_back(throw_if_not_absolute(fs::path(token)));
127     }
128     return result;
129 }
130
131 fs::path xdg::Config::home() const
132 {
133     auto v = env::get(env::xdg_config_home, "");
134     if (v.empty())
135         return throw_if_not_absolute(fs::path{env::get_or_throw("HOME")} / ".config");
136
137     return throw_if_not_absolute(fs::path(v));
138 }
139
140 std::vector<fs::path> xdg::Config::dirs() const
141 {
142     auto v = env::get(env::xdg_config_dirs, "");
143     if (v.empty())
144         return {fs::path{"/etc/xdg"}};
145
146     std::vector<std::string> tokens;
147     tokens = boost::split(tokens, v, boost::is_any_of(":"));
148     std::vector<fs::path> result;
149     for (const auto& token : tokens)
150     {
151         fs::path p(token);
152         result.push_back(throw_if_not_absolute(p));
153     }
154     return result;
155 }
156
157 fs::path xdg::Cache::home() const
158 {
159     auto v = env::get(env::xdg_cache_home, "");
160     if (v.empty())
161         return throw_if_not_absolute(fs::path{env::get_or_throw("HOME")} / ".cache");
162
163     return throw_if_not_absolute(fs::path(v));
164 }
165
166 fs::path xdg::Runtime::dir() const
167 {
168     auto v = env::get(env::xdg_config_home, "");
169     if (v.empty())
170     {
171         // We do not fall back gracefully and instead throw, dispatching to calling
172         // code for handling the case of a safe user-specfic runtime directory missing.
173         throw std::runtime_error{"Runtime directory not set"};
174     }
175
176     return throw_if_not_absolute(fs::path(v));
177 }
178
179 std::shared_ptr<xdg::BaseDirSpecification> xdg::BaseDirSpecification::create()
180 {
181     return std::make_shared<impl::BaseDirSpecification>();
182 }
183
184 const xdg::Data& xdg::data()
185 {
186     return impl::BaseDirSpecification::instance().data();
187 }
188
189 const xdg::Config& xdg::config()
190 {
191     return impl::BaseDirSpecification::instance().config();
192 }
193
194 const xdg::Cache& xdg::cache()
195 {
196     return impl::BaseDirSpecification::instance().cache();
197 }
198
199 const xdg::Runtime& xdg::runtime()
200 {
201     return impl::BaseDirSpecification::instance().runtime();
202 }