Fun 0.41.5
The programming language that makes you have fun!
Loading...
Searching...
No Matches
findall.c
Go to the documentation of this file.
1/*
2 * This file is part of the Fun programming language.
3 * https://fun-lang.xyz/
4 *
5 * Copyright 2025 Johannes Findeisen <you@hanez.org>
6 * Licensed under the terms of the Apache-2.0 license.
7 * https://opensource.org/license/apache-2-0
8 */
9
10/**
11 * @file findall.c
12 * @brief Implements the OP_PCRE2_FINDALL opcode (conditional build).
13 *
14 * Finds all non-overlapping matches of a PCRE2 pattern in a subject string
15 * and returns an array of maps describing each match when FUN_WITH_PCRE2 is
16 * enabled. When PCRE2 support is disabled at build time, the opcode falls
17 * back to returning an empty array.
18 */
19
20/**
21 * OP_PCRE2_FINDALL: (pattern:any, text:any, flags:int|bool=0) -> array(map)
22 *
23 * Behavior when FUN_WITH_PCRE2 is enabled:
24 * - Pops three arguments from the VM stack: pattern, text, flags.
25 * - pattern and text are converted to strings using value_to_string_alloc().
26 * - flags bits map to PCRE2 options:
27 * - 1 = PCRE2_CASELESS (I)
28 * - 2 = PCRE2_MULTILINE (M)
29 * - 4 = PCRE2_DOTALL (S)
30 * - 8 = PCRE2_UTF (U)
31 * - 16 = PCRE2_EXTENDED (X)
32 * - Compiles the pattern and scans the subject for all non-overlapping
33 * matches. For each match, pushes into the result array a map with keys:
34 * - "full": matched substring (group 0)
35 * - "start": start index (int)
36 * - "end": end index (int, exclusive)
37 * - "groups": array of captured group strings (excluding group 0)
38 * - On compilation error or allocation failure, returns an empty array.
39 *
40 * Behavior when FUN_WITH_PCRE2 is disabled:
41 * - Pops three values and returns an empty array.
42 */
43
44/* PCRE2_FINDALL */
46#ifdef FUN_WITH_PCRE2
47 Value vflags = pop_value(vm);
50 int flags = 0;
51 if (vflags.type == VAL_INT || vflags.type == VAL_BOOL) flags = (int)vflags.i;
54 free_value(vflags);
57 if (!pattern || !subject) {
58 if (pattern) free(pattern);
59 if (subject) free(subject);
61 break;
62 }
63#ifndef PCRE2_CODE_UNIT_WIDTH
64#define PCRE2_CODE_UNIT_WIDTH 8
65#endif
66#include <pcre2.h>
68 PCRE2_SIZE erroff;
69 uint32_t opt = 0;
70 if (flags & 1) opt |= PCRE2_CASELESS; /* I */
71 if (flags & 2) opt |= PCRE2_MULTILINE; /* M */
72 if (flags & 4) opt |= PCRE2_DOTALL; /* S */
73 if (flags & 8) opt |= PCRE2_UTF; /* U */
74 if (flags & 16) opt |= PCRE2_EXTENDED; /* X */
75 pcre2_code *re = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, opt, &errorcode, &erroff, NULL);
76 if (!re) {
80 break;
81 }
82 pcre2_match_data *mdata = pcre2_match_data_create_from_pattern(re, NULL);
84 size_t subj_len = strlen(subject);
85 size_t start_off = 0;
86 int gcount = 0;
87 while (1) {
88 int rc = pcre2_match(re, (PCRE2_SPTR)subject, (PCRE2_SIZE)subj_len, start_off, 0, mdata, NULL);
89 if (rc <= 0) break;
90 PCRE2_SIZE *ov = pcre2_get_ovector_pointer(mdata);
91 int s0 = (int)ov[0];
92 int e0 = (int)ov[1];
93 /* result map for this match */
95 char *full = string_substr(subject, s0, e0 - s0);
96 (void)map_set(&res, "full", make_string(full ? full : ""));
97 if (full) free(full);
98 (void)map_set(&res, "start", make_int(s0));
99 (void)map_set(&res, "end", make_int(e0));
100 Value groups = make_array_from_values(NULL, 0);
101 for (int i = 1; i < rc; ++i) {
102 int s = (int)ov[2 * i];
103 int e = (int)ov[2 * i + 1];
104 char *gstr = (s >= 0 && e >= s) ? string_substr(subject, s, e - s) : NULL;
105 Value gv = make_string(gstr ? gstr : "");
106 if (gstr) free(gstr);
107 (void)array_push(&groups, gv);
108 }
109 (void)map_set(&res, "groups", groups);
110 (void)array_push(&out, res);
111 /* advance start offset; guard against empty match */
112 if (e0 == s0) {
113 if ((size_t)e0 < subj_len) {
114 start_off = e0 + 1;
115 } else {
116 break;
117 }
118 } else {
119 start_off = e0;
120 }
121 gcount = rc;
122 }
128#else
129 Value a = pop_value(vm);
130 free_value(a);
131 Value b = pop_value(vm);
132 free_value(b);
133 Value c = pop_value(vm);
134 free_value(c);
136#endif
137 break;
138}
Value a
Definition add.c:37
Value out
Definition apop.c:38
uint32_t b
Definition band.c:32
@ OP_PCRE2_FINDALL
Definition bytecode.h:194
pcsc_ctx_entry * e
Definition connect.c:38
CURLcode rc
Definition download.c:71
pcre2_match_data_free(mdata)
free_value(vflags)
uint32_t opt
Definition findall.c:69
Value vtext
Definition findall.c:48
pcre2_code * re
Definition findall.c:75
Value vpat
Definition findall.c:49
pcre2_match_data * mdata
Definition findall.c:82
free(pattern)
push_value(vm, out)
size_t subj_len
Definition findall.c:84
pcre2_code_free(re)
int errorcode
Definition findall.c:67
PCRE2_SIZE erroff
Definition findall.c:68
int gcount
Definition findall.c:86
char * subject
Definition findall.c:53
char * pattern
Definition findall.c:52
size_t start_off
Definition findall.c:85
const char * res
Definition get_string.c:38
Value c
Definition load_const.c:31
int map_set(Value *vm, const char *key, Value v)
Insert or replace a key in the map.
Definition map.c:79
Value make_map_empty(void)
Construct a new empty map Value.
Definition map.c:35
char * full
Definition match.c:95
PCRE2_SIZE * ov
Definition match.c:90
uint32_t s
Definition rol.c:31
char * string_substr(const char *s, int start, int len)
Create a newly allocated substring of s.
Definition str_utils.c:35
int flags
Definition stringify.c:38
Tagged union representing a Fun value.
Definition value.h:68
int64_t i
Definition value.h:71
ValueType type
Definition value.h:69
Value make_string(const char *s)
Construct a string Value by duplicating the given C string.
Definition value.c:95
char * value_to_string_alloc(const Value *v)
Allocate a printable C string for a Value.
Definition value.c:641
int array_push(Value *v, Value newElem)
Append a Value to an array.
Definition value.c:257
Value make_int(int64_t v)
Construct a Value representing a 64-bit integer.
Definition value.c:51
Value make_array_from_values(const Value *vals, int count)
Create an array Value by copying items from an input span.
Definition value.c:142
@ VAL_BOOL
Definition value.h:52
@ VAL_INT
Definition value.h:51
static Value pop_value(VM *vm)
Pop a Value from the VM operand stack.
Definition vm.c:580