// The `RegexSet` is not exposed with option support or matching at an // arbitrary position with a crate just yet. To circumvent this, we use // the `Exec` structure directly. pubstruct RegexSet {
re: bytes::RegexSet,
}
ffi_fn! { fn rure_compile_must(pattern: *const c_char) -> *const Regex { let len = unsafe { CStr::from_ptr(pattern).to_bytes().len() }; let pat = pattern as *const u8; letmut err = Error::new(ErrorKind::None); let re = rure_compile(
pat, len, RURE_DEFAULT_FLAGS, ptr::null(), &mut err); if err.is_err() { let _ = writeln!(&mut io::stderr(), "{}", err); let _ = writeln!(
&mut io::stderr(), "aborting from rure_compile_must"); unsafe { abort() }
}
re
}
}
ffi_fn! { fn rure_compile(
pattern: *const u8,
length: size_t,
flags: u32,
options: *const Options,
error: *mut Error,
) -> *const Regex { let pat = unsafe { slice::from_raw_parts(pattern, length) }; let pat = match str::from_utf8(pat) {
Ok(pat) => pat,
Err(err) => { unsafe { if !error.is_null() {
*error = Error::new(ErrorKind::Str(err));
} return ptr::null();
}
}
}; letmut builder = bytes::RegexBuilder::new(pat); if !options.is_null() { let options = unsafe { &*options };
builder.size_limit(options.size_limit);
builder.dfa_size_limit(options.dfa_size_limit);
}
builder.case_insensitive(flags & RURE_FLAG_CASEI > 0);
builder.multi_line(flags & RURE_FLAG_MULTI > 0);
builder.dot_matches_new_line(flags & RURE_FLAG_DOTNL > 0);
builder.swap_greed(flags & RURE_FLAG_SWAP_GREED > 0);
builder.ignore_whitespace(flags & RURE_FLAG_SPACE > 0);
builder.unicode(flags & RURE_FLAG_UNICODE > 0); match builder.build() {
Ok(re) => { letmut capture_names = HashMap::new(); for (i, name) in re.capture_names().enumerate() { iflet Some(name) = name {
capture_names.insert(name.to_owned(), i as i32);
}
} let re = Regex {
re: re,
capture_names: capture_names,
}; Box::into_raw(Box::new(re))
}
Err(err) => { unsafe { if !error.is_null() {
*error = Error::new(ErrorKind::Regex(err));
}
ptr::null()
}
}
}
}
}
let it = unsafe { &mut *it }; let cn = match it.capture_names.next() { // Top-level iterator ran out of capture groups
None => returnfalse,
Some(val) => { let name = match val { // inner Option didn't have a name
None => "",
Some(name) => name
};
name
}
};
unsafe { let cs = match CString::new(cn.as_bytes()) {
Result::Ok(val) => val,
Result::Err(_) => returnfalse
}; let ptr = cs.into_raw();
it.name_ptrs.push(ptr);
*capture_name = ptr;
} true
ffi_fn! { fn rure_iter_next(
it: *mut Iter,
haystack: *const u8,
len: size_t,
match_info: *mut rure_match,
) -> bool { let it = unsafe { &mut *it }; let re = unsafe { &*it.re }; let text = unsafe { slice::from_raw_parts(haystack, len) }; if it.last_end > text.len() { returnfalse;
} let (s, e) = match re.find_at(text, it.last_end) {
None => returnfalse,
Some(m) => (m.start(), m.end()),
}; if s == e { // This is an empty match. To ensure we make progress, start // the next search at the smallest possible starting position // of the next match following this one.
it.last_end += 1; // Don't accept empty matches immediately following a match. // Just move on to the next match. if Some(e) == it.last_match { return rure_iter_next(it, haystack, len, match_info);
}
} else {
it.last_end = e;
}
it.last_match = Some(e); if !match_info.is_null() { unsafe {
(*match_info).start = s;
(*match_info).end = e;
}
} true
}
}
ffi_fn! { fn rure_iter_next_captures(
it: *mut Iter,
haystack: *const u8,
len: size_t,
captures: *mut Captures,
) -> bool { let it = unsafe { &mut *it }; let re = unsafe { &*it.re }; let slots = unsafe { &mut (*captures).0 }; let text = unsafe { slice::from_raw_parts(haystack, len) }; if it.last_end > text.len() { returnfalse;
} let (s, e) = match re.read_captures_at(slots, text, it.last_end) {
None => returnfalse,
Some(m) => (m.start(), m.end()),
}; if s == e { // This is an empty match. To ensure we make progress, start // the next search at the smallest possible starting position // of the next match following this one.
it.last_end += 1; // Don't accept empty matches immediately following a match. // Just move on to the next match. if Some(e) == it.last_match { return rure_iter_next_captures(it, haystack, len, captures);
}
} else {
it.last_end = e;
}
it.last_match = Some(e); true
}
}
ffi_fn! { fn rure_captures_new(re: *const Regex) -> *mut Captures { let re = unsafe { &*re }; let captures = Captures(re.locations()); Box::into_raw(Box::new(captures))
}
}
// read_matches_at isn't guaranteed to set non-matches to false for item in matches.iter_mut() {
*item = false;
}
re.read_matches_at(&mut matches, haystack, start)
}
}
ffi_fn! { fn rure_escape_must(pattern: *const c_char) -> *const c_char { let len = unsafe { CStr::from_ptr(pattern).to_bytes().len() }; let pat = pattern as *const u8; letmut err = Error::new(ErrorKind::None); let esc = rure_escape(pat, len, &mut err); if err.is_err() { let _ = writeln!(&mut io::stderr(), "{}", err); let _ = writeln!(
&mut io::stderr(), "aborting from rure_escape_must"); unsafe { abort() }
}
esc
}
}
/// A helper function that implements fallible escaping in a way that returns /// an error if escaping failed. /// /// This should ideally be exposed, but it needs API design work. In /// particular, this should not return a C string, but a `const uint8_t *` /// instead, since it may contain a NUL byte. fn rure_escape(
pattern: *const u8,
length: size_t,
error: *mut Error,
) -> *const c_char { let pat: &[u8] = unsafe { slice::from_raw_parts(pattern, length) }; let str_pat = match str::from_utf8(pat) {
Ok(val) => val,
Err(err) => unsafe { if !error.is_null() {
*error = Error::new(ErrorKind::Str(err));
} return ptr::null();
},
}; let esc_pat = regex::escape(str_pat); let c_esc_pat = match CString::new(esc_pat) {
Ok(val) => val,
Err(err) => unsafe { if !error.is_null() {
*error = Error::new(ErrorKind::Nul(err));
} return ptr::null();
},
};
c_esc_pat.into_raw() as *const c_char
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.