Skip to content

Commit bfc8b9e

Browse files
committed
[logfmt] parse spans that are not kv-pairs
1 parent 6fa7e46 commit bfc8b9e

File tree

6 files changed

+210
-64
lines changed

6 files changed

+210
-64
lines changed

src/base/intern_string.hh

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,11 +586,11 @@ struct string_fragment {
586586
string_fragment{
587587
this->sf_string,
588588
this->sf_begin,
589-
this->sf_begin + curr,
589+
curr,
590590
},
591591
string_fragment{
592592
this->sf_string,
593-
this->sf_begin + curr + 1,
593+
curr + 1,
594594
this->sf_end,
595595
});
596596
}
@@ -601,6 +601,35 @@ struct string_fragment {
601601
return std::nullopt;
602602
}
603603

604+
template<typename P>
605+
split_when_result rsplit_when(P&& predicate) const
606+
{
607+
if (this->empty()) {
608+
return std::make_pair(string_fragment{}, string_fragment{});
609+
}
610+
611+
auto curr = this->sf_end - 1;
612+
while (curr >= this->sf_begin) {
613+
if (predicate(this->sf_string[curr])) {
614+
return std::make_pair(
615+
string_fragment{
616+
this->sf_string,
617+
this->sf_begin,
618+
curr + 1,
619+
},
620+
string_fragment{
621+
this->sf_string,
622+
curr + 1,
623+
this->sf_end,
624+
});
625+
}
626+
627+
curr -= 1;
628+
}
629+
630+
return std::make_pair(string_fragment{}, *this);
631+
}
632+
604633
using split_n_result = std::pair<string_fragment, string_fragment>;
605634

606635
split_n_result split_n(int amount) const;

src/formats/logfmt/logfmt.parser.cc

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@
3838
logfmt::parser::parser(string_fragment sf) : p_next_input(sf) {}
3939

4040
static bool
41-
is_not_eq(char ch)
41+
is_not_key(char ch)
4242
{
43-
return ch != '=';
43+
return !isalnum(ch) && ch != '_' && ch != '-' && ch != '.';
4444
}
4545

4646
struct bare_value_predicate {
@@ -181,20 +181,25 @@ logfmt::parser::step()
181181
return end_of_input{};
182182
}
183183

184-
auto pair_opt = remaining.split_while(is_not_eq);
185-
186-
if (!pair_opt) {
184+
auto [before, after] = remaining.split_when(string_fragment::tag1{'='});
185+
if (before.empty()) {
187186
return error{remaining.sf_begin, "expecting key followed by '='"};
188187
}
189188

190-
auto key_frag = pair_opt->first;
191-
auto after_eq = pair_opt->second.consume(string_fragment::tag1{'='});
189+
if (before.sf_end == remaining.sf_end) {
190+
this->p_next_input = after;
191+
return before;
192+
}
192193

193-
if (!after_eq) {
194-
return error{pair_opt->second.sf_begin, "expecting '='"};
194+
auto [plain, key] = before.rsplit_when(is_not_key);
195+
if (!plain.empty()) {
196+
this->p_next_input = key;
197+
this->p_next_input.sf_end = after.sf_end;
198+
return plain;
195199
}
196200

197-
auto value_start = after_eq.value();
201+
auto key_frag = before;
202+
auto value_start = after;
198203

199204
if (value_start.startswith("\"")) {
200205
string_fragment::quoted_string_body qsb;

src/formats/logfmt/logfmt.parser.hh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232
#ifndef lnav_logfmt_parser_hh
3333
#define lnav_logfmt_parser_hh
3434

35+
#include <utility>
36+
3537
#include "base/intern_string.hh"
36-
#include "base/result.h"
3738
#include "mapbox/variant.hpp"
3839

3940
namespace logfmt {
@@ -76,6 +77,7 @@ public:
7677
using kvpair = std::pair<string_fragment, value_type>;
7778

7879
using step_result = mapbox::util::variant<
80+
string_fragment,
7981
end_of_input,
8082
kvpair,
8183
error

0 commit comments

Comments
 (0)