$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 
82 class Conf {
83  public:
84  Conf() = default;
85  explicit Conf(Json data) : data_(std::move(data)) {}
86  explicit Conf(std::string file);
87  Conf(Json data, std::string file) : file_(std::move(file)), data_(std::move(data)) {}
88  Conf(Json data, std::string file, std::string root)
89  : file_(std::move(file)), root_(std::move(root)), data_(std::move(data)) {}
90 
100  [[nodiscard]] bool is_from_file() const { return !file_.empty(); }
101 
105  [[nodiscard]] const std::string& file() const { return file_; }
106 
110  [[nodiscard]] bool is_empty() const { return data_.is_null(); }
111 
117  const Json& operator*() const { return data_; }
118 
124  Json& operator*() { return data_; }
125 
131  const Json* operator->() const { return &data_; }
132 
138  Json* operator->() { return &data_; }
139 
154  [[nodiscard]] std::string root() const { return (root_.empty() ? "/" : root_); }
155 
166  [[nodiscard]] bool has(const std::string& key) const { return data_.count(key) != 0; }
167 
178  [[nodiscard]] bool has(const JsonPointer& ptr) const;
179 
190  [[nodiscard]] bool has_pointer(const std::string& ptr) const { return has(JsonPointer(ptr)); }
191 
201  [[nodiscard]] Conf at(const std::string& key) const;
202 
212  [[nodiscard]] Conf at(const JsonPointer& ptr) const;
213 
224  [[nodiscard]] Conf at_pointer(const std::string& ptr) const { return at(JsonPointer(ptr)); }
225 
236  size_t erase(const std::string& key);
237 
254  size_t erase(const JsonPointer& ptr, bool preserve_empty = false);
255 
272  size_t erase_pointer(const std::string& ptr, bool preserve_empty = false) {
273  return erase(JsonPointer(ptr), preserve_empty);
274  }
275 
290  [[nodiscard]] std::vector<Conf> to_array() const;
291 
297  template <typename T>
298  [[nodiscard]] T get() const {
299  try {
300  return data_.get<T>();
301  } catch (Json::type_error&) {
303  }
304  }
305 
312  template <typename T>
313  [[nodiscard]] T get(const std::string& key) const {
314  try {
315  return data_.at(key).get<T>();
316  } catch (Json::out_of_range&) {
317  throw_missing(key);
318  } catch (Json::type_error&) {
319  throw_wrong_type(key);
320  }
321  }
322 
329  template <typename T>
330  [[nodiscard]] T get(const JsonPointer& ptr) const {
331  try {
332  return data_.at(ptr).get<T>();
333  } catch (Json::out_of_range&) {
334  throw_missing(ptr);
335  } catch (Json::type_error&) {
336  throw_wrong_type(ptr);
337  }
338  }
339 
347  template <typename T>
348  [[nodiscard]] T get_pointer(const std::string& ptr) const {
349  return get<T>(JsonPointer(ptr));
350  }
351 
360  template <typename T>
361  [[nodiscard]] T get_or(const std::string& key, T def) const {
362  if (!data_.count(key)) {
363  return def;
364  }
365  try {
366  return data_.at(key).get<T>();
367  } catch (Json::type_error&) {
368  throw_wrong_type(key);
369  }
370  }
371 
380  template <typename T>
381  [[nodiscard]] T get_or(const JsonPointer& ptr, T def) const {
382  try {
383  return data_.at(ptr).get<T>();
384  } catch (Json::out_of_range&) {
385  return def;
386  } catch (Json::type_error&) {
387  throw_wrong_type(ptr);
388  }
389  }
390 
400  template <typename T>
401  [[nodiscard]] T get_pointer_or(const std::string& ptr, T def) const {
402  return get_or(JsonPointer(ptr), def);
403  }
404 
411  template <typename T>
412  void with(const std::string& key, std::function<void(const T&)> fn) const {
413  if (data_.count(key)) {
414  fn(get<T>(key));
415  }
416  }
417 
424  template <typename T>
425  void with(const JsonPointer& ptr, std::function<void(const T&)> fn) const {
426  try {
427  fn(get<T>(ptr));
428  } catch (Json::out_of_range&) {
429  return;
430  }
431  }
432 
440  template <typename T>
441  void with_pointer(const std::string& ptr, std::function<void(const T&)> fn) const {
442  with(JsonPointer(ptr), fn);
443  }
444 
454  template <typename T>
455  void try_from(const std::string& key, T& val) const {
456  if (data_.count(key)) {
457  val = get<T>(key);
458  }
459  }
460 
470  template <typename T>
471  void try_from(const JsonPointer& ptr, T& val) const {
472  try {
473  val = data_.at(ptr).get<T>();
474  } catch (Json::out_of_range& e) {
475  return;
476  } catch (Json::type_error& e) {
477  throw_wrong_type(ptr);
478  }
479  }
480 
491  template <typename T>
492  void try_from_pointer(const std::string& ptr, T& val) const {
493  try_from(JsonPointer(ptr), val);
494  }
495 
502  void assert_has(const std::string& key) const;
503 
510  void assert_has(const JsonPointer& ptr) const;
511 
519  void assert_has_pointer(const std::string& key) const { assert_has(JsonPointer(key)); }
520 
529  void assert_has_type(const std::string& key, JsonType t) const;
530 
539  void assert_has_type(const JsonPointer& ptr, JsonType t) const;
540 
550  void assert_has_pointer_type(const std::string& ptr, JsonType t) const {
551  assert_has_type(JsonPointer(ptr), t);
552  }
553 
561  void assert_has_not(const std::string& key, const std::string& msg = "") const;
562 
571  void assert_has_not(const JsonPointer& ptr, const std::string& msg = "") const;
572 
581  void assert_has_pointer_not(const std::string& ptr, const std::string& msg = "") const {
582  assert_has_not(JsonPointer(ptr), msg);
583  }
584 
595  [[nodiscard]] std::filesystem::path resolve_file(const std::filesystem::path& filename) const;
596 
607  [[nodiscard]] std::string resolve_file(const std::string& filename) const;
608 
618  template <typename... Args>
619  [[noreturn]] void throw_error(std::string_view format, Args&&... args) const {
620  throw_error(fmt::format(fmt::runtime(format), std::forward<Args>(args)...));
621  }
622 
627  [[noreturn]] void throw_error(const std::string& msg) const;
628 
636  [[noreturn]] void throw_unexpected(const std::string& key, const std::string& msg = "") const;
637 
645  [[noreturn]] void throw_unexpected(const JsonPointer& ptr, const std::string& msg = "") const;
646 
653  [[noreturn]] void throw_missing(const std::string& key) const;
654 
661  [[noreturn]] void throw_missing(const JsonPointer& ptr) const;
662 
669  [[noreturn]] void throw_wrong_type(const std::string& key = "") const;
670 
677  [[noreturn]] void throw_wrong_type(const JsonPointer& ptr) const;
678 
686  [[noreturn]] void throw_wrong_type(const std::string& key, JsonType expected) const;
687 
695  [[noreturn]] void throw_wrong_type(const JsonPointer& ptr, JsonType expected) const;
696 
702  friend void to_json(Json& j, const Conf& c) { j = *c; }
703 
709  friend void from_json(const Json& j, Conf& c) { *c = j; }
710 
711  private:
712  std::string file_;
713  std::string root_;
714  Json data_;
715 };
716 
717 } // namespace fable
Definition: conf.hpp:82
void try_from(const JsonPointer &ptr, T &val) const
Definition: conf.hpp:471
bool has(const std::string &key) const
Definition: conf.hpp:166
void with_pointer(const std::string &ptr, std::function< void(const T &)> fn) const
Definition: conf.hpp:441
T get_or(const std::string &key, T def) const
Definition: conf.hpp:361
void throw_error(std::string_view format, Args &&... args) const
Definition: conf.hpp:619
void with(const std::string &key, std::function< void(const T &)> fn) const
Definition: conf.hpp:412
void throw_unexpected(const std::string &key, const std::string &msg="") const
Definition: conf.cpp:173
const Json * operator->() const
Definition: conf.hpp:131
Conf at_pointer(const std::string &ptr) const
Definition: conf.hpp:224
std::filesystem::path resolve_file(const std::filesystem::path &filename) const
Definition: conf.cpp:152
bool has_pointer(const std::string &ptr) const
Definition: conf.hpp:190
friend void to_json(Json &j, const Conf &c)
Definition: conf.hpp:702
std::string root() const
Definition: conf.hpp:154
void assert_has_type(const std::string &key, JsonType t) const
Definition: conf.cpp:138
friend void from_json(const Json &j, Conf &c)
Definition: conf.hpp:709
void assert_has(const std::string &key) const
Definition: conf.cpp:110
T get_or(const JsonPointer &ptr, T def) const
Definition: conf.hpp:381
T get_pointer_or(const std::string &ptr, T def) const
Definition: conf.hpp:401
void try_from(const std::string &key, T &val) const
Definition: conf.hpp:455
void throw_missing(const std::string &key) const
Definition: conf.cpp:187
T get(const JsonPointer &ptr) const
Definition: conf.hpp:330
const std::string & file() const
Definition: conf.hpp:105
void try_from_pointer(const std::string &ptr, T &val) const
Definition: conf.hpp:492
const Json & operator*() const
Definition: conf.hpp:117
size_t erase(const std::string &key)
Definition: conf.cpp:74
bool is_from_file() const
Definition: conf.hpp:100
void throw_wrong_type(const std::string &key="") const
Definition: conf.cpp:195
Conf at(const std::string &key) const
Definition: conf.cpp:58
void assert_has_pointer_not(const std::string &ptr, const std::string &msg="") const
Definition: conf.hpp:581
void assert_has_not(const std::string &key, const std::string &msg="") const
Definition: conf.cpp:122
T get_pointer(const std::string &ptr) const
Definition: conf.hpp:348
size_t erase_pointer(const std::string &ptr, bool preserve_empty=false)
Definition: conf.hpp:272
void assert_has_pointer(const std::string &key) const
Definition: conf.hpp:519
void assert_has_pointer_type(const std::string &ptr, JsonType t) const
Definition: conf.hpp:550
T get() const
Definition: conf.hpp:298
bool is_empty() const
Definition: conf.hpp:110
Json & operator*()
Definition: conf.hpp:124
std::vector< Conf > to_array() const
Definition: conf.cpp:93
void with(const JsonPointer &ptr, std::function< void(const T &)> fn) const
Definition: conf.hpp:425
T get(const std::string &key) const
Definition: conf.hpp:313
Json * operator->()
Definition: conf.hpp:138
nlohmann::json Json
Definition: fable_fwd.hpp:35
nlohmann::json_pointer< std::string > JsonPointer
Definition: fable_fwd.hpp:36
nlohmann::json::value_t JsonType
Definition: json.hpp:78