userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
utils.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/formats/common/utils.hpp
4
/// @brief formats::common::GetAtPath and formats::common::RemoveAtPath utils
5
/// for `Value` and `ValueBuilder`
6
/// @ingroup userver_universal
7
8
#
include
<
cstddef
>
9
#
include
<
optional
>
10
#
include
<
string
>
11
#
include
<
string_view
>
12
#
include
<
utility
>
13
#
include
<
vector
>
14
15
#
include
<
userver
/
formats
/
common
/
meta
.
hpp
>
16
#
include
<
userver
/
formats
/
common
/
transfer_tag
.
hpp
>
17
#
include
<
userver
/
formats
/
common
/
type
.
hpp
>
18
#
include
<
userver
/
utils
/
assert
.
hpp
>
19
20
USERVER_NAMESPACE_BEGIN
21
22
namespace
formats::common {
23
24
namespace
impl {
25
26
template
<
typename
ValueBuilder>
27
ValueBuilder GetAtPath(ValueBuilder& parent, std::vector<std::string>&& path, std::size_t path_size) {
28
UINVARIANT
(path_size != 0,
"attempt to get a ValueBuilder element on an empty path"
);
29
if
(path_size == 1) {
30
return
parent[std::move(path[0])];
31
}
32
std::optional<ValueBuilder> current_element;
33
34
current_element.emplace(TransferTag(), parent[std::move(path[0])]);
35
for
(std::size_t i = 1; i < path_size - 1; i++) {
36
current_element.emplace(TransferTag(), (*current_element)[std::move(path[i])]);
37
}
38
return
(*current_element)[std::move(path[path_size - 1])];
39
}
40
41
}
// namespace impl
42
43
/// @brief Get the `Value` at `path` in `parent`.
44
/// @note For empty `path` this function returns `parent`.
45
/// @throws TypeMismatchException if there is a non-object node in the middle of
46
/// `path`
47
template
<
common
::IsFormatValue Value>
48
Value
GetAtPath
(Value parent,
const
std::vector<std::string>& path) {
49
auto
current_value = std::move(parent);
50
for
(
const
auto
& current_key : path) {
51
current_value = current_value[current_key];
52
}
53
return
current_value;
54
}
55
56
/// @brief Get the `ValueBuilder` at `path` in `parent`.
57
/// @note `path` must not be empty.
58
/// @throws TypeMismatchException if there is a non-object node in the middle of
59
/// `path`
60
template
<
typename
ValueBuilder>
61
requires
(!common::IsFormatValue<ValueBuilder>)
62
ValueBuilder
GetAtPath
(ValueBuilder& parent, std::vector<std::string>&& path) {
63
return
impl::GetAtPath(parent, std::move(path), path.size());
64
}
65
66
/// @brief Set the `new_value` along the `path` in the `parent`.
67
/// @note If `path` is empty it sets `new_value` to `parent`.
68
/// @throws TypeMismatchException if there is a non-object node in the middle of
69
/// `path`
70
template
<
typename
Value>
71
void
SetAtPath
(
typename
Value::Builder& parent, std::vector<std::string>&& path, Value new_value) {
72
if
(path.empty()) {
73
parent = std::move(new_value);
74
}
else
{
75
GetAtPath(parent, std::move(path)) = std::move(new_value);
76
}
77
}
78
79
/// @brief Remove the element along the `path` in the `parent`.
80
/// @note If `path` is empty or there is no node at `path`, this function does
81
/// nothing.
82
/// @throws TypeMismatchException if there is a non-object node in the middle of
83
/// `path`
84
template
<
typename
ValueBuilder>
85
void
RemoveAtPath
(ValueBuilder& parent, std::vector<std::string>&& path) {
86
if
(path.empty()) {
87
parent = ValueBuilder();
88
}
else
if
(path.size() == 1) {
89
parent.Remove(path[0]);
90
}
else
{
91
auto
& key = path[path.size() - 1];
92
impl::GetAtPath(parent, std::move(path), path.size() - 1).Remove(key);
93
}
94
}
95
96
/// @brief Split `path` to `vector<std::string>` by dots.
97
/// @note If `path` has a double dot or a dot at the beginning or end, the
98
/// result will contain an empty string.
99
/// @note Returns an empty `vector` if `path` is empty
100
std::vector<std::string>
SplitPathString
(std::string_view path);
101
102
}
// namespace formats::common
103
104
USERVER_NAMESPACE_END
userver
formats
common
utils.hpp
Generated on
for userver by
Doxygen
1.17.0