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