$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 #include <fable/fable_fwd.hpp> // for ConfError
61 #include <fable/json.hpp> // for Json
62 
63 namespace fable {
64 
81 class Conf {
82  public:
83  Conf() = default;
84  explicit Conf(Json data) : data_(std::move(data)) {}
85  explicit Conf(std::string file);
86  Conf(Json data, std::string file) : file_(std::move(file)), data_(std::move(data)) {}
87  Conf(Json data, std::string file, std::string root)
88  : file_(std::move(file)), root_(std::move(root)), data_(std::move(data)) {}
89 
99  [[nodiscard]] bool is_from_file() const { return !file_.empty(); }
100 
104  [[nodiscard]] const std::string& file() const { return file_; }
105 
109  [[nodiscard]] bool is_empty() const { return data_.is_null(); }
110 
116  const Json& operator*() const { return data_; }
117 
123  Json& operator*() { return data_; }
124 
130  const Json* operator->() const { return &data_; }
131 
137  Json* operator->() { return &data_; }
138 
153  [[nodiscard]] std::string root() const { return (root_.empty() ? "/" : root_); }
154 
165  [[nodiscard]] bool has(const std::string& key) const { return data_.count(key) != 0; }
166 
177  [[nodiscard]] bool has(const JsonPointer& ptr) const;
178 
189  [[nodiscard]] bool has_pointer(const std::string& ptr) const { return has(JsonPointer(ptr)); }
190 
200  [[nodiscard]] Conf at(const std::string& key) const;
201 
211  [[nodiscard]] Conf at(const JsonPointer& ptr) const;
212 
223  [[nodiscard]] Conf at_pointer(const std::string& ptr) const { return at(JsonPointer(ptr)); }
224 
235  size_t erase(const std::string& key);
236 
253  size_t erase(const JsonPointer& ptr, bool preserve_empty = false);
254 
271  size_t erase_pointer(const std::string& ptr, bool preserve_empty = false) {
272  return erase(JsonPointer(ptr), preserve_empty);
273  }
274 
289  [[nodiscard]] std::vector<Conf> to_array() const;
290 
296  template <typename T>
297  [[nodiscard]] T get() const {
298  try {
299  return data_.get<T>();
300  } catch (Json::type_error&) {
302  }
303  }
304 
311  template <typename T>
312  [[nodiscard]] T get(const std::string& key) const {
313  try {
314  return data_.at(key).get<T>();
315  } catch (Json::out_of_range&) {
316  throw_missing(key);
317  } catch (Json::type_error&) {
318  throw_wrong_type(key);
319  }
320  }
321 
328  template <typename T>
329  [[nodiscard]] T get(const JsonPointer& ptr) const {
330  try {
331  return data_.at(ptr).get<T>();
332  } catch (Json::out_of_range&) {
333  throw_missing(ptr);
334  } catch (Json::type_error&) {
335  throw_wrong_type(ptr);
336  }
337  }
338 
346  template <typename T>
347  [[nodiscard]] T get_pointer(const std::string& ptr) const {
348  return get<T>(JsonPointer(ptr));
349  }
350 
359  template <typename T>
360  [[nodiscard]] T get_or(const std::string& key, T def) const {
361  if (!data_.count(key)) {
362  return def;
363  }
364  try {
365  return data_.at(key).get<T>();
366  } catch (Json::type_error&) {
367  throw_wrong_type(key);
368  }
369  }
370 
379  template <typename T>
380  [[nodiscard]] T get_or(const JsonPointer& ptr, T def) const {
381  try {
382  return data_.at(ptr).get<T>();
383  } catch (Json::out_of_range&) {
384  return def;
385  } catch (Json::type_error&) {
386  throw_wrong_type(ptr);
387  }
388  }
389 
399  template <typename T>
400  [[nodiscard]] T get_pointer_or(const std::string& ptr, T def) const {
401  return get_or(JsonPointer(ptr), def);
402  }
403 
410  template <typename T>
411  void with(const std::string& key, std::function<void(const T&)> fn) const {
412  if (data_.count(key)) {
413  fn(get<T>(key));
414  }
415  }
416 
423  template <typename T>
424  void with(const JsonPointer& ptr, std::function<void(const T&)> fn) const {
425  try {
426  fn(get<T>(ptr));
427  } catch (Json::out_of_range&) {
428  return;
429  }
430  }
431 
439  template <typename T>
440  void with_pointer(const std::string& ptr, std::function<void(const T&)> fn) const {
441  with(JsonPointer(ptr), fn);
442  }
443 
453  template <typename T>
454  void try_from(const std::string& key, T& val) const {
455  if (data_.count(key)) {
456  val = get<T>(key);
457  }
458  }
459 
469  template <typename T>
470  void try_from(const JsonPointer& ptr, T& val) const {
471  try {
472  val = data_.at(ptr).get<T>();
473  } catch (Json::out_of_range& e) {
474  return;
475  } catch (Json::type_error& e) {
476  throw_wrong_type(ptr);
477  }
478  }
479 
490  template <typename T>
491  void try_from_pointer(const std::string& ptr, T& val) const {
492  try_from(JsonPointer(ptr), val);
493  }
494 
501  void assert_has(const std::string& key) const;
502 
509  void assert_has(const JsonPointer& ptr) const;
510 
518  void assert_has_pointer(const std::string& key) const { assert_has(JsonPointer(key)); }
519 
528  void assert_has_type(const std::string& key, JsonType t) const;
529 
538  void assert_has_type(const JsonPointer& ptr, JsonType t) const;
539 
549  void assert_has_pointer_type(const std::string& ptr, JsonType t) const {
550  assert_has_type(JsonPointer(ptr), t);
551  }
552 
560  void assert_has_not(const std::string& key, const std::string& msg = "") const;
561 
570  void assert_has_not(const JsonPointer& ptr, const std::string& msg = "") const;
571 
580  void assert_has_pointer_not(const std::string& ptr, const std::string& msg = "") const {
581  assert_has_not(JsonPointer(ptr), msg);
582  }
583 
594  [[nodiscard]] std::filesystem::path resolve_file(const std::filesystem::path& filename) const;
595 
606  [[nodiscard]] std::string resolve_file(const std::string& filename) const;
607 
617  template <typename... Args>
618  [[noreturn]] void throw_error(std::string_view format, Args&&... args) const {
619  throw_error(fmt::format(fmt::runtime(format), std::forward<Args>(args)...));
620  }
621 
626  [[noreturn]] void throw_error(const std::string& msg) const;
627 
635  [[noreturn]] void throw_unexpected(const std::string& key, const std::string& msg = "") const;
636 
644  [[noreturn]] void throw_unexpected(const JsonPointer& ptr, const std::string& msg = "") const;
645 
652  [[noreturn]] void throw_missing(const std::string& key) const;
653 
660  [[noreturn]] void throw_missing(const JsonPointer& ptr) const;
661 
668  [[noreturn]] void throw_wrong_type(const std::string& key = "") const;
669 
676  [[noreturn]] void throw_wrong_type(const JsonPointer& ptr) const;
677 
685  [[noreturn]] void throw_wrong_type(const std::string& key, JsonType expected) const;
686 
694  [[noreturn]] void throw_wrong_type(const JsonPointer& ptr, JsonType expected) const;
695 
701  friend void to_json(Json& j, const Conf& c) { j = *c; }
702 
708  friend void from_json(const Json& j, Conf& c) { *c = j; }
709 
710  private:
711  std::string file_;
712  std::string root_;
713  Json data_;
714 };
715 
716 } // namespace fable
Definition: conf.hpp:81
void try_from(const JsonPointer &ptr, T &val) const
Definition: conf.hpp:470
bool has(const std::string &key) const
Definition: conf.hpp:165
void with_pointer(const std::string &ptr, std::function< void(const T &)> fn) const
Definition: conf.hpp:440
T get_or(const std::string &key, T def) const
Definition: conf.hpp:360
void throw_error(std::string_view format, Args &&... args) const
Definition: conf.hpp:618
void with(const std::string &key, std::function< void(const T &)> fn) const
Definition: conf.hpp:411
void throw_unexpected(const std::string &key, const std::string &msg="") const
Definition: conf.cpp:173
const Json * operator->() const
Definition: conf.hpp:130
Conf at_pointer(const std::string &ptr) const
Definition: conf.hpp:223
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:189
friend void to_json(Json &j, const Conf &c)
Definition: conf.hpp:701
std::string root() const
Definition: conf.hpp:153
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:708
void assert_has(const std::string &key) const
Definition: conf.cpp:110
T get_or(const JsonPointer &ptr, T def) const
Definition: conf.hpp:380
T get_pointer_or(const std::string &ptr, T def) const
Definition: conf.hpp:400
void try_from(const std::string &key, T &val) const
Definition: conf.hpp:454
void throw_missing(const std::string &key) const
Definition: conf.cpp:187
T get(const JsonPointer &ptr) const
Definition: conf.hpp:329
const std::string & file() const
Definition: conf.hpp:104
void try_from_pointer(const std::string &ptr, T &val) const
Definition: conf.hpp:491
const Json & operator*() const
Definition: conf.hpp:116
size_t erase(const std::string &key)
Definition: conf.cpp:74
bool is_from_file() const
Definition: conf.hpp:99
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:580
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:347
size_t erase_pointer(const std::string &ptr, bool preserve_empty=false)
Definition: conf.hpp:271
void assert_has_pointer(const std::string &key) const
Definition: conf.hpp:518
void assert_has_pointer_type(const std::string &ptr, JsonType t) const
Definition: conf.hpp:549
T get() const
Definition: conf.hpp:297
bool is_empty() const
Definition: conf.hpp:109
Json & operator*()
Definition: conf.hpp:123
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:424
T get(const std::string &key) const
Definition: conf.hpp:312
Json * operator->()
Definition: conf.hpp:137
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