From c8fd78a59002c54dbc331a26839d042055e89d65 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Tue, 1 Jan 2008 16:09:31 +0000 Subject: [PATCH] Added silc_regex and silc_regex_buffer. Deprecated silc_string_regex_match.. --- lib/silcutil/silcregex.c | 113 +++++++++++++++++++++++++++++++++++-- lib/silcutil/silcregex.h | 90 +++++++++++++++++++++++++---- lib/silcutil/silcstrutil.c | 17 ------ lib/silcutil/silcstrutil.h | 13 ----- 4 files changed, 189 insertions(+), 44 deletions(-) diff --git a/lib/silcutil/silcregex.c b/lib/silcutil/silcregex.c index c11ea8ad..e422ded5 100644 --- a/lib/silcutil/silcregex.c +++ b/lib/silcutil/silcregex.c @@ -1601,11 +1601,11 @@ SilcBool silc_regex_compile(SilcRegex regexp, const char *regex, /* Match compiled regular expression */ SilcBool silc_regex_match(SilcRegex regexp, const char *string, - SilcUInt32 num_match, SilcRegexMatch match, - SilcRegexFlags flags) + SilcUInt32 string_len, SilcUInt32 num_match, + SilcRegexMatch match, SilcRegexFlags flags) { struct re_registers regs; - int ret, i, len = strlen(string); + int ret, i; if (!regexp || !string) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); @@ -1622,7 +1622,7 @@ SilcBool silc_regex_match(SilcRegex regexp, const char *string, num_match = RE_NREGS; /* Search */ - ret = re_search(regexp, (char *)string, len, 0, len, + ret = re_search(regexp, (char *)string, string_len, 0, string_len, num_match ? ®s : NULL); if (ret < 0) { if (ret == -2) @@ -1648,3 +1648,108 @@ void silc_regex_free(SilcRegex regexp) { silc_free(regexp->buffer); } + +/* Match string */ + +SilcBool silc_regex_va(const char *string, SilcUInt32 string_len, + const char *regex, SilcBuffer match, va_list va) +{ + SilcRegexStruct reg; + SilcRegexMatch m = NULL; + SilcBuffer buf, *rets = NULL; + int i, c = 0; + + /* Compile */ + if (!silc_regex_compile(®, regex, 0)) + return FALSE; + + /* Get match pointers */ + if (match) { + rets = silc_malloc(sizeof(*rets)); + if (!rets) + return FALSE; + rets[c++] = match; + + while ((buf = va_arg(va, SilcBuffer))) { + rets = silc_realloc(rets, (c + 1) * sizeof(*rets)); + if (!rets) + return FALSE; + rets[c++] = buf; + } + + m = silc_malloc(c * sizeof(*m)); + if (!m) { + silc_free(rets); + return FALSE; + } + } + + /* Match */ + if (!silc_regex_match(®, string, string_len, c, m, 0)) { + silc_free(m); + silc_free(rets); + return FALSE; + } + + /* Return matches */ + for (i = 0; i < c; i++) { + if (m[i].start == -1) + continue; + silc_buffer_set(rets[i], (unsigned char *)string + m[i].start, + m[i].end - m[i].start); + } + + silc_free(m); + silc_free(rets); + + return TRUE; +} + +/* Match string */ + +SilcBool silc_regex(const char *string, const char *regex, + SilcBuffer match, ...) +{ + SilcBool ret; + va_list va; + + if (!string || !regex) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + + if (match) + va_start(va, match); + + ret = silc_regex_va(string, strlen(string), regex, match, va); + + if (match) + va_end(va); + + return ret; +} + +/* Match string */ + +SilcBool silc_regex_buffer(SilcBuffer buffer, const char *regex, + SilcBuffer match, ...) +{ + SilcBool ret; + va_list va; + + if (!buffer || !regex) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + + if (match) + va_start(va, match); + + ret = silc_regex_va((const char *)silc_buffer_data(buffer), + silc_buffer_len(buffer), regex, match, va); + + if (match) + va_end(va); + + return ret; +} diff --git a/lib/silcutil/silcregex.h b/lib/silcutil/silcregex.h index 217144ab..1527a2c5 100644 --- a/lib/silcutil/silcregex.h +++ b/lib/silcutil/silcregex.h @@ -1,4 +1,3 @@ - /* regexpr.h @@ -29,7 +28,11 @@ * DESCRIPTION * * SILC regular expression interface provides Unix and POSIX compliant - * regular expression compilation and matching. + * regular expression compilation and matching. The syntax is compliant + * with Unix and POSIX regular expression syntax. + * + * The interface also provides many convenience functions to make the use + * of regular expressions easier. * * EXAMPLE * @@ -59,7 +62,9 @@ * * DESCRIPTION * - * The regular expression context. + * The regular expression context. This context is given as argument + * to all silc_regex_* functions. It is usually statically allocated + * but can be dynamically allocated by silc_malloc. * ***/ typedef struct SilcRegexObject { @@ -82,6 +87,9 @@ typedef struct SilcRegexObject { * * DESCRIPTION * + * The regular expression match context that provides information on the + * found match. It provides the start offset and end offset of the + * found match. * * SOURCE */ @@ -134,8 +142,8 @@ SilcBool silc_regex_compile(SilcRegex regexp, const char *regex, * SYNOPSIS * * SilcBool silc_regex_match(SilcRegex regexp, const char *string, - * SilcUInt32 num_match, SilcRegexMatch match, - * SilcRegexFlags flags); + * SilcUInt32 string_len, SilcUInt32 num_match, + * SilcRegexMatch match, SilcRegexFlags flags); * * DESCRIPTION * @@ -160,13 +168,13 @@ SilcBool silc_regex_compile(SilcRegex regexp, const char *regex, * EXAMPLE * * // Find first match (check if string matches) - * if (!silc_regex_match(®, "foo20", 0, NULL, 0)) + * if (!silc_regex_match(®, "foo20", 5, 0, NULL, 0)) * no_match; * * // Find multiple matches, one by one * SilcRegexMatchStruct match; * - * while (silc_regex_match(®, string, 1, &match, 0)) { + * while (silc_regex_match(®, string, len, 1, &match, 0)) { * match_string = silc_memdup(string + match.start, * match.end - match.start); * string += match.end; @@ -177,12 +185,12 @@ SilcBool silc_regex_compile(SilcRegex regexp, const char *regex, * SilcRegexMatchStruct match[7]; * * silc_regex_compile(®, "^(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)", 0); - * silc_regex_match(®, "http://example.com/page.html", 7, match, 0); + * silc_regex_match(®, "http://example.com/page.html", len, 7, match, 0); * ***/ SilcBool silc_regex_match(SilcRegex regexp, const char *string, - SilcUInt32 num_match, SilcRegexMatch match, - SilcRegexFlags flags); + SilcUInt32 string_len, SilcUInt32 num_match, + SilcRegexMatch match, SilcRegexFlags flags); /****f* silcutil/SilcRegexAPI/silc_regex_free * @@ -199,4 +207,66 @@ SilcBool silc_regex_match(SilcRegex regexp, const char *string, ***/ void silc_regex_free(SilcRegex regexp); +/****f* silcutil/SilcRegexAPI/silc_regex + * + * SYNOPSIS + * + * SilcBool silc_regex(const char *string, const char *regex, + * SilcBuffer match, ...); + * + * DESCRIPTION + * + * Matches the `string' to the regular expression `regex'. Returns TRUE + * if the `string' matches the regular expression or FALSE if it does not + * match. The silc_errno is also set to SILC_ERR_NOT_FOUND. + * + * The first (whole) match is returned to `match' buffer if it is non-NULL. + * The variable argument list are buffers where multiple matches are + * returned in case of group (parenthesized) regular expression. The caller + * needs to know how many pointers to provide, in order to get all matches. + * If `match' is non-NULL the variable argument list must be ended with + * NULL. The data in the `match' and in any other buffer is from `string' + * and must not be freed by the caller. + * + * EXAMPLE + * + * // Simple match + * if (!silc_regex("foobar", "foo.", NULL)) + * no_match; + * + * // Get the pointer to the first match + * if (!silc_regex("foobar", ".bar", &match, NULL)) + * no_match; + * + * // Group match + * SilcBufferStruct match, sub1, sub2; + * + * if (!silc_regex("Hello World", "(H..).(o..)", &match, &sub1, &sub2, NULL)) + * no_match; + * + ***/ +SilcBool silc_regex(const char *string, const char *regex, + SilcBuffer match, ...); + +/****f* silcutil/SilcRegexAPI/silc_regex_buffer + * + * SYNOPSIS + * + * SilcBool silc_regex_buffer(SilcBuffer buffer, const char *regex, + * SilcBuffer match, ...); + * + * DESCRIPTION + * + * Same as silc_regex but the string to match is in `buffer'. Returns + * TRUE if the string matches and FALSE if it doesn't. See examples and + * other information in silc_regex. The `buffer' and `match' may be the + * same buffer. + * + ***/ +SilcBool silc_regex_buffer(SilcBuffer buffer, const char *regex, + SilcBuffer match, ...); + +/* Backwards support */ +#define silc_string_regex_match(regex, string) silc_regex(string, regex, NULL) + #endif /* SILCREGEX_H */ diff --git a/lib/silcutil/silcstrutil.c b/lib/silcutil/silcstrutil.c index 914adc98..3251c2b0 100644 --- a/lib/silcutil/silcstrutil.c +++ b/lib/silcutil/silcstrutil.c @@ -249,23 +249,6 @@ char *silc_string_regex_combine(const char *string1, const char *string2) return tmp; } -/* Matches the two strings and returns TRUE if the strings match. */ - -int silc_string_regex_match(const char *regex, const char *string) -{ - SilcRegexStruct preg; - SilcBool ret; - - if (!silc_regex_compile(&preg, regex, 0)) - return FALSE; - - ret = silc_regex_match(&preg, string, 0, NULL, 0); - - silc_regex_free(&preg); - - return ret; -} - /* Do regex match to the two strings `string1' and `string2'. If the `string2' matches the `string1' this returns TRUE. */ diff --git a/lib/silcutil/silcstrutil.h b/lib/silcutil/silcstrutil.h index 1236e4fa..bc692975 100644 --- a/lib/silcutil/silcstrutil.h +++ b/lib/silcutil/silcstrutil.h @@ -99,19 +99,6 @@ char *silc_strncat(char *dest, SilcUInt32 dest_size, ***/ char *silc_string_regexify(const char *string); -/****f* silcutil/SilcStrUtilAPI/silc_string_regex_match - * - * SYNOPSIS - * - * int silc_string_regex_match(const char *regex, const char *string); - * - * DESCRIPTION - * - * Matches the two strings and returns TRUE if the strings match. - * - ***/ -int silc_string_regex_match(const char *regex, const char *string); - /****f* silcutil/SilcStrUtilAPI/silc_string_match * * SYNOPSIS -- 2.24.0