diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2022-02-21 15:25:27 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2022-02-21 16:12:07 -0500 |
commit | 9754c1ab7ceebd41ffda5f8004e562f18006dc6c (patch) | |
tree | be623cc6de520ed5578458e58a9d774c75b0f296 /regex.c | |
parent | 5a3b68d37cdc1e60802a5963340be5c5705d1f5d (diff) | |
download | bfs-9754c1ab7ceebd41ffda5f8004e562f18006dc6c.tar.xz |
regex: Wrap the POSIX API in a facade
Diffstat (limited to 'regex.c')
-rw-r--r-- | regex.c | 87 |
1 files changed, 80 insertions, 7 deletions
@@ -15,9 +15,29 @@ ****************************************************************************/ #include "regex.h" +#include <stdbool.h> #include <stdlib.h> +#include <string.h> + +#if BFS_WITH_ONIGURUMA +# include <onigposix.h> +#else +# include <regex.h> +#endif + +struct bfs_regex { + regex_t impl; +}; + +struct bfs_regex *bfs_regcomp(const char *expr, enum bfs_regex_type type, enum bfs_regcomp_flags flags, int *err) { + struct bfs_regex *regex = malloc(sizeof(*regex)); + if (!regex) { + *err = REG_ESPACE; + return NULL; + } + + int cflags = 0; -int bfs_regcomp(regex_t *preg, const char *regex, int cflags, enum bfs_regex_type type) { #if BFS_WITH_ONIGURUMA // Oniguruma's POSIX wrapper uses the selected default syntax when REG_EXTENDED is set cflags |= REG_EXTENDED; @@ -39,24 +59,77 @@ int bfs_regcomp(regex_t *preg, const char *regex, int cflags, enum bfs_regex_typ #else switch (type) { case BFS_REGEX_POSIX_BASIC: - cflags &= ~REG_EXTENDED; break; case BFS_REGEX_POSIX_EXTENDED: cflags |= REG_EXTENDED; break; default: - return REG_BADPAT; + *err = REG_BADPAT; + goto fail; + } +#endif + + if (flags & BFS_REGEX_ICASE) { + cflags |= REG_ICASE; + } + + *err = regcomp(®ex->impl, expr, cflags); + if (*err != 0) { + goto fail; + } + + return regex; + +fail: + free(regex); + return NULL; +} + +bool bfs_regexec(struct bfs_regex *regex, const char *str, enum bfs_regexec_flags flags, int *err) { + size_t len = strlen(str); + regmatch_t match = { + .rm_so = 0, + .rm_eo = len, + }; + + int eflags = 0; +#ifdef REG_STARTEND + if (flags & BFS_REGEX_ANCHOR) { + eflags |= REG_STARTEND; } #endif - return regcomp(preg, regex, cflags); + int ret = regexec(®ex->impl, str, 1, &match, eflags); + if (ret == 0) { + *err = 0; + if (flags & BFS_REGEX_ANCHOR) { + return match.rm_so == 0 && (size_t)match.rm_eo == len; + } else { + return true; + } + } else if (ret == REG_NOMATCH) { + *err = 0; + return false; + } else { + *err = ret; + return false; + } +} + +void bfs_regfree(struct bfs_regex *regex) { + if (regex) { + regfree(®ex->impl); + free(regex); + } } -char *bfs_regerror(int err, const regex_t *regex) { - size_t len = regerror(err, regex, NULL, 0); +char *bfs_regerror(int err, const struct bfs_regex *regex) { + const regex_t *impl = regex ? ®ex->impl : NULL; + + size_t len = regerror(err, impl, NULL, 0); char *str = malloc(len); if (str) { - regerror(err, regex, str, len); + regerror(err, impl, str, len); } return str; } |