userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
array_parser.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/formats/json/parser/array_parser.hpp
4
/// @brief @copybrief formats::json::parser::ArrayParser
5
/// @ingroup userver_universal
6
7
#
include
<
vector
>
8
9
#
include
<
userver
/
formats
/
common
/
path
.
hpp
>
10
#
include
<
userver
/
formats
/
json
/
parser
/
typed_parser
.
hpp
>
11
#
include
<
userver
/
utils
/
meta
.
hpp
>
12
13
USERVER_NAMESPACE_BEGIN
14
15
/// @brief Streaming JSON SAX parsers and parser stack.
16
namespace
formats::
json
::
parser
{
17
18
/// @brief SAX parser that fills arrays or sets from JSON arrays.
19
template
<
typename
Item,
typename
ItemParser,
typename
Array = std::vector<Item>>
20
class
ArrayParser
final
:
public
TypedParser
<Array>,
public
Subscriber
<Item> {
21
public
:
22
explicit
ArrayParser(ItemParser& item_parser)
23
: item_parser_(item_parser)
24
{
25
this
->item_parser_.Subscribe(*
this
);
26
}
27
28
void
Reset
()
override
{
29
index_ = 0;
30
state_ = State::kStart;
31
storage_.clear();
32
33
if
constexpr
(meta::
kIsVector
<Array>) {
34
/*
35
* Heuristics:
36
* STL impls have a small initial capacity of vector.
37
* It leads to multiple reallocations during inserts.
38
* We intentionally give up some maybe-unused space to lower realloc
39
* count.
40
*/
41
storage_.reserve(16);
42
}
43
}
44
45
protected
:
46
void
StartArray()
override
{
47
if
(state_ == State::kStart) {
48
state_ = State::kInside;
49
}
else
{
50
PushParser(
"array"
);
51
Parser().StartArray();
52
}
53
}
54
void
EndArray()
override
{
55
if
(state_ == State::kInside) {
56
this
->SetResult(std::move(storage_));
57
return
;
58
}
59
// impossible?
60
this
->Throw(
"end of array"
);
61
}
62
63
void
Int64(int64_t i)
override
{
64
PushParser(
"integer"
);
65
Parser().Int64(i);
66
}
67
void
Uint64(uint64_t i)
override
{
68
PushParser(
"integer"
);
69
Parser().Uint64(i);
70
}
71
void
Null()
override
{
72
PushParser(
"null"
);
73
Parser().Null();
74
}
75
void
Bool(
bool
b)
override
{
76
PushParser(
"bool"
);
77
Parser().Bool(b);
78
}
79
void
Double(
double
d)
override
{
80
PushParser(
"double"
);
81
Parser().Double(d);
82
}
83
void
String(std::string_view sw)
override
{
84
PushParser(
"string"
);
85
Parser().String(sw);
86
}
87
void
StartObject()
override
{
88
PushParser(
"object"
);
89
Parser().StartObject();
90
}
91
92
std::string Expected()
const
override
{
return
"array"
; }
93
94
void
PushParser(std::string_view what) {
95
if
(state_ != State::kInside) {
96
// Error path must not include [x] - we're not inside an array yet
97
this
->parser_state_->PopMe(*
this
);
98
99
this
->Throw(std::string(what));
100
}
101
102
this
->item_parser_.Reset();
103
this
->parser_state_->PushParser(item_parser_.GetParser());
104
index_++;
105
}
106
107
void
OnSend(Item&& item)
override
{
108
if
constexpr
(!meta::
kIsVector
<Array>) {
109
this
->storage_.insert(std::move(item));
110
}
else
{
111
this
->storage_.push_back(std::move(item));
112
}
113
}
114
115
std::string GetPathItem()
const
override
{
return
common
::
GetIndexString
(
index_ - 1
)
; }
116
117
BaseParser
& Parser() {
return
item_parser_.GetParser(); }
118
119
private
:
120
ItemParser& item_parser_;
121
std::optional<size_t> min_items_, max_items_;
122
123
enum
class
State {
124
kStart,
125
kInside,
126
};
127
size_t index_{0};
128
State state_{State::kStart};
129
Array storage_;
130
};
131
132
}
// namespace formats::json::parser
133
134
USERVER_NAMESPACE_END
userver
formats
json
parser
array_parser.hpp
Generated on
for userver by
Doxygen
1.17.0