userver
C++ Async Framework
Loading...
Searching...
No Matches
tskv_parser.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/utils/encoding/tskv_parser.hpp
4
/// @brief @copybrief utils::encoding::TskvParser
5
6
#
include
<
optional
>
7
#
include
<
string
>
8
#
include
<
string_view
>
9
10
USERVER_NAMESPACE_BEGIN
11
12
namespace
utils::encoding {
13
14
/// @brief A streaming parser for the TSKV variant that userver emits.
15
///
16
/// **Supported syntax**
17
/// 1. Records are separated by a single non-escaped `\n` character
18
/// 2. A record consists of entries separated by a single `\t` character
19
/// 3. The first entry SHOULD be verbatim `tskv`
20
/// 4. Entries MAY have values, separated by the first non-escaped `=`
21
/// 5. An entry MAY have no key-value split, in which case it all counts as key
22
///
23
/// **Escaping**
24
/// 1. `\n`, `\t`, `\\` in keys or values SHOULD be escaped as
25
/// `"\\\n"`, `"\\\t"`, `"\\\\"`
26
/// 2. `=` SHOULD be escaped as `"\\="` in keys, MAY be escaped in values
27
/// 3. `\r` and `\0` MAY be escaped as `"\\\r"`, `"\\\0"`
28
///
29
/// **Parsing process**
30
/// Initialize `TskvParser` with a caller-owned string that may contain a single
31
/// or multiple TSKV records. For each record, first call `SkipToRecordBegin`.
32
/// Then call `ReadKey` and `ReadValue` a bunch of times.
33
///
34
/// For a simpler way to read TSKV records, see utils::encoding::TskvReadRecord.
35
class
TskvParser
final
{
36
public
:
37
/// The status is returned once the record is complete. We ignore invalid
38
/// escaping, not reporting it as an error, trying to push through.
39
/// `nullopt` status means we should keep reading the current TSKV record.
40
enum
class
[[nodiscard]]
RecordStatus
{
41
kReachedEnd
,
///< successfully read the whole record
42
kIncomplete
,
///< the record ends abruptly, the service is probably
43
///< still writing the record
44
};
45
46
explicit
TskvParser(std::string_view in)
noexcept
;
47
48
/// @brief Skips the current record or optional invalid junk until it finds
49
/// the start of the a valid record.
50
/// @returns pointer to the start of the next record if there is one,
51
/// `nullptr` otherwise
52
/// @note `tskv\n` records are currently not supported
53
const
char
*
SkipToRecordBegin
()
noexcept
;
54
55
/// @brief Skips to the end of the current record, which might not be the same
56
/// as the start of the next valid record.
57
/// @note RecordStatus::kReachedEnd SHOULD
58
/// not have been returned for the current record, otherwise the behavior is
59
/// unspecified.
60
/// @note `tskv\n` records are currently not supported
61
RecordStatus
SkipToRecordEnd
()
noexcept
;
62
63
/// @brief Parses the key, replacing `result` with it.
64
/// @throws std::bad_alloc only if `std::string` allocation throws
65
/// @note RecordStatus::kReachedEnd is returned specifically
66
/// on a trailing `\t\n` sequence
67
std::optional<
RecordStatus
>
ReadKey
(std::string& result);
68
69
/// @brief Parses the value, replacing `result` with it.
70
/// @throws std::bad_alloc only if `std::string` allocation throws
71
std::optional<
RecordStatus
>
ReadValue
(std::string& result);
72
73
/// @returns pointer to the data that will be read by the next operation
74
const
char
*
GetStreamPosition
()
const
noexcept
;
75
76
private
:
77
std::string_view in_;
78
};
79
80
}
// namespace utils::encoding
81
82
USERVER_NAMESPACE_END
userver
utils
encoding
tskv_parser.hpp
Generated on Thu Sep 5 2024 11:25:29 for userver by
Doxygen
1.10.0