1/*
2 * librdkafka - The Apache Kafka C/C++ library
3 *
4 * Copyright (c) 2016 Magnus Edenhill
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29
30#include "rd.h"
31#include "rdregex.h"
32
33#if HAVE_REGEX
34#include <regex.h>
35struct rd_regex_s {
36 regex_t re;
37};
38
39#else
40
41#include "regexp.h"
42struct rd_regex_s {
43 Reprog *re;
44};
45#endif
46
47
48/**
49 * @brief Destroy compiled regex
50 */
51void rd_regex_destroy (rd_regex_t *re) {
52#if HAVE_REGEX
53 regfree(&re->re);
54#else
55 re_regfree(re->re);
56#endif
57 rd_free(re);
58}
59
60
61/**
62 * @brief Compile regex \p pattern
63 * @returns Compiled regex object on success on error.
64 */
65rd_regex_t *
66rd_regex_comp (const char *pattern, char *errstr, size_t errstr_size) {
67 rd_regex_t *re = rd_calloc(1, sizeof(*re));
68#if HAVE_REGEX
69 int r;
70
71 r = regcomp(&re->re, pattern, REG_EXTENDED|REG_NOSUB);
72 if (r) {
73 if (errstr)
74 regerror(r, &re->re, errstr, errstr_size);
75 rd_free(re);
76 return NULL;
77 }
78#else
79 const char *errstr2;
80
81 re->re = re_regcomp(pattern, 0, &errstr2);
82 if (!re->re) {
83 if (errstr) {
84 strncpy(errstr, errstr2, errstr_size-1);
85 errstr[errstr_size-1] = '\0';
86 }
87 rd_free(re);
88 return NULL;
89 }
90#endif
91
92 return re;
93}
94
95
96/**
97 * @brief Match \p str to pre-compiled regex \p re
98 * @returns 1 on match, else 0
99 */
100int rd_regex_exec (rd_regex_t *re, const char *str) {
101#if HAVE_REGEX
102 return regexec(&re->re, str, 0, NULL, 0) != REG_NOMATCH;
103#else
104 return !re_regexec(re->re, str, NULL, 0);
105#endif
106}
107
108
109/**
110 * @brief Perform regex match of \p str using regex \p pattern.
111 *
112 * @returns 1 on match, 0 on non-match or -1 on regex compilation error
113 * in which case a human readable error string is written to
114 * \p errstr (if not NULL).
115 */
116int rd_regex_match (const char *pattern, const char *str,
117 char *errstr, size_t errstr_size) {
118#if HAVE_REGEX /* use libc regex */
119 regex_t re;
120 int r;
121
122 /* FIXME: cache compiled regex */
123 r = regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB);
124 if (r) {
125 if (errstr)
126 regerror(r, &re, errstr, errstr_size);
127 return 0;
128 }
129
130 r = regexec(&re, str, 0, NULL, 0) != REG_NOMATCH;
131
132 regfree(&re);
133
134 return r;
135
136#else /* Using regexp.h from minilibs (included) */
137 Reprog *re;
138 int r;
139 const char *errstr2;
140
141 /* FIXME: cache compiled regex */
142 re = re_regcomp(pattern, 0, &errstr2);
143 if (!re) {
144 if (errstr) {
145 strncpy(errstr, errstr2, errstr_size-1);
146 errstr[errstr_size-1] = '\0';
147 }
148 return -1;
149 }
150
151 r = !re_regexec(re, str, NULL, 0);
152
153 re_regfree(re);
154
155 return r;
156#endif
157}
158