ruffle/core/src/avm2/regexp.rs

126 lines
2.9 KiB
Rust
Raw Normal View History

2021-02-11 07:56:21 +00:00
//! RegExp Structure
use crate::avm2::string::AvmString;
use bitflags::bitflags;
use gc_arena::Collect;
use regress::Regex;
#[derive(Clone, Collect, Debug)]
#[collect(no_drop)]
pub struct RegExp<'gc> {
source: AvmString<'gc>,
flags: RegExpFlags,
2021-02-11 07:56:21 +00:00
last_index: usize,
}
bitflags! {
#[derive(Collect)]
#[collect(require_static)]
2021-02-11 07:56:21 +00:00
struct RegExpFlags: u8 {
const GLOBAL = 1 << 0;
const IGNORE_CASE = 1 << 1;
const MULTILINE = 1 << 2;
const DOTALL = 1 << 3;
const EXTENDED = 1 << 4;
}
}
impl<'gc> RegExp<'gc> {
pub fn new<S>(source: S) -> Self
where
S: Into<AvmString<'gc>>,
{
Self {
source: source.into(),
flags: RegExpFlags::empty(),
2021-02-11 07:56:21 +00:00
last_index: 0,
}
}
pub fn source(&self) -> AvmString<'gc> {
self.source
}
pub fn set_source<S>(&mut self, source: S)
where
S: Into<AvmString<'gc>>,
{
self.source = source.into();
}
pub fn last_index(&self) -> usize {
self.last_index
}
pub fn set_last_index(&mut self, i: usize) {
self.last_index = i;
}
pub fn dotall(&self) -> bool {
self.flags.contains(RegExpFlags::DOTALL)
2021-02-11 07:56:21 +00:00
}
pub fn set_dotall(&mut self, value: bool) {
self.flags.set(RegExpFlags::DOTALL, value);
2021-02-11 07:56:21 +00:00
}
pub fn extended(&self) -> bool {
self.flags.contains(RegExpFlags::EXTENDED)
2021-02-11 07:56:21 +00:00
}
pub fn set_extended(&mut self, value: bool) {
self.flags.set(RegExpFlags::EXTENDED, value);
2021-02-11 07:56:21 +00:00
}
pub fn global(&self) -> bool {
self.flags.contains(RegExpFlags::GLOBAL)
2021-02-11 07:56:21 +00:00
}
pub fn set_global(&mut self, value: bool) {
self.flags.set(RegExpFlags::GLOBAL, value);
2021-02-11 07:56:21 +00:00
}
pub fn ignore_case(&self) -> bool {
self.flags.contains(RegExpFlags::IGNORE_CASE)
2021-02-11 07:56:21 +00:00
}
pub fn set_ignore_case(&mut self, value: bool) {
self.flags.set(RegExpFlags::IGNORE_CASE, value);
2021-02-11 07:56:21 +00:00
}
pub fn multiline(&self) -> bool {
self.flags.contains(RegExpFlags::MULTILINE)
2021-02-11 07:56:21 +00:00
}
pub fn set_multiline(&mut self, value: bool) {
self.flags.set(RegExpFlags::MULTILINE, value);
2021-02-11 07:56:21 +00:00
}
pub fn test(&mut self, text: &str) -> bool {
self.exec(text).is_some()
}
pub fn exec(&mut self, text: &str) -> Option<regress::Match> {
if let Ok(re) = Regex::with_flags(
&self.source,
regress::Flags {
icase: self.ignore_case(),
multiline: self.multiline(),
dot_all: self.dotall(),
no_opt: false,
},
) {
let start = if self.global() { self.last_index } else { 0 };
2021-06-05 10:53:23 +00:00
if let Some(matched) = re.find_from(text, start).next() {
2021-02-11 07:56:21 +00:00
if self.global() {
self.last_index = matched.end();
}
return Some(matched);
}
}
None
}
}