[pcrepp] add support for named captures and fix some other bugs

This commit is contained in:
Timothy Stack 2013-06-24 18:08:43 -07:00
parent 63c6855a99
commit 6d77a7412e
7 changed files with 177 additions and 24 deletions

View File

@ -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)

View File

@ -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();

View File

@ -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();

View File

@ -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,

View File

@ -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)
{

View File

@ -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

View File

@ -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;
}