mirror of
https://github.com/tstack/lnav
synced 2024-11-17 15:29:40 +00:00
[pcrepp] add support for named captures and fix some other bugs
This commit is contained in:
parent
63c6855a99
commit
6d77a7412e
@ -147,12 +147,27 @@ private:
|
||||
|
||||
};
|
||||
|
||||
inline long kmerge_tree_brute_log2(long value)
|
||||
{
|
||||
|
||||
long square = 2;
|
||||
long count = 1;
|
||||
while ( square < value )
|
||||
{
|
||||
square *= 2;
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
} // kmerge_tree_brute_log2
|
||||
|
||||
//~~~~~~~~~~class kmerge_tree_c
|
||||
|
||||
template <class T, class owner_t, class iterator_t, class comparitor>
|
||||
kmerge_tree_c<T, owner_t, iterator_t, comparitor>::kmerge_tree_c(long bucket_qty) :
|
||||
bucket_qty_mbr(bucket_qty),
|
||||
number_of_levels_mbr(bucket_qty ? ::log2(bucket_qty_mbr) : 0), // don't add one - build_levels is zero based
|
||||
number_of_levels_mbr(bucket_qty ? ::kmerge_tree_brute_log2(bucket_qty_mbr) : 0), // don't add one - build_levels is zero based
|
||||
top_node_ptr_mbr(NULL),
|
||||
first_leaf_ptr(NULL),
|
||||
last_leaf_ptr(NULL)
|
||||
|
@ -896,6 +896,11 @@ static void moveto_cluster(vis_line_t(bookmark_vector<vis_line_t>::*f) (
|
||||
time_t last_time;
|
||||
logline * ll;
|
||||
|
||||
if (lss.empty()) {
|
||||
flash();
|
||||
return;
|
||||
}
|
||||
|
||||
ll = lss.find_line(lss.at(top));
|
||||
last_time = ll->get_time();
|
||||
last_level = ll->get_level();
|
||||
|
@ -368,7 +368,7 @@ bool logfile_sub_source::rebuild_index(observer *obs, bool force)
|
||||
}
|
||||
|
||||
if (retval || force) {
|
||||
size_t index_size;
|
||||
size_t index_size = 0;
|
||||
|
||||
if (force) {
|
||||
this->lss_index.clear();
|
||||
|
@ -118,6 +118,9 @@ public:
|
||||
{
|
||||
return this->lss_index.size();
|
||||
};
|
||||
|
||||
bool empty() const { return this->lss_index.empty(); };
|
||||
|
||||
void text_value_for_line(textview_curses &tc,
|
||||
int row,
|
||||
std::string &value_out,
|
||||
|
@ -36,6 +36,19 @@
|
||||
const int JIT_STACK_MIN_SIZE = 32 * 1024;
|
||||
const int JIT_STACK_MAX_SIZE = 512 * 1024;
|
||||
|
||||
pcre_context::capture_t *pcre_context::operator[](const char *name) const
|
||||
{
|
||||
capture_t *retval = NULL;
|
||||
int index;
|
||||
|
||||
index = this->pc_pcre->name_index(name);
|
||||
if (index != PCRE_ERROR_NOSUBSTRING) {
|
||||
retval = &this->pc_captures[index + 1];
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef PCRE_STUDY_JIT_COMPILE
|
||||
pcre_jit_stack *pcrepp::jit_stack(void)
|
||||
{
|
||||
|
@ -57,6 +57,8 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class pcrepp;
|
||||
|
||||
/**
|
||||
* Context that tracks captures found during a match operation. This class is a
|
||||
* base that defines iterator methods and fields, but does not allocate space
|
||||
@ -95,6 +97,8 @@ public:
|
||||
return this->pc_count;
|
||||
};
|
||||
|
||||
void set_pcrepp(const pcrepp *src) { this->pc_pcre = src; };
|
||||
|
||||
/**
|
||||
* @return a capture_t that covers all of the text that was matched.
|
||||
*/
|
||||
@ -105,10 +109,17 @@ public:
|
||||
/** @return An iterator that refers to the end of the capture array. */
|
||||
iterator end() { return pc_captures + pc_count; };
|
||||
|
||||
capture_t *operator[](int offset) {
|
||||
return &this->pc_captures[offset + 1];
|
||||
};
|
||||
|
||||
capture_t *operator[](const char *name) const;
|
||||
|
||||
protected:
|
||||
pcre_context(capture_t *captures, int max_count)
|
||||
: pc_captures(captures), pc_max_count(max_count), pc_count(0) { };
|
||||
|
||||
const pcrepp *pc_pcre;
|
||||
capture_t *pc_captures;
|
||||
int pc_max_count;
|
||||
int pc_count;
|
||||
@ -216,6 +227,50 @@ private:
|
||||
const char *pi_string;
|
||||
};
|
||||
|
||||
struct pcre_named_capture {
|
||||
class iterator {
|
||||
public:
|
||||
iterator(pcre_named_capture *pnc, size_t name_len)
|
||||
: i_named_capture(pnc), i_name_len(name_len)
|
||||
{
|
||||
};
|
||||
|
||||
iterator() : i_named_capture(NULL), i_name_len(0) { };
|
||||
|
||||
const pcre_named_capture &operator*(void) const {
|
||||
return *this->i_named_capture;
|
||||
};
|
||||
|
||||
const pcre_named_capture *operator->(void) const {
|
||||
return this->i_named_capture;
|
||||
};
|
||||
|
||||
bool operator!=(const iterator &rhs) const {
|
||||
return this->i_named_capture != rhs.i_named_capture;
|
||||
};
|
||||
|
||||
iterator &operator++() {
|
||||
char *ptr = (char *)this->i_named_capture;
|
||||
|
||||
ptr += this->i_name_len;
|
||||
this->i_named_capture = (pcre_named_capture *)ptr;
|
||||
return *this;
|
||||
};
|
||||
|
||||
private:
|
||||
pcre_named_capture *i_named_capture;
|
||||
size_t i_name_len;
|
||||
};
|
||||
|
||||
int index() const {
|
||||
return (this->pnc_index_msb << 8 | this->pnc_index_lsb);
|
||||
};
|
||||
|
||||
char pnc_index_msb;
|
||||
char pnc_index_lsb;
|
||||
char pnc_name[];
|
||||
};
|
||||
|
||||
class pcrepp {
|
||||
public:
|
||||
class error : public std::exception {
|
||||
@ -272,6 +327,28 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
pcre_named_capture::iterator named_begin() const {
|
||||
return pcre_named_capture::iterator(this->p_named_entries,
|
||||
this->p_name_len);
|
||||
};
|
||||
|
||||
pcre_named_capture::iterator named_end() const {
|
||||
char *ptr = (char *)this->p_named_entries;
|
||||
|
||||
ptr += this->p_named_count * this->p_name_len;
|
||||
return pcre_named_capture::iterator((pcre_named_capture *)ptr,
|
||||
this->p_name_len);
|
||||
};
|
||||
|
||||
int name_index(const char *name) const {
|
||||
int retval = pcre_get_stringnumber(this->p_code, name);
|
||||
|
||||
if (retval == PCRE_ERROR_NOSUBSTRING)
|
||||
return retval;
|
||||
|
||||
return retval - 1;
|
||||
};
|
||||
|
||||
bool match(pcre_context &pc, pcre_input &pi, int options = 0) const
|
||||
{
|
||||
int length, startoffset, filtered_options = options;
|
||||
@ -279,6 +356,7 @@ public:
|
||||
const char *str;
|
||||
int rc;
|
||||
|
||||
pc.set_pcrepp(this);
|
||||
pi.pi_offset = pi.pi_next_offset;
|
||||
|
||||
str = pi.get_string();
|
||||
@ -369,9 +447,24 @@ private:
|
||||
pcre_assign_jit_stack(extra, NULL, jit_stack());
|
||||
#endif
|
||||
}
|
||||
pcre_fullinfo(this->p_code,
|
||||
this->p_code_extra,
|
||||
PCRE_INFO_NAMECOUNT,
|
||||
&this->p_named_count);
|
||||
pcre_fullinfo(this->p_code,
|
||||
this->p_code_extra,
|
||||
PCRE_INFO_NAMEENTRYSIZE,
|
||||
&this->p_name_len);
|
||||
pcre_fullinfo(this->p_code,
|
||||
this->p_code_extra,
|
||||
PCRE_INFO_NAMETABLE,
|
||||
&this->p_named_entries);
|
||||
};
|
||||
|
||||
pcre *p_code;
|
||||
auto_mem<pcre_extra> p_code_extra;
|
||||
int p_named_count;
|
||||
int p_name_len;
|
||||
pcre_named_capture *p_named_entries;
|
||||
};
|
||||
#endif
|
||||
|
@ -42,36 +42,60 @@ int main(int argc, char *argv[])
|
||||
int retval = EXIT_SUCCESS;
|
||||
|
||||
{
|
||||
pcrepp nomatch("nothing-to-match");
|
||||
pcre_input pi("dummy");
|
||||
|
||||
assert(!nomatch.match(context, pi));
|
||||
pcrepp nomatch("nothing-to-match");
|
||||
pcre_input pi("dummy");
|
||||
|
||||
assert(!nomatch.match(context, pi));
|
||||
}
|
||||
|
||||
{
|
||||
pcrepp match1("(\\w*)=(\\d+)");
|
||||
pcre_input pi("a=1 b=2");
|
||||
pcre_context::capture_t *cap;
|
||||
|
||||
assert(match1.match(context, pi));
|
||||
|
||||
cap = context.all();
|
||||
assert(cap->c_begin == 0);
|
||||
assert(cap->c_end == 3);
|
||||
pcrepp match1("(\\w*)=(\\d+)");
|
||||
pcre_input pi("a=1 b=2");
|
||||
pcre_context::capture_t *cap;
|
||||
|
||||
assert((context.end() - context.begin()) == 2);
|
||||
assert(pi.get_substr(context.begin()) == "a");
|
||||
assert(pi.get_substr(context.begin() + 1) == "1");
|
||||
assert(match1.match(context, pi));
|
||||
|
||||
assert(match1.match(context, pi));
|
||||
assert((context.end() - context.begin()) == 2);
|
||||
assert(pi.get_substr(context.begin()) == "b");
|
||||
assert(pi.get_substr(context.begin() + 1) == "2");
|
||||
cap = context.all();
|
||||
assert(cap->c_begin == 0);
|
||||
assert(cap->c_end == 3);
|
||||
|
||||
assert((context.end() - context.begin()) == 2);
|
||||
assert(pi.get_substr(context.begin()) == "a");
|
||||
assert(pi.get_substr(context.begin() + 1) == "1");
|
||||
assert(pi.get_substr(context[1]) == "1");
|
||||
|
||||
assert(match1.match(context, pi));
|
||||
assert((context.end() - context.begin()) == 2);
|
||||
assert(pi.get_substr(context.begin()) == "b");
|
||||
assert(pi.get_substr(context.begin() + 1) == "2");
|
||||
}
|
||||
|
||||
{
|
||||
pcrepp match2("");
|
||||
pcrepp match2("");
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
pcrepp match3("(?<var1>\\d+)(?<var2>\\w+)");
|
||||
pcre_named_capture::iterator iter;
|
||||
const char *expected_names[] = {
|
||||
"var1",
|
||||
"var2",
|
||||
};
|
||||
int index = 0;
|
||||
|
||||
for (iter = match3.named_begin();
|
||||
iter != match3.named_end();
|
||||
++iter, index++) {
|
||||
assert(strcmp(iter->pnc_name, expected_names[index]) == 0);
|
||||
}
|
||||
|
||||
assert(match3.name_index("var2") == 1);
|
||||
|
||||
pcre_input pi("123foo");
|
||||
|
||||
match3.match(context, pi);
|
||||
assert(pi.get_substr(context["var1"]) == "123");
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user