$darkmode
conf.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Robert Bosch GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  */
51 #pragma once
52 
53 #include <filesystem> // for path
54 #include <functional> // for function<>
55 #include <string> // for string
56 #include <utility> // for move
57 #include <vector> // for vector<>
58 
59 #include <fmt/format.h> // for fmt::format
60 
61 #include <fable/fable_fwd.hpp> // for ConfError
62 #include <fable/json.hpp> // for Json
63 
64 namespace fable {
65 
76 class Conf {
77  public:
78  Conf() = default;
79  explicit Conf(Json data) : data_(std::move(data)) {}
80  explicit Conf(std::string file);
81  Conf(Json data, std::string file) : file_(std::move(file)), data_(std::move(data)) {}
82  Conf(Json data, std::string file, std::string root)
83  : file_(std::move(file)), root_(std::move(root)), data_(std::move(data)) {}
84 
94  [[nodiscard]] bool is_from_file() const { return !file_.empty(); }
95 
99  [[nodiscard]] const std::string& file() const { return file_; }
100 
104  [[nodiscard]] bool is_empty() const { return data_.is_null(); }
105 
111  const Json& operator*() const { return data_; }
112  Json& operator*() { return data_; }
113 
119  const Json* operator->() const { return &data_; }
120  Json* operator->() { return &data_; }
121 
125  [[nodiscard]] std::string root() const { return (root_.empty() ? "/" : root_); }
126 
132  [[nodiscard]] bool has(const std::string& key) const { return data_.count(key) != 0; }
133  [[nodiscard]] bool has(const JsonPointer& key) const;
134  [[nodiscard]] bool has_pointer(const std::string& key) const { return has(JsonPointer(key)); }
135 
141  [[nodiscard]] Conf at(const std::string& key) const;
142  [[nodiscard]] Conf at(const JsonPointer& key) const;
143  [[nodiscard]] Conf at_pointer(const std::string& key) const { return at(JsonPointer(key)); }
144 
149  size_t erase(const std::string& key);
150  size_t erase(const JsonPointer& key);
151  size_t erase_pointer(const std::string& key) { return erase(JsonPointer(key)); }
152 
158  [[nodiscard]] std::vector<Conf> to_array() const;
159 
165  template <typename T>
166  [[nodiscard]] T get() const {
167  try {
168  return data_.get<T>();
169  } catch (nlohmann::detail::type_error&) {
170  throw_wrong_type();
171  }
172  }
173 
179  template <typename T>
180  [[nodiscard]] T get(const std::string& key) const {
181  try {
182  return data_.at(key).get<T>();
183  } catch (nlohmann::detail::out_of_range&) {
184  throw_missing(key);
185  } catch (nlohmann::detail::type_error&) {
186  throw_wrong_type(key);
187  }
188  }
189 
190  template <typename T>
191  [[nodiscard]] T get(const JsonPointer& key) const {
192  try {
193  return data_.at(key).get<T>();
194  } catch (nlohmann::detail::out_of_range&) {
195  throw_missing(key.to_string());
196  } catch (nlohmann::detail::type_error&) {
197  throw_wrong_type(key.to_string());
198  }
199  }
200 
201  template <typename T>
202  [[nodiscard]] T get_pointer(const std::string& key) const {
203  return get<T>(JsonPointer(key));
204  }
205 
210  template <typename T>
211  [[nodiscard]] T get_or(const std::string& key, T def) const {
212  if (!data_.count(key)) {
213  return def;
214  }
215  try {
216  return data_.at(key).get<T>();
217  } catch (nlohmann::detail::type_error&) {
218  throw_wrong_type(key);
219  }
220  }
221 
222  template <typename T>
223  [[nodiscard]] T get_or(const JsonPointer& key, T def) const {
224  try {
225  return data_.at(key).get<T>();
226  } catch (nlohmann::detail::out_of_range&) {
227  return def;
228  } catch (nlohmann::detail::type_error&) {
229  throw_wrong_type(key.to_string());
230  }
231  }
232 
233  template <typename T>
234  [[nodiscard]] T get_pointer_or(const std::string& key, T def) const {
235  return get_or(key, def);
236  }
237 
244  template <typename T>
245  void with(const std::string& key, std::function<void(const T&)> fn) const {
246  if (data_.count(key)) {
247  fn(get<T>(key));
248  }
249  }
250 
251  template <typename T>
252  void with(const JsonPointer& key, std::function<void(const T&)> fn) const {
253  try {
254  fn(get<T>(key));
255  } catch (nlohmann::detail::out_of_range&) {
256  return;
257  }
258  }
259 
260  template <typename T>
261  void with_pointer(const std::string& key, std::function<void(const T&)> fn) const {
262  with(JsonPointer(key), fn);
263  }
264 
270  template <typename T>
271  void try_from(const std::string& key, T& val) const {
272  if (data_.count(key)) {
273  val = get<T>(key);
274  }
275  }
276 
277  template <typename T>
278  void try_from(const JsonPointer& key, T& val) const {
279  try {
280  val = data_.at(key).get<T>();
281  } catch (nlohmann::detail::out_of_range& e) {
282  return;
283  } catch (nlohmann::detail::type_error& e) {
284  throw_wrong_type(key.to_string());
285  }
286  }
287 
288  template <typename T>
289  void try_from_pointer(const std::string& key, T& val) const {
290  try_from(JsonPointer(key), val);
291  }
292 
296  void assert_has(const std::string& key) const;
297  void assert_has(const JsonPointer& key) const;
298  void assert_has_pointer(const std::string& key) const { assert_has(JsonPointer(key)); }
299 
304  void assert_has_type(const std::string& key, JsonType t) const;
305  void assert_has_type(const JsonPointer& key, JsonType t) const;
306  void assert_has_pointer_type(const std::string& key, JsonType t) const {
307  assert_has_type(JsonPointer(key), t);
308  }
309 
314  void assert_has_not(const std::string& key, const std::string& msg = "") const;
315  void assert_has_not(const JsonPointer& key, const std::string& msg = "") const;
316  void assert_has_pointer_not(const std::string& key, const std::string& msg = "") const {
317  assert_has_not(JsonPointer(key), msg);
318  }
319 
330  [[nodiscard]] std::filesystem::path resolve_file(const std::filesystem::path& filename) const;
331  [[nodiscard]] std::string resolve_file(const std::string& filename) const;
332 
333  template <typename... Args>
334  [[noreturn]] void throw_error(std::string_view format, Args&&... args) const {
335  throw_error(fmt::format(fmt::runtime(format), std::forward<Args>(args)...));
336  }
337  [[noreturn]] void throw_error(const std::string& msg) const;
338  [[noreturn]] void throw_unexpected(const std::string& key, const std::string& msg = "") const;
339  [[noreturn]] void throw_missing(const std::string& key) const;
340  [[noreturn]] void throw_wrong_type(const std::string& key = "") const;
341  [[noreturn]] void throw_wrong_type(const std::string& key, JsonType type) const;
342 
343  friend void to_json(Json& j, const Conf& c) { j = *c; }
344  friend void from_json(const Json& j, Conf& c) { *c = j; }
345 
346  private:
347  std::string file_;
348  std::string root_;
349  Json data_;
350 };
351 
352 } // namespace fable
Definition: conf.hpp:76
bool has(const std::string &key) const
Definition: conf.hpp:132
T get_or(const std::string &key, T def) const
Definition: conf.hpp:211
void with(const std::string &key, std::function< void(const T &)> fn) const
Definition: conf.hpp:245
const Json * operator->() const
Definition: conf.hpp:119
std::filesystem::path resolve_file(const std::filesystem::path &filename) const
Definition: conf.cpp:151
std::string root() const
Definition: conf.hpp:125
void assert_has_type(const std::string &key, JsonType t) const
Definition: conf.cpp:137
void assert_has(const std::string &key) const
Definition: conf.cpp:109
void try_from(const std::string &key, T &val) const
Definition: conf.hpp:271
const std::string & file() const
Definition: conf.hpp:99
const Json & operator*() const
Definition: conf.hpp:111
size_t erase(const std::string &key)
Definition: conf.cpp:74
bool is_from_file() const
Definition: conf.hpp:94
Conf at(const std::string &key) const
Definition: conf.cpp:58
void assert_has_not(const std::string &key, const std::string &msg="") const
Definition: conf.cpp:121
T get() const
Definition: conf.hpp:166
bool is_empty() const
Definition: conf.hpp:104
std::vector< Conf > to_array() const
Definition: conf.cpp:92
T get(const std::string &key) const
Definition: conf.hpp:180
nlohmann::json Json
Definition: fable_fwd.hpp:35
nlohmann::json_pointer< std::string > JsonPointer
Definition: fable_fwd.hpp:36