diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-06-14 12:48:58 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-06-14 12:48:58 +0900 |
| commit | c1070afe69f53b621adea232527080d2c922e1a9 (patch) | |
| tree | be125ece467c2d1d761cd9f8a606337f6e5233f4 /crates | |
| parent | 4ace644474d3d0e5575d19616ce46ba7d521fc64 (diff) | |
| download | php-shirabe-c1070afe69f53b621adea232527080d2c922e1a9.tar.gz php-shirabe-c1070afe69f53b621adea232527080d2c922e1a9.tar.zst php-shirabe-c1070afe69f53b621adea232527080d2c922e1a9.zip | |
refactor(pcre): consolidate duplicate preg_* shim helpers
The preg.rs shim had several near-duplicate functions: simple helpers
re-implementing logic already covered by their full-featured `2`
variants. Delegate or remove the redundant ones while preserving
behavior, and migrate the affected callers:
- preg_replace / preg_split now delegate to preg_replace2 / preg_split2
- preg_match_all_simple removed; its caller uses preg_match_all
- preg_split_chars removed; its caller uses a char-boundary iterator
- preg_match_offset removed; its callers use preg_match2 directly
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates')
4 files changed, 78 insertions, 110 deletions
diff --git a/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs b/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs index 27a74e6..0de90be 100644 --- a/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs +++ b/crates/shirabe-external-packages/src/symfony/console/formatter/output_formatter.rs @@ -126,12 +126,10 @@ impl OutputFormatter { .expect("preg_replace failed"); style.set_href(&url); } else if r#match[0] == "options" { - let mut options: Vec<Vec<String>> = vec![]; - shirabe_php_shim::preg_match_all_simple( + let mut options = shirabe_php_shim::preg_match_all( "([^,;]+)", &shirabe_php_shim::strtolower(&r#match[1]), - &mut options, - )?; + ); let options = shirabe_php_shim::array_shift(&mut options).unwrap_or_default(); for option in &options { style.set_option(option); diff --git a/crates/shirabe-external-packages/src/symfony/console/input/string_input.rs b/crates/shirabe-external-packages/src/symfony/console/input/string_input.rs index 2d53f68..952a18e 100644 --- a/crates/shirabe-external-packages/src/symfony/console/input/string_input.rs +++ b/crates/shirabe-external-packages/src/symfony/console/input/string_input.rs @@ -5,7 +5,7 @@ use crate::symfony::console::input::argv_input::ArgvInput; use crate::symfony::console::input::input_definition::InputDefinition; use crate::symfony::console::input::input_interface::InputInterface; use indexmap::IndexMap; -use shirabe_php_shim::PhpMixed; +use shirabe_php_shim::{CaptureKey, PhpMixed}; /// StringInput represents an input provided as a string. /// @@ -54,52 +54,80 @@ impl StringInput { continue; } - let mut m: Vec<String> = vec![]; - if shirabe_php_shim::preg_match_offset(r"/\s+/A", input, &mut m, 0, cursor) { + let mut m: IndexMap<CaptureKey, Option<String>> = IndexMap::new(); + if shirabe_php_shim::preg_match2(r"/\s+/A", input, Some(&mut m), 0, cursor as usize) + .expect("invalid regex") + == 1 + { if token.is_some() { tokens.push(token.take().unwrap()); } - cursor += shirabe_php_shim::strlen(&m[0]); - } else if shirabe_php_shim::preg_match_offset( + cursor += + shirabe_php_shim::strlen(m[&CaptureKey::ByIndex(0)].as_deref().unwrap_or("")); + } else if shirabe_php_shim::preg_match2( &format!(r#"/([^="'\s]+?)(=?)({}+)/A"#, Self::REGEX_QUOTED_STRING), input, - &mut m, + Some(&mut m), 0, - cursor, - ) { - let inner = shirabe_php_shim::substr(&m[3], 1, Some(-1)); + cursor as usize, + ) + .expect("invalid regex") + == 1 + { + let inner = shirabe_php_shim::substr( + m[&CaptureKey::ByIndex(3)].as_deref().unwrap_or(""), + 1, + Some(-1), + ); let replaced = shirabe_php_shim::str_replace_arr(&["\"'", "'\"", "''", "\"\""], "", &inner); token = Some(format!( "{}{}{}{}", token.unwrap_or_default(), - m[1], - m[2], + m[&CaptureKey::ByIndex(1)].as_deref().unwrap_or(""), + m[&CaptureKey::ByIndex(2)].as_deref().unwrap_or(""), shirabe_php_shim::stripcslashes(&replaced) )); - cursor += shirabe_php_shim::strlen(&m[0]); - } else if shirabe_php_shim::preg_match_offset( + cursor += + shirabe_php_shim::strlen(m[&CaptureKey::ByIndex(0)].as_deref().unwrap_or("")); + } else if shirabe_php_shim::preg_match2( &format!(r"/{}/A", Self::REGEX_QUOTED_STRING), input, - &mut m, + Some(&mut m), 0, - cursor, - ) { + cursor as usize, + ) + .expect("invalid regex") + == 1 + { token = Some(format!( "{}{}", token.unwrap_or_default(), - shirabe_php_shim::stripcslashes(&shirabe_php_shim::substr(&m[0], 1, Some(-1))) + shirabe_php_shim::stripcslashes(&shirabe_php_shim::substr( + m[&CaptureKey::ByIndex(0)].as_deref().unwrap_or(""), + 1, + Some(-1) + )) )); - cursor += shirabe_php_shim::strlen(&m[0]); - } else if shirabe_php_shim::preg_match_offset( + cursor += + shirabe_php_shim::strlen(m[&CaptureKey::ByIndex(0)].as_deref().unwrap_or("")); + } else if shirabe_php_shim::preg_match2( &format!(r"/{}/A", Self::REGEX_UNQUOTED_STRING), input, - &mut m, + Some(&mut m), 0, - cursor, - ) { - token = Some(format!("{}{}", token.unwrap_or_default(), m[1])); - cursor += shirabe_php_shim::strlen(&m[0]); + cursor as usize, + ) + .expect("invalid regex") + == 1 + { + token = Some(format!( + "{}{}", + token.unwrap_or_default(), + m[&CaptureKey::ByIndex(1)].as_deref().unwrap_or("") + )); + cursor += + shirabe_php_shim::strlen(m[&CaptureKey::ByIndex(0)].as_deref().unwrap_or("")); } else { // should never happen return Err( diff --git a/crates/shirabe-php-shim/src/preg.rs b/crates/shirabe-php-shim/src/preg.rs index e1b05b6..48b81ed 100644 --- a/crates/shirabe-php-shim/src/preg.rs +++ b/crates/shirabe-php-shim/src/preg.rs @@ -58,23 +58,12 @@ pub fn preg_match(pattern: &str, subject: &str, matches: &mut Vec<Option<String> // Returns Some(result) on success, None on error. pub fn preg_replace(pattern: &str, replacement: &str, subject: &str) -> Option<String> { - let re = compile_php_pattern(pattern).ok()?; - let mut out: Vec<u8> = Vec::new(); - let mut last = 0; - for caps in re.captures_iter(subject) { - 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(); - } - out.extend_from_slice(&subject.as_bytes()[last..]); - Some(String::from_utf8_lossy(&out).into_owned()) + preg_replace2(pattern, replacement, subject, -1, None) } // Returns Some(parts) on success, None on error. pub fn preg_split(pattern: &str, subject: &str) -> Option<Vec<String>> { - let re = compile_php_pattern(pattern).ok()?; - Some(php_split_impl(&re, subject)) + preg_split2(pattern, subject, -1, 0) } // PREG_PATTERN_ORDER: the outer vec is indexed by capture group, the inner by @@ -95,29 +84,6 @@ pub fn preg_match_all(pattern: &str, subject: &str) -> Vec<Vec<String>> { groups } -pub fn preg_match_all_simple( - pattern: &str, - subject: &str, - matches: &mut Vec<Vec<String>>, -) -> anyhow::Result<i64> { - let re = compile_php_pattern(pattern)?; - let group_count = re.captures_len(); - let mut groups: Vec<Vec<String>> = vec![Vec::new(); group_count]; - let mut count = 0i64; - for caps in re.captures_iter(subject) { - count += 1; - for g in 0..group_count { - groups[g].push( - caps.get(g) - .map(|m| m.as_str().to_string()) - .unwrap_or_default(), - ); - } - } - *matches = groups; - Ok(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( @@ -135,26 +101,6 @@ pub fn preg_match_all_set_order( Ok(count) } -pub fn preg_match_offset( - pattern: &str, - subject: &str, - matches: &mut Vec<String>, - _flags: i64, - offset: i64, -) -> bool { - let re = compile_php_pattern(pattern).unwrap_or_else(|e| panic!("invalid regex: {e}")); - match re.captures_at(subject, offset as usize) { - Some(caps) => { - *matches = php_match_row(&caps); - true - } - None => { - matches.clear(); - false - } - } -} - pub fn preg_match_groups(pattern: &str, subject: &str) -> Option<Vec<String>> { let re = compile_php_pattern(pattern).ok()?; let caps = re.captures(subject)?; @@ -166,11 +112,6 @@ pub fn preg_grep(pattern: &str, input: &Vec<String>) -> Vec<String> { input.iter().filter(|s| re.is_match(s)).cloned().collect() } -pub fn preg_split_chars(pattern: &str, subject: &str) -> Vec<String> { - let re = compile_php_pattern(pattern).unwrap_or_else(|e| panic!("invalid regex: {e}")); - php_split_impl(&re, subject) -} - pub fn preg_match_all_offset_capture( pattern: &str, subject: &str, @@ -551,21 +492,6 @@ fn php_replacement_group(bytes: &[u8]) -> (usize, usize) { (group, consumed) } -// PHP `preg_split($pattern, $subject)` with no flags or limit: the text between -// successive matches, including the leading and trailing pieces (which may be -// empty). Zero-width matches split between every position. -fn php_split_impl(re: ®ex::Regex, subject: &str) -> Vec<String> { - let mut result = Vec::new(); - let mut last = 0; - for caps in re.captures_iter(subject) { - let m = caps.get(0).unwrap(); - result.push(subject[last..m.start()].to_string()); - last = m.end(); - } - result.push(subject[last..].to_string()); - result -} - // Classic preg_match `$matches` row: index 0 is the full match, trailing // unmatched groups are truncated and interior unmatched groups become "". fn php_match_row(caps: ®ex::Captures) -> Vec<String> { diff --git a/crates/shirabe/src/console/application.rs b/crates/shirabe/src/console/application.rs index 00453f8..4be2f90 100644 --- a/crates/shirabe/src/console/application.rs +++ b/crates/shirabe/src/console/application.rs @@ -2703,17 +2703,33 @@ impl Application { let mut line = String::new(); let mut offset = 0i64; - let mut m: Vec<String> = Vec::new(); - while shirabe_php_shim::preg_match_offset(r"/.{1,10000}/u", &utf8_string, &mut m, 0, offset) + let mut m: indexmap::IndexMap<shirabe_php_shim::CaptureKey, Option<String>> = + indexmap::IndexMap::new(); + while shirabe_php_shim::preg_match2( + r"/.{1,10000}/u", + &utf8_string, + Some(&mut m), + 0, + offset as usize, + ) + .expect("invalid regex") + == 1 { - offset += shirabe_php_shim::strlen(&m[0]); + let m0 = m[&shirabe_php_shim::CaptureKey::ByIndex(0)] + .as_deref() + .unwrap_or(""); + offset += shirabe_php_shim::strlen(m0); - for char in shirabe_php_shim::preg_split_chars(r"//u", &m[0]) { + let chunk = m0; + for char in chunk + .char_indices() + .map(|(i, c)| &chunk[i..i + c.len_utf8()]) + { // test if $char could be appended to current line if shirabe_php_shim::mb_strwidth(&format!("{}{}", line, char), Some("utf8")) <= width { - line.push_str(&char); + line.push_str(char); continue; } // if not, push current line to array and make new line @@ -2723,7 +2739,7 @@ impl Application { " ", shirabe_php_shim::STR_PAD_RIGHT, )); - line = char; + line = char.to_string(); } } |
