Clio develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
Config.hpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of clio: https://github.com/XRPLF/clio
4 Copyright (c) 2022, the clio developers.
5
6 Permission to use, copy, modify, and 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
20#pragma once
21
22#include "util/config/impl/Helpers.hpp"
23
24#include <boost/json.hpp>
25#include <boost/json/kind.hpp>
26#include <boost/json/object.hpp>
27#include <boost/json/value.hpp>
28
29#include <chrono>
30#include <cstdint>
31#include <exception>
32#include <filesystem>
33#include <functional>
34#include <optional>
35#include <stdexcept>
36#include <string>
37#include <string_view>
38#include <utility>
39#include <vector>
40
41namespace util {
42
49class Config final {
50 boost::json::value store_;
51 static constexpr char kSEPARATOR = '.';
52
53public:
54 using KeyType = std::string;
55 using ArrayType = std::vector<Config>;
56 using WriteCursorType = std::pair<std::optional<std::reference_wrapper<boost::json::value>>, KeyType>;
57
62 explicit Config(boost::json::value store = {});
63
64 //
65 // Querying the store
66 //
67
74 operator bool() const noexcept;
75
84 [[nodiscard]] bool
85 contains(KeyType key) const;
86
87 //
88 // Key value access
89 //
90
106 template <typename Result>
107 [[nodiscard]] std::optional<Result>
108 maybeValue(KeyType key) const
109 {
110 auto maybeElement = lookup(key);
111 if (maybeElement)
112 return std::make_optional<Result>(checkedAs<Result>(key, *maybeElement));
113 return std::nullopt;
114 }
115
132 template <typename Result>
133 [[nodiscard]] Result
134 value(KeyType key) const
135 {
136 return maybeValue<Result>(key).value();
137 }
138
156 template <typename Result>
157 [[nodiscard]] Result
158 valueOr(KeyType key, Result fallback) const
159 {
160 try {
161 return maybeValue<Result>(key).value_or(fallback);
162 } catch (impl::StoreException const&) {
163 return fallback;
164 }
165 }
166
183 template <typename Result>
184 [[nodiscard]] Result
185 valueOrThrow(KeyType key, std::string_view err) const
186 {
187 try {
188 return maybeValue<Result>(key).value();
189 } catch (std::exception const&) {
190 throw std::runtime_error(std::string{err});
191 }
192 }
193
206 [[nodiscard]] std::optional<ArrayType>
207 maybeArray(KeyType key) const;
208
222 [[nodiscard]] ArrayType
223 array(KeyType key) const;
224
238 [[nodiscard]] ArrayType
239 arrayOr(KeyType key, ArrayType fallback) const;
240
255 [[nodiscard]] ArrayType
256 arrayOrThrow(KeyType key, std::string_view err) const;
257
270 [[nodiscard]] Config
271 section(KeyType key) const;
272
284 [[nodiscard]] Config
285 sectionOr(KeyType key, boost::json::object fallback) const;
286
287 //
288 // Direct self-value access
289 //
290
298 template <typename Result>
299 [[nodiscard]] std::optional<Result>
301 {
302 if (store_.is_null())
303 return std::nullopt;
304 return std::make_optional<Result>(checkedAs<Result>("_self_", store_));
305 }
306
314 template <typename Result>
315 [[nodiscard]] Result
316 value() const
317 {
318 return maybeValue<Result>().value();
319 }
320
329 template <typename Result>
330 [[nodiscard]] Result
331 valueOr(Result fallback) const
332 {
333 return maybeValue<Result>().valueOr(fallback);
334 }
335
345 template <typename Result>
346 [[nodiscard]] Result
347 valueOrThrow(std::string_view err) const
348 {
349 try {
350 return maybeValue<Result>().value();
351 } catch (std::exception const&) {
352 throw std::runtime_error(std::string{err});
353 }
354 }
355
363 [[nodiscard]] ArrayType
364 array() const;
365
372 static std::chrono::milliseconds
373 toMilliseconds(float value);
374
375private:
376 template <typename Return>
377 [[nodiscard]] Return
378 checkedAs(KeyType key, boost::json::value const& value) const
379 {
380 using boost::json::value_to;
381
382 auto errorIf = [&key, &value](bool condition) {
383 if (condition) {
384 throw std::runtime_error(
385 "Type for key '" + key + "' is '" + std::string{to_string(value.kind())} +
386 "' in JSON but requested '" + impl::typeName<Return>() + "'"
387 );
388 }
389 };
390
391 if constexpr (std::is_same_v<Return, bool>) {
392 errorIf(not value.is_bool());
393 } else if constexpr (std::is_same_v<Return, std::string>) {
394 errorIf(not value.is_string());
395 } else if constexpr (std::is_same_v<Return, double> or std::is_same_v<Return, float>) {
396 errorIf(not value.is_number());
397 } else if constexpr (std::is_convertible_v<Return, uint64_t> || std::is_convertible_v<Return, int64_t>) {
398 errorIf(not value.is_int64() && not value.is_uint64());
399 }
400
401 return value_to<Return>(value);
402 }
403
404 std::optional<boost::json::value>
405 lookup(KeyType key) const;
406
407 WriteCursorType
408 lookupForWrite(KeyType key);
409};
410
417class ConfigReader final {
418public:
425 static Config
426 open(std::filesystem::path path);
427};
428
429} // namespace util
Simple configuration file reader.
Definition Config.hpp:417
static Config open(std::filesystem::path path)
Read in a configuration file.
Definition Config.cpp:191
Convenience wrapper to query a JSON configuration file.
Definition Config.hpp:49
Result valueOrThrow(KeyType key, std::string_view err) const
Interface for fetching values by key with custom error handling.
Definition Config.hpp:185
std::optional< ArrayType > maybeArray(KeyType key) const
Interface for fetching an array by key that returns std::optional.
Definition Config.cpp:104
Result value() const
Interface for reading the value directly referred to by the instance.
Definition Config.hpp:316
ArrayType array() const
Interface for reading the array directly referred to by the instance.
Definition Config.cpp:170
Config(boost::json::value store={})
Construct a new Config object.
Definition Config.cpp:53
ArrayType arrayOr(KeyType key, ArrayType fallback) const
Interface for fetching an array by key with fallback.
Definition Config.cpp:134
bool contains(KeyType key) const
Checks whether something exists under given key.
Definition Config.cpp:63
Result valueOr(Result fallback) const
Interface for reading the value directly referred to by the instance with user-specified fallback.
Definition Config.hpp:331
Config sectionOr(KeyType key, boost::json::object fallback) const
Interface for fetching a sub section by key with a fallback object.
Definition Config.cpp:161
ArrayType arrayOrThrow(KeyType key, std::string_view err) const
Interface for fetching an array by key with custom error handling.
Definition Config.cpp:142
Result valueOr(KeyType key, Result fallback) const
Interface for fetching values by key with fallback.
Definition Config.hpp:158
Config section(KeyType key) const
Interface for fetching a sub section by key.
Definition Config.cpp:152
Result value(KeyType key) const
Interface for fetching values by key.
Definition Config.hpp:134
std::optional< Result > maybeValue() const
Interface for reading the value directly referred to by the instance. Wraps as std::optional.
Definition Config.hpp:300
static std::chrono::milliseconds toMilliseconds(float value)
Method to convert a float seconds value to milliseconds.
Definition Config.cpp:184
std::optional< Result > maybeValue(KeyType key) const
Interface for fetching values by key that returns std::optional.
Definition Config.hpp:108
Result valueOrThrow(std::string_view err) const
Interface for reading the value directly referred to by the instance with user-specified error messag...
Definition Config.hpp:347
This namespace contains various utilities.
Definition AccountUtils.hpp:30
Thrown when a Store (config's storage) related error occurs.
Definition Helpers.hpp:43