From: "Jun'ichi Nomura" <j-nomura@ce.jp.nec.com>
To: device-mapper development <dm-devel@redhat.com>,
Alasdair Kergon <agk@redhat.com>
Subject: [PATCH] libdevmapper: (3/6) Move lib/regex from LVM2
Date: Wed, 18 Apr 2007 12:47:34 -0400 [thread overview]
Message-ID: <46264BA6.3050104@ce.jp.nec.com> (raw)
In-Reply-To: <46264A57.1020800@ce.jp.nec.com>
[-- Attachment #1: Type: text/plain, Size: 306 bytes --]
Hi,
This patch just moves lib/regex from LVM2 as a preparation for
the filtering feature of dm_report.
Now, the following functions are exported:
- dm_regex_create()
- dm_regex_match()
Corresponding patch to LVM2 will be posted to lvm-devel.
Thanks,
--
Jun'ichi Nomura, NEC Corporation of America
[-- Attachment #2: libdm-regex.patch --]
[-- Type: text/x-patch, Size: 22489 bytes --]
Moved lib/regex from LVM2
Exported functions and a structure are renamed:
- matcher_create() -> dm_regex_create()
- matcher_run() -> dm_regex_match()
- struct matcher -> struct dm_regex
---
lib/.exported_symbols | 2
lib/Makefile.in | 3
lib/libdevmapper.h | 7
lib/regex/matcher.c | 366 ++++++++++++++++++++++++++++++++++++++++++++++++++
lib/regex/parse_rx.c | 360 +++++++++++++++++++++++++++++++++++++++++++++++++
lib/regex/parse_rx.h | 52 +++++++
lib/regex/ttree.c | 117 +++++++++++++++
lib/regex/ttree.h | 26 +++
8 files changed, 933 insertions(+)
Index: device-mapper.work/lib/.exported_symbols
===================================================================
--- device-mapper.work.orig/lib/.exported_symbols
+++ device-mapper.work/lib/.exported_symbols
@@ -127,3 +127,5 @@ dm_report_field_int32
dm_report_field_uint32
dm_report_field_uint64
dm_report_field_set_value
+dm_regex_create
+dm_regex_match
Index: device-mapper.work/lib/libdevmapper.h
===================================================================
--- device-mapper.work.orig/lib/libdevmapper.h
+++ device-mapper.work/lib/libdevmapper.h
@@ -711,4 +711,11 @@ int dm_report_field_uint64(struct dm_rep
void dm_report_field_set_value(struct dm_report_field *field, const void *value,
const void *sortvalue);
+/*
+ * dm_regex
+ */
+struct dm_regex;
+struct dm_regex *dm_regex_create(struct dm_pool *mem, const char **patterns,
+ unsigned num);
+int dm_regex_match(struct dm_regex *regex, const char *s);
#endif /* LIB_DEVICE_MAPPER_H */
Index: device-mapper.work/lib/regex/matcher.c
===================================================================
--- /dev/null
+++ device-mapper.work/lib/regex/matcher.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "lib.h"
+#include "parse_rx.h"
+#include "ttree.h"
+
+#define assert(x) do { if (!(x)) log_error("assertion failed"); } while(0)
+
+struct dfa_state {
+ int final;
+ struct dfa_state *lookup[256];
+};
+
+struct state_queue {
+ struct dfa_state *s;
+ dm_bitset_t bits;
+ struct state_queue *next;
+};
+
+struct dm_regex { /* Instance variables for the lexer */
+ struct dfa_state *start;
+ unsigned num_nodes;
+ int nodes_entered;
+ struct rx_node **nodes;
+ struct dm_pool *scratch, *mem;
+};
+
+#define TARGET_TRANS '\0'
+
+static int _count_nodes(struct rx_node *rx)
+{
+ int r = 1;
+
+ if (rx->left)
+ r += _count_nodes(rx->left);
+
+ if (rx->right)
+ r += _count_nodes(rx->right);
+
+ return r;
+}
+
+static void _fill_table(struct dm_regex *m, struct rx_node *rx)
+{
+ assert((rx->type != OR) || (rx->left && rx->right));
+
+ if (rx->left)
+ _fill_table(m, rx->left);
+
+ if (rx->right)
+ _fill_table(m, rx->right);
+
+ m->nodes[m->nodes_entered++] = rx;
+}
+
+static void _create_bitsets(struct dm_regex *m)
+{
+ int i;
+
+ for (i = 0; i < m->num_nodes; i++) {
+ struct rx_node *n = m->nodes[i];
+ n->firstpos = dm_bitset_create(m->scratch, m->num_nodes);
+ n->lastpos = dm_bitset_create(m->scratch, m->num_nodes);
+ n->followpos = dm_bitset_create(m->scratch, m->num_nodes);
+ }
+}
+
+static void _calc_functions(struct dm_regex *m)
+{
+ int i, j, final = 1;
+ struct rx_node *rx, *c1, *c2;
+
+ for (i = 0; i < m->num_nodes; i++) {
+ rx = m->nodes[i];
+ c1 = rx->left;
+ c2 = rx->right;
+
+ if (dm_bit(rx->charset, TARGET_TRANS))
+ rx->final = final++;
+
+ switch (rx->type) {
+ case CAT:
+ if (c1->nullable)
+ dm_bit_union(rx->firstpos,
+ c1->firstpos, c2->firstpos);
+ else
+ dm_bit_copy(rx->firstpos, c1->firstpos);
+
+ if (c2->nullable)
+ dm_bit_union(rx->lastpos,
+ c1->lastpos, c2->lastpos);
+ else
+ dm_bit_copy(rx->lastpos, c2->lastpos);
+
+ rx->nullable = c1->nullable && c2->nullable;
+ break;
+
+ case PLUS:
+ dm_bit_copy(rx->firstpos, c1->firstpos);
+ dm_bit_copy(rx->lastpos, c1->lastpos);
+ rx->nullable = c1->nullable;
+ break;
+
+ case OR:
+ dm_bit_union(rx->firstpos, c1->firstpos, c2->firstpos);
+ dm_bit_union(rx->lastpos, c1->lastpos, c2->lastpos);
+ rx->nullable = c1->nullable || c2->nullable;
+ break;
+
+ case QUEST:
+ case STAR:
+ dm_bit_copy(rx->firstpos, c1->firstpos);
+ dm_bit_copy(rx->lastpos, c1->lastpos);
+ rx->nullable = 1;
+ break;
+
+ case CHARSET:
+ dm_bit_set(rx->firstpos, i);
+ dm_bit_set(rx->lastpos, i);
+ rx->nullable = 0;
+ break;
+
+ default:
+ log_error("Internal error: Unknown calc node type");
+ }
+
+ /*
+ * followpos has it's own switch
+ * because PLUS and STAR do the
+ * same thing.
+ */
+ switch (rx->type) {
+ case CAT:
+ for (j = 0; j < m->num_nodes; j++) {
+ if (dm_bit(c1->lastpos, j)) {
+ struct rx_node *n = m->nodes[j];
+ dm_bit_union(n->followpos,
+ n->followpos, c2->firstpos);
+ }
+ }
+ break;
+
+ case PLUS:
+ case STAR:
+ for (j = 0; j < m->num_nodes; j++) {
+ if (dm_bit(rx->lastpos, j)) {
+ struct rx_node *n = m->nodes[j];
+ dm_bit_union(n->followpos,
+ n->followpos, rx->firstpos);
+ }
+ }
+ break;
+ }
+ }
+}
+
+static struct dfa_state *_create_dfa_state(struct dm_pool *mem)
+{
+ return dm_pool_zalloc(mem, sizeof(struct dfa_state));
+}
+
+static struct state_queue *_create_state_queue(struct dm_pool *mem,
+ struct dfa_state *dfa,
+ dm_bitset_t bits)
+{
+ struct state_queue *r = dm_pool_alloc(mem, sizeof(*r));
+
+ if (!r) {
+ stack;
+ return NULL;
+ }
+
+ r->s = dfa;
+ r->bits = dm_bitset_create(mem, bits[0]); /* first element is the size */
+ dm_bit_copy(r->bits, bits);
+ r->next = 0;
+ return r;
+}
+
+static int _calc_states(struct dm_regex *m, struct rx_node *rx)
+{
+ unsigned iwidth = (m->num_nodes / DM_BITS_PER_INT) + 1;
+ struct ttree *tt = ttree_create(m->scratch, iwidth);
+ struct state_queue *h, *t, *tmp;
+ struct dfa_state *dfa, *ldfa;
+ int i, a, set_bits = 0, count = 0;
+ dm_bitset_t bs, dfa_bits;
+
+ if (!tt)
+ return_0;
+
+ if (!(bs = dm_bitset_create(m->scratch, m->num_nodes)))
+ return_0;
+
+ /* create first state */
+ dfa = _create_dfa_state(m->mem);
+ m->start = dfa;
+ ttree_insert(tt, rx->firstpos + 1, dfa);
+
+ /* prime the queue */
+ h = t = _create_state_queue(m->scratch, dfa, rx->firstpos);
+ while (h) {
+ /* pop state off front of the queue */
+ dfa = h->s;
+ dfa_bits = h->bits;
+ h = h->next;
+
+ /* iterate through all the inputs for this state */
+ dm_bit_clear_all(bs);
+ for (a = 0; a < 256; a++) {
+ /* iterate through all the states in firstpos */
+ for (i = dm_bit_get_first(dfa_bits);
+ i >= 0; i = dm_bit_get_next(dfa_bits, i)) {
+ if (dm_bit(m->nodes[i]->charset, a)) {
+ if (a == TARGET_TRANS)
+ dfa->final = m->nodes[i]->final;
+
+ dm_bit_union(bs, bs,
+ m->nodes[i]->followpos);
+ set_bits = 1;
+ }
+ }
+
+ if (set_bits) {
+ ldfa = ttree_lookup(tt, bs + 1);
+ if (!ldfa) {
+ /* push */
+ ldfa = _create_dfa_state(m->mem);
+ ttree_insert(tt, bs + 1, ldfa);
+ tmp =
+ _create_state_queue(m->scratch,
+ ldfa, bs);
+ if (!h)
+ h = t = tmp;
+ else {
+ t->next = tmp;
+ t = tmp;
+ }
+
+ count++;
+ }
+
+ dfa->lookup[a] = ldfa;
+ set_bits = 0;
+ dm_bit_clear_all(bs);
+ }
+ }
+ }
+
+ log_debug("Matcher built with %d dfa states", count);
+ return 1;
+}
+
+struct dm_regex *dm_regex_create(struct dm_pool *mem, const char **patterns,
+ unsigned num)
+{
+ char *all, *ptr;
+ int i;
+ size_t len = 0;
+ struct rx_node *rx;
+ struct dm_pool *scratch = dm_pool_create("regex matcher", 10 * 1024);
+ struct dm_regex *m;
+
+ if (!scratch) {
+ stack;
+ return NULL;
+ }
+
+ if (!(m = dm_pool_alloc(mem, sizeof(*m)))) {
+ stack;
+ dm_pool_destroy(scratch);
+ return NULL;
+ }
+
+ memset(m, 0, sizeof(*m));
+
+ /* join the regexps together, delimiting with zero */
+ for (i = 0; i < num; i++)
+ len += strlen(patterns[i]) + 8;
+
+ ptr = all = dm_pool_alloc(scratch, len + 1);
+
+ if (!all) {
+ stack;
+ goto bad;
+ }
+
+ for (i = 0; i < num; i++) {
+ ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i], TARGET_TRANS);
+ if (i < (num - 1))
+ *ptr++ = '|';
+ }
+
+ /* parse this expression */
+ if (!(rx = rx_parse_tok(scratch, all, ptr))) {
+ log_error("Couldn't parse regex");
+ goto bad;
+ }
+
+ m->mem = mem;
+ m->scratch = scratch;
+ m->num_nodes = _count_nodes(rx);
+ m->nodes = dm_pool_alloc(scratch, sizeof(*m->nodes) * m->num_nodes);
+
+ if (!m->nodes) {
+ stack;
+ goto bad;
+ }
+
+ _fill_table(m, rx);
+ _create_bitsets(m);
+ _calc_functions(m);
+ _calc_states(m, rx);
+ dm_pool_destroy(scratch);
+ m->scratch = NULL;
+
+ return m;
+
+ bad:
+ dm_pool_destroy(scratch);
+ dm_pool_destroy(mem);
+ return NULL;
+}
+
+static struct dfa_state *_step_matcher(int c, struct dfa_state *cs, int *r)
+{
+ if (!(cs = cs->lookup[(unsigned char) c]))
+ return NULL;
+
+ if (cs->final && (cs->final > *r))
+ *r = cs->final;
+
+ return cs;
+}
+
+int dm_regex_match(struct dm_regex *m, const char *b)
+{
+ struct dfa_state *cs = m->start;
+ int r = 0;
+
+ if (!(cs = _step_matcher(HAT_CHAR, cs, &r)))
+ goto out;
+
+ for (; *b; b++)
+ if (!(cs = _step_matcher(*b, cs, &r)))
+ goto out;
+
+ _step_matcher(DOLLAR_CHAR, cs, &r);
+
+ out:
+ /* subtract 1 to get back to zero index */
+ return r - 1;
+}
Index: device-mapper.work/lib/regex/parse_rx.c
===================================================================
--- /dev/null
+++ device-mapper.work/lib/regex/parse_rx.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "lib.h"
+#include "parse_rx.h"
+
+struct parse_sp { /* scratch pad for the parsing process */
+ struct dm_pool *mem;
+ int type; /* token type, 0 indicates a charset */
+ dm_bitset_t charset; /* The current charset */
+ const char *cursor; /* where we are in the regex */
+ const char *rx_end; /* 1pte for the expression being parsed */
+};
+
+static struct rx_node *_or_term(struct parse_sp *ps);
+
+static void _single_char(struct parse_sp *ps, unsigned int c, const char *ptr)
+{
+ ps->type = 0;
+ ps->cursor = ptr + 1;
+ dm_bit_clear_all(ps->charset);
+ dm_bit_set(ps->charset, c);
+}
+
+/*
+ * Get the next token from the regular expression.
+ * Returns: 1 success, 0 end of input, -1 error.
+ */
+static int _rx_get_token(struct parse_sp *ps)
+{
+ int neg = 0, range = 0;
+ char c, lc = 0;
+ const char *ptr = ps->cursor;
+ if (ptr == ps->rx_end) { /* end of input ? */
+ ps->type = -1;
+ return 0;
+ }
+
+ switch (*ptr) {
+ /* charsets and ncharsets */
+ case '[':
+ ptr++;
+ if (*ptr == '^') {
+ dm_bit_set_all(ps->charset);
+
+ /* never transition on zero */
+ dm_bit_clear(ps->charset, 0);
+ neg = 1;
+ ptr++;
+
+ } else
+ dm_bit_clear_all(ps->charset);
+
+ while ((ptr < ps->rx_end) && (*ptr != ']')) {
+ if (*ptr == '\\') {
+ /* an escaped character */
+ ptr++;
+ switch (*ptr) {
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ default:
+ c = *ptr;
+ }
+ } else if (*ptr == '-' && lc) {
+ /* we've got a range on our hands */
+ range = 1;
+ ptr++;
+ if (ptr == ps->rx_end) {
+ log_error("Incomplete range"
+ "specification");
+ return -1;
+ }
+ c = *ptr;
+ } else
+ c = *ptr;
+
+ if (range) {
+ /* add lc - c into the bitset */
+ if (lc > c) {
+ char tmp = c;
+ c = lc;
+ lc = tmp;
+ }
+
+ for (; lc <= c; lc++) {
+ if (neg)
+ dm_bit_clear(ps->charset, lc);
+ else
+ dm_bit_set(ps->charset, lc);
+ }
+ range = 0;
+ } else {
+ /* add c into the bitset */
+ if (neg)
+ dm_bit_clear(ps->charset, c);
+ else
+ dm_bit_set(ps->charset, c);
+ }
+ ptr++;
+ lc = c;
+ }
+
+ if (ptr >= ps->rx_end) {
+ ps->type = -1;
+ return -1;
+ }
+
+ ps->type = 0;
+ ps->cursor = ptr + 1;
+ break;
+
+ /* These characters are special, we just return their ASCII
+ codes as the type. Sorted into ascending order to help the
+ compiler */
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case '?':
+ case '|':
+ ps->type = (int) *ptr;
+ ps->cursor = ptr + 1;
+ break;
+
+ case '^':
+ _single_char(ps, HAT_CHAR, ptr);
+ break;
+
+ case '$':
+ _single_char(ps, DOLLAR_CHAR, ptr);
+ break;
+
+ case '.':
+ /* The 'all but newline' character set */
+ ps->type = 0;
+ ps->cursor = ptr + 1;
+ dm_bit_set_all(ps->charset);
+ dm_bit_clear(ps->charset, (int) '\n');
+ dm_bit_clear(ps->charset, (int) '\r');
+ dm_bit_clear(ps->charset, 0);
+ break;
+
+ case '\\':
+ /* escaped character */
+ ptr++;
+ if (ptr >= ps->rx_end) {
+ log_error("Badly quoted character at end "
+ "of expression");
+ ps->type = -1;
+ return -1;
+ }
+
+ ps->type = 0;
+ ps->cursor = ptr + 1;
+ dm_bit_clear_all(ps->charset);
+ switch (*ptr) {
+ case 'n':
+ dm_bit_set(ps->charset, (int) '\n');
+ break;
+ case 'r':
+ dm_bit_set(ps->charset, (int) '\r');
+ break;
+ case 't':
+ dm_bit_set(ps->charset, (int) '\t');
+ break;
+ default:
+ dm_bit_set(ps->charset, (int) *ptr);
+ }
+ break;
+
+ default:
+ /* add a single character to the bitset */
+ ps->type = 0;
+ ps->cursor = ptr + 1;
+ dm_bit_clear_all(ps->charset);
+ dm_bit_set(ps->charset, (int) *ptr);
+ break;
+ }
+
+ return 1;
+}
+
+static struct rx_node *_node(struct dm_pool *mem, int type,
+ struct rx_node *l, struct rx_node *r)
+{
+ struct rx_node *n = dm_pool_zalloc(mem, sizeof(*n));
+
+ if (n) {
+ if (!(n->charset = dm_bitset_create(mem, 256))) {
+ dm_pool_free(mem, n);
+ return NULL;
+ }
+
+ n->type = type;
+ n->left = l;
+ n->right = r;
+ }
+
+ return n;
+}
+
+static struct rx_node *_term(struct parse_sp *ps)
+{
+ struct rx_node *n;
+
+ switch (ps->type) {
+ case 0:
+ if (!(n = _node(ps->mem, CHARSET, NULL, NULL))) {
+ stack;
+ return NULL;
+ }
+
+ dm_bit_copy(n->charset, ps->charset);
+ _rx_get_token(ps); /* match charset */
+ break;
+
+ case '(':
+ _rx_get_token(ps); /* match '(' */
+ n = _or_term(ps);
+ if (ps->type != ')') {
+ log_error("missing ')' in regular expression");
+ return 0;
+ }
+ _rx_get_token(ps); /* match ')' */
+ break;
+
+ default:
+ n = 0;
+ }
+
+ return n;
+}
+
+static struct rx_node *_closure_term(struct parse_sp *ps)
+{
+ struct rx_node *l, *n;
+
+ if (!(l = _term(ps)))
+ return NULL;
+
+ for (;;) {
+ switch (ps->type) {
+ case '*':
+ n = _node(ps->mem, STAR, l, NULL);
+ break;
+
+ case '+':
+ n = _node(ps->mem, PLUS, l, NULL);
+ break;
+
+ case '?':
+ n = _node(ps->mem, QUEST, l, NULL);
+ break;
+
+ default:
+ return l;
+ }
+
+ if (!n) {
+ stack;
+ return NULL;
+ }
+
+ _rx_get_token(ps);
+ l = n;
+ }
+
+ return n;
+}
+
+static struct rx_node *_cat_term(struct parse_sp *ps)
+{
+ struct rx_node *l, *r, *n;
+
+ if (!(l = _closure_term(ps)))
+ return NULL;
+
+ if (ps->type == '|')
+ return l;
+
+ if (!(r = _cat_term(ps)))
+ return l;
+
+ if (!(n = _node(ps->mem, CAT, l, r)))
+ stack;
+
+ return n;
+}
+
+static struct rx_node *_or_term(struct parse_sp *ps)
+{
+ struct rx_node *l, *r, *n;
+
+ if (!(l = _cat_term(ps)))
+ return NULL;
+
+ if (ps->type != '|')
+ return l;
+
+ _rx_get_token(ps); /* match '|' */
+
+ if (!(r = _or_term(ps))) {
+ log_error("Badly formed 'or' expression");
+ return NULL;
+ }
+
+ if (!(n = _node(ps->mem, OR, l, r)))
+ stack;
+
+ return n;
+}
+
+struct rx_node *rx_parse_tok(struct dm_pool *mem,
+ const char *begin, const char *end)
+{
+ struct rx_node *r;
+ struct parse_sp *ps = dm_pool_zalloc(mem, sizeof(*ps));
+
+ if (!ps) {
+ stack;
+ return NULL;
+ }
+
+ ps->mem = mem;
+ ps->charset = dm_bitset_create(mem, 256);
+ ps->cursor = begin;
+ ps->rx_end = end;
+ _rx_get_token(ps); /* load the first token */
+
+ if (!(r = _or_term(ps))) {
+ log_error("Parse error in regex");
+ dm_pool_free(mem, ps);
+ }
+
+ return r;
+}
+
+struct rx_node *rx_parse_str(struct dm_pool *mem, const char *str)
+{
+ return rx_parse_tok(mem, str, str + strlen(str));
+}
Index: device-mapper.work/lib/regex/parse_rx.h
===================================================================
--- /dev/null
+++ device-mapper.work/lib/regex/parse_rx.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LVM_PARSE_REGEX_H
+#define _LVM_PARSE_REGEX_H
+
+enum {
+ CAT,
+ STAR,
+ PLUS,
+ OR,
+ QUEST,
+ CHARSET
+};
+
+/*
+ * We're never going to be running the regex on non-printable
+ * chars, so we can use a couple of these chars to represent the
+ * start and end of a string.
+ */
+#define HAT_CHAR 0x2
+#define DOLLAR_CHAR 0x3
+
+struct rx_node {
+ int type;
+ dm_bitset_t charset;
+ struct rx_node *left, *right;
+
+ /* used to build the dfa for the toker */
+ int nullable, final;
+ dm_bitset_t firstpos;
+ dm_bitset_t lastpos;
+ dm_bitset_t followpos;
+};
+
+struct rx_node *rx_parse_str(struct dm_pool *mem, const char *str);
+struct rx_node *rx_parse_tok(struct dm_pool *mem,
+ const char *begin, const char *end);
+
+#endif
Index: device-mapper.work/lib/regex/ttree.c
===================================================================
--- /dev/null
+++ device-mapper.work/lib/regex/ttree.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "lib.h"
+#include "ttree.h"
+
+struct node {
+ unsigned k;
+ struct node *l, *m, *r;
+ void *data;
+};
+
+struct ttree {
+ int klen;
+ struct dm_pool *mem;
+ struct node *root;
+};
+
+static struct node **_lookup_single(struct node **c, unsigned int k)
+{
+ while (*c) {
+ if (k < (*c)->k)
+ c = &((*c)->l);
+
+ else if (k > (*c)->k)
+ c = &((*c)->r);
+
+ else {
+ c = &((*c)->m);
+ break;
+ }
+ }
+
+ return c;
+}
+
+void *ttree_lookup(struct ttree *tt, unsigned *key)
+{
+ struct node **c = &tt->root;
+ int count = tt->klen;
+
+ while (*c && count) {
+ c = _lookup_single(c, *key++);
+ count--;
+ }
+
+ return *c ? (*c)->data : NULL;
+}
+
+static struct node *_tree_node(struct dm_pool *mem, unsigned int k)
+{
+ struct node *n = dm_pool_zalloc(mem, sizeof(*n));
+
+ if (n)
+ n->k = k;
+
+ return n;
+}
+
+int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
+{
+ struct node **c = &tt->root;
+ int count = tt->klen;
+ unsigned int k;
+
+ do {
+ k = *key++;
+ c = _lookup_single(c, k);
+ count--;
+
+ } while (*c && count);
+
+ if (!*c) {
+ count++;
+
+ while (count--) {
+ if (!(*c = _tree_node(tt->mem, k))) {
+ stack;
+ return 0;
+ }
+
+ k = *key++;
+
+ if (count)
+ c = &((*c)->m);
+ }
+ }
+ (*c)->data = data;
+
+ return 1;
+}
+
+struct ttree *ttree_create(struct dm_pool *mem, unsigned int klen)
+{
+ struct ttree *tt;
+
+ if (!(tt = dm_pool_zalloc(mem, sizeof(*tt)))) {
+ stack;
+ return NULL;
+ }
+
+ tt->klen = klen;
+ tt->mem = mem;
+ return tt;
+}
Index: device-mapper.work/lib/regex/ttree.h
===================================================================
--- /dev/null
+++ device-mapper.work/lib/regex/ttree.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LVM_TTREE_H
+#define _LVM_TTREE_H
+
+struct ttree;
+
+struct ttree *ttree_create(struct dm_pool *mem, unsigned int klen);
+
+void *ttree_lookup(struct ttree *tt, unsigned *key);
+int ttree_insert(struct ttree *tt, unsigned *key, void *data);
+
+#endif
Index: device-mapper.work/lib/Makefile.in
===================================================================
--- device-mapper.work.orig/lib/Makefile.in
+++ device-mapper.work/lib/Makefile.in
@@ -25,6 +25,9 @@ SOURCES =\
libdm-deptree.c \
libdm-string.c \
libdm-report.c \
+ regex/matcher.c \
+ regex/parse_rx.c \
+ regex/ttree.c \
mm/dbg_malloc.c \
mm/pool.c \
$(interface)/libdm-iface.c
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
next prev parent reply other threads:[~2007-04-18 16:47 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-18 16:41 [PATCH] libdevmapper: (0/6) Filtering feature in dm_report Jun'ichi Nomura
2007-04-18 16:47 ` [PATCH] libdevmapper: (1/6) Tidy up _field_match() and _key_match() Jun'ichi Nomura
2007-04-18 16:47 ` [PATCH] libdevmapper: (2/6) Fix trailing separator Jun'ichi Nomura
2007-04-18 16:47 ` Jun'ichi Nomura [this message]
2007-04-18 19:23 ` [PATCH] LVM2: (1/2) Use dm_regex Jun'ichi Nomura
2007-04-18 16:47 ` [PATCH] libdevmapper: (4/6) Add filtering feature to dm_report Jun'ichi Nomura
2007-04-18 19:32 ` [PATCH] LVM2: (2/2) Use dm_report filter Jun'ichi Nomura
2007-04-18 16:47 ` [PATCH] libdevmapper: (5/6) Add '--filter' option to dmsetup Jun'ichi Nomura
2007-04-18 16:47 ` [PATCH] libdevmapper: (6/6) Add deps and treenode fields for dmsetup info -c Jun'ichi Nomura
2007-04-18 19:23 ` [PATCH] libdevmapper: (7/6) Add dm_report_get_report_types() Jun'ichi Nomura
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46264BA6.3050104@ce.jp.nec.com \
--to=j-nomura@ce.jp.nec.com \
--cc=agk@redhat.com \
--cc=dm-devel@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.