aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-php-shim
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-16 18:54:33 +0900
committernsfisis <nsfisis@gmail.com>2026-08-16 18:54:33 +0900
commitc5605cc072c1880af7d70647278c6aa0de43f402 (patch)
treef11947c8d2c087f9d4f887194aef27ef3a3ce9d7 /crates/shirabe-php-shim
parent24a4f39bd981768cc299121b506f6bba584cb31d (diff)
downloadphp-shirabe-c5605cc072c1880af7d70647278c6aa0de43f402.tar.gz
php-shirabe-c5605cc072c1880af7d70647278c6aa0de43f402.tar.zst
php-shirabe-c5605cc072c1880af7d70647278c6aa0de43f402.zip
refactor(preg): re-order preg_*() functions in shim
Diffstat (limited to 'crates/shirabe-php-shim')
-rw-r--r--crates/shirabe-php-shim/src/preg.rs284
1 files changed, 142 insertions, 142 deletions
diff --git a/crates/shirabe-php-shim/src/preg.rs b/crates/shirabe-php-shim/src/preg.rs
index 56801ca9..637e969d 100644
--- a/crates/shirabe-php-shim/src/preg.rs
+++ b/crates/shirabe-php-shim/src/preg.rs
@@ -69,111 +69,6 @@ pub fn preg_match(
}
}
-pub fn preg_replace(pattern: impl PregPattern, replacement: &str, subject: &str) -> String {
- preg_replace2(pattern, replacement, subject, -1, None)
-}
-
-pub fn preg_split(pattern: impl PregPattern, subject: &str) -> Vec<String> {
- preg_split2(pattern, subject, -1, 0)
-}
-
-// PREG_PATTERN_ORDER: the outer vec is indexed by capture group, the inner by
-// match occurrence. Non-participating groups are reported as "".
-pub fn preg_match_all(pattern: impl PregPattern, subject: &str) -> Vec<Vec<String>> {
- let __resolved = pattern.resolve();
- let (re, _anchored) = __resolved.parts();
- let group_count = re.captures_len();
- let mut groups: Vec<Vec<String>> = vec![Vec::new(); group_count];
- for caps in re.captures_iter(subject) {
- for (g, group) in groups.iter_mut().enumerate() {
- group.push(
- caps.get(g)
- .map(|m| m.as_str().to_string())
- .unwrap_or_default(),
- );
- }
- }
- groups
-}
-
-// PREG_SET_ORDER: the outer vec is indexed by match occurrence, the inner by
-// capture group (a classic `$matches` row).
-pub fn preg_match_all_set_order(
- pattern: impl PregPattern,
- subject: &str,
- matches: &mut Vec<Vec<String>>,
-) -> usize {
- let __resolved = pattern.resolve();
- let (re, _anchored) = __resolved.parts();
- let mut rows: Vec<Vec<String>> = Vec::new();
- for caps in re.captures_iter(subject) {
- rows.push(php_match_row(&caps));
- }
- let count = rows.len();
- *matches = rows;
- count
-}
-
-pub fn preg_grep(pattern: impl PregPattern, input: &[String]) -> Vec<String> {
- let __resolved = pattern.resolve();
- let (re, _anchored) = __resolved.parts();
- input.iter().filter(|s| re.is_match(s)).cloned().collect()
-}
-
-pub fn preg_match_all_offset_capture(
- pattern: impl PregPattern,
- subject: &str,
- matches: &mut PregOffsetCaptureMatches,
-) -> usize {
- let __resolved = pattern.resolve();
- let (re, _anchored) = __resolved.parts();
- let group_count = re.captures_len();
- matches.groups = vec![Vec::new(); group_count];
-
- let mut count = 0;
- for caps in re.captures_iter(subject) {
- count += 1;
- for g in 0..group_count {
- // PHP stores ["", -1] for non-participating groups under
- // PREG_OFFSET_CAPTURE; the unsigned offset here approximates -1 as 0,
- // which callers must not rely on for absent groups.
- let entry = caps
- .get(g)
- .map(|m| (m.as_str().to_string(), m.start()))
- .unwrap_or_else(|| (String::new(), 0));
- matches.groups[g].push(entry);
- }
- }
-
- count
-}
-
-pub fn preg_replace_callback<F>(
- pattern: impl PregPattern,
- mut callback: F,
- subject: &str,
-) -> anyhow::Result<String>
-where
- F: FnMut(&indexmap::IndexMap<CaptureKey, Option<String>>) -> anyhow::Result<String>,
-{
- let __resolved = pattern.resolve();
- let (re, _anchored) = __resolved.parts();
- let names: Vec<Option<&str>> = re.capture_names().collect();
-
- let mut out: Vec<u8> = Vec::new();
- let mut last = 0usize;
- for caps in re.captures_iter(subject) {
- let m = caps.get(0).unwrap();
- out.extend_from_slice(&subject.as_bytes()[last..m.start()]);
- let map = single_match_map(&caps, &names, false);
- out.extend_from_slice(callback(&map)?.as_bytes());
- last = m.end();
- }
- out.extend_from_slice(&subject.as_bytes()[last..]);
-
- Ok(String::from_utf8_lossy(&out).into_owned())
-}
-
// Returns whether the pattern matched. Unmatched groups are reported as None
// (PREG_UNMATCHED_AS_NULL).
pub fn preg_match2(
@@ -205,6 +100,25 @@ pub fn preg_match2(
caps.is_some()
}
+// PREG_PATTERN_ORDER: the outer vec is indexed by capture group, the inner by
+// match occurrence. Non-participating groups are reported as "".
+pub fn preg_match_all(pattern: impl PregPattern, subject: &str) -> Vec<Vec<String>> {
+ let __resolved = pattern.resolve();
+ let (re, _anchored) = __resolved.parts();
+ let group_count = re.captures_len();
+ let mut groups: Vec<Vec<String>> = vec![Vec::new(); group_count];
+ for caps in re.captures_iter(subject) {
+ for (g, group) in groups.iter_mut().enumerate() {
+ group.push(
+ caps.get(g)
+ .map(|m| m.as_str().to_string())
+ .unwrap_or_default(),
+ );
+ }
+ }
+ groups
+}
+
pub fn preg_match_all2(
pattern: impl PregPattern,
subject: &str,
@@ -244,6 +158,52 @@ pub fn preg_match_all2(
count
}
+// PREG_SET_ORDER: the outer vec is indexed by match occurrence, the inner by
+// capture group (a classic `$matches` row).
+pub fn preg_match_all_set_order(
+ pattern: impl PregPattern,
+ subject: &str,
+ matches: &mut Vec<Vec<String>>,
+) -> usize {
+ let __resolved = pattern.resolve();
+ let (re, _anchored) = __resolved.parts();
+ let mut rows: Vec<Vec<String>> = Vec::new();
+ for caps in re.captures_iter(subject) {
+ rows.push(php_match_row(&caps));
+ }
+ let count = rows.len();
+ *matches = rows;
+ count
+}
+
+pub fn preg_match_all_offset_capture(
+ pattern: impl PregPattern,
+ subject: &str,
+ matches: &mut PregOffsetCaptureMatches,
+) -> usize {
+ let __resolved = pattern.resolve();
+ let (re, _anchored) = __resolved.parts();
+ let group_count = re.captures_len();
+ matches.groups = vec![Vec::new(); group_count];
+
+ let mut count = 0;
+ for caps in re.captures_iter(subject) {
+ count += 1;
+ for g in 0..group_count {
+ // PHP stores ["", -1] for non-participating groups under
+ // PREG_OFFSET_CAPTURE; the unsigned offset here approximates -1 as 0,
+ // which callers must not rely on for absent groups.
+ let entry = caps
+ .get(g)
+ .map(|m| (m.as_str().to_string(), m.start()))
+ .unwrap_or_else(|| (String::new(), 0));
+ matches.groups[g].push(entry);
+ }
+ }
+
+ count
+}
+
pub fn preg_match_all_offset_capture2(
pattern: impl PregPattern,
subject: &str,
@@ -282,40 +242,25 @@ pub fn preg_match_all_offset_capture2(
count
}
-pub fn preg_replace2(
- pattern: impl PregPattern,
- replacement: &str,
- subject: &str,
- limit: i64,
- count: Option<&mut usize>,
-) -> String {
+pub fn preg_grep(pattern: impl PregPattern, input: &[String]) -> Vec<String> {
let __resolved = pattern.resolve();
let (re, _anchored) = __resolved.parts();
- let limit = if limit < 0 {
- usize::MAX
- } else {
- limit as usize
- };
+ input.iter().filter(|s| re.is_match(s)).cloned().collect()
+}
- let mut out: Vec<u8> = Vec::new();
- let mut last = 0usize;
- let mut n = 0usize;
- for caps in re.captures_iter(subject) {
- if n >= limit {
- break;
- }
- let m = caps.get(0).unwrap();
- out.extend_from_slice(&subject.as_bytes()[last..m.start()]);
- php_replacement_expand(replacement, &caps, &mut out);
- last = m.end();
- n += 1;
- }
- out.extend_from_slice(&subject.as_bytes()[last..]);
+pub fn preg_grep2(pattern: impl PregPattern, array: &[&str], flags: i64) -> Vec<String> {
+ let __resolved = pattern.resolve();
+ let (re, _anchored) = __resolved.parts();
+ let invert = flags & PREG_GREP_INVERT != 0;
+ array
+ .iter()
+ .filter(|s| re.is_match(s) != invert)
+ .map(|s| s.to_string())
+ .collect()
+}
- if let Some(count) = count {
- *count = n;
- }
- String::from_utf8_lossy(&out).into_owned()
+pub fn preg_split(pattern: impl PregPattern, subject: &str) -> Vec<String> {
+ preg_split2(pattern, subject, -1, 0)
}
pub fn preg_split2(
@@ -365,15 +310,70 @@ pub fn preg_split2(
result
}
-pub fn preg_grep2(pattern: impl PregPattern, array: &[&str], flags: i64) -> Vec<String> {
+pub fn preg_replace(pattern: impl PregPattern, replacement: &str, subject: &str) -> String {
+ preg_replace2(pattern, replacement, subject, -1, None)
+}
+
+pub fn preg_replace2(
+ pattern: impl PregPattern,
+ replacement: &str,
+ subject: &str,
+ limit: i64,
+ count: Option<&mut usize>,
+) -> String {
let __resolved = pattern.resolve();
let (re, _anchored) = __resolved.parts();
- let invert = flags & PREG_GREP_INVERT != 0;
- array
- .iter()
- .filter(|s| re.is_match(s) != invert)
- .map(|s| s.to_string())
- .collect()
+ let limit = if limit < 0 {
+ usize::MAX
+ } else {
+ limit as usize
+ };
+
+ let mut out: Vec<u8> = Vec::new();
+ let mut last = 0usize;
+ let mut n = 0usize;
+ for caps in re.captures_iter(subject) {
+ if n >= limit {
+ break;
+ }
+ let m = caps.get(0).unwrap();
+ out.extend_from_slice(&subject.as_bytes()[last..m.start()]);
+ php_replacement_expand(replacement, &caps, &mut out);
+ last = m.end();
+ n += 1;
+ }
+ out.extend_from_slice(&subject.as_bytes()[last..]);
+
+ if let Some(count) = count {
+ *count = n;
+ }
+ String::from_utf8_lossy(&out).into_owned()
+}
+
+pub fn preg_replace_callback<F>(
+ pattern: impl PregPattern,
+ mut callback: F,
+ subject: &str,
+) -> anyhow::Result<String>
+where
+ F: FnMut(&indexmap::IndexMap<CaptureKey, Option<String>>) -> anyhow::Result<String>,
+{
+ let __resolved = pattern.resolve();
+ let (re, _anchored) = __resolved.parts();
+ let names: Vec<Option<&str>> = re.capture_names().collect();
+
+ let mut out: Vec<u8> = Vec::new();
+ let mut last = 0usize;
+ for caps in re.captures_iter(subject) {
+ let m = caps.get(0).unwrap();
+ out.extend_from_slice(&subject.as_bytes()[last..m.start()]);
+ let map = single_match_map(&caps, &names, false);
+ out.extend_from_slice(callback(&map)?.as_bytes());
+ last = m.end();
+ }
+ out.extend_from_slice(&subject.as_bytes()[last..]);
+
+ Ok(String::from_utf8_lossy(&out).into_owned())
}
// Translates a PHP PCRE pattern (delimiters + trailing modifiers) into a regex