summaryrefslogtreecommitdiffhomepage
path: root/lib.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-05-11 17:08:50 +0200
committerJo-Philipp Wich <jo@mein.io>2021-05-11 17:34:31 +0200
commit5c4e1ea8dca744482879dfc15ed21fc24beb2775 (patch)
tree34e0d206b6db6161b4f169f2e215e3c76129268a /lib.c
parentfbf3dfad950310a0a7c5ae29f25312733fa9063d (diff)
lib: implement regexp(), a function to construct regexp instances at runtime
Provide a new ucode function regexp() which allows constructing regular expression instances from separate source and flag strings. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/lib.c b/lib.c
index 453f976..a24ed23 100644
--- a/lib.c
+++ b/lib.c
@@ -2470,6 +2470,61 @@ uc_assert(uc_vm *vm, size_t nargs)
return ucv_get(cond);
}
+static uc_value_t *
+uc_regexp(uc_vm *vm, size_t nargs)
+{
+ bool icase = false, newline = false, global = false, freeable;
+ uc_value_t *source = uc_get_arg(0);
+ uc_value_t *flags = uc_get_arg(1);
+ uc_value_t *regex = NULL;
+ char *p, *err = NULL;
+
+ if (flags) {
+ if (ucv_type(flags) != UC_STRING) {
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Given flags argument is not a string");
+
+ return NULL;
+ }
+
+ for (p = ucv_string_get(flags); *p; p++) {
+ switch (*p) {
+ case 'i':
+ icase = true;
+ break;
+
+ case 's':
+ newline = true;
+ break;
+
+ case 'g':
+ global = true;
+ break;
+
+ default:
+ uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Unrecognized flag character '%c'", *p);
+
+ return NULL;
+ }
+ }
+ }
+
+ p = uc_cast_string(vm, &source, &freeable);
+ regex = ucv_regexp_new(p, icase, newline, global, &err);
+
+ if (freeable)
+ free(p);
+
+ if (err) {
+ uc_vm_raise_exception(vm, EXCEPTION_SYNTAX, "%s", err);
+ ucv_put(regex);
+ free(err);
+
+ return NULL;
+ }
+
+ return regex;
+}
+
static const uc_cfunction_list functions[] = {
{ "chr", uc_chr },
{ "delete", uc_delete },
@@ -2521,7 +2576,8 @@ static const uc_cfunction_list functions[] = {
{ "proto", uc_proto },
{ "sleep", uc_sleep },
{ "assert", uc_assert },
- { "render", uc_render }
+ { "render", uc_render },
+ { "regexp", uc_regexp }
};