-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlog_parser.cpp
More file actions
75 lines (62 loc) · 2.43 KB
/
Copy pathlog_parser.cpp
File metadata and controls
75 lines (62 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "log_parser.h"
namespace {
// Advance p past any spaces.
inline void skip_spaces(const char*& p, const char* end) {
while (p < end && *p == ' ') ++p;
}
// Return the next space-delimited token as [tok_begin, p) and advance p to the
// delimiter. Returns an empty view if none remain.
inline std::string_view next_token(const char*& p, const char* end) {
skip_spaces(p, end);
const char* tok = p;
while (p < end && *p != ' ') ++p;
return std::string_view(tok, static_cast<std::size_t>(p - tok));
}
inline bool starts_with(std::string_view s, std::string_view prefix) {
return s.size() >= prefix.size() && s.substr(0, prefix.size()) == prefix;
}
// Parse an unsigned integer from a string_view. Returns false on empty input or
// any non-digit. Caps at uint64 without overflow checks (log values fit easily).
template <typename T>
inline bool parse_uint(std::string_view s, T& out) {
if (s.empty()) return false;
T v = 0;
for (char c : s) {
if (c < '0' || c > '9') return false;
v = v * 10 + static_cast<T>(c - '0');
}
out = v;
return true;
}
} // namespace
bool parse_line(const char* begin, const char* end, LogRecord& out) {
const char* p = begin;
// Timestamp: "YYYY-MM-DD" then "HH:MM:SS". They are contiguous in the buffer
// separated by one space, so the 16-byte minute label "YYYY-MM-DD HH:MM" is a
// single substring starting at the date token.
std::string_view date = next_token(p, end);
if (date.size() != 10) return false;
std::string_view time = next_token(p, end);
if (time.size() < 5) return false;
// Require the single-space layout so the 16-byte slice is exactly the minute.
if (time.data() != date.data() + 11) return false;
out.minute = std::string_view(date.data(), 16);
// Level.
out.level = next_token(p, end);
if (out.level.empty()) return false;
out.is_error = (out.level == "ERROR");
// user=<int>
std::string_view user_tok = next_token(p, end);
if (!starts_with(user_tok, "user=")) return false;
if (!parse_uint(user_tok.substr(5), out.user_id)) return false;
// endpoint=</path>
std::string_view ep_tok = next_token(p, end);
if (!starts_with(ep_tok, "endpoint=")) return false;
out.endpoint = ep_tok.substr(9);
if (out.endpoint.empty()) return false;
// latency=<int>
std::string_view lat_tok = next_token(p, end);
if (!starts_with(lat_tok, "latency=")) return false;
if (!parse_uint(lat_tok.substr(8), out.latency)) return false;
return true;
}