/* 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);
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)
{
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;
+}
-
/*
regexpr.h
* 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
*
*
* 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 {
*
* 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
*/
* 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
*
* 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;
* 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
*
***/
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 */