Performance improvement.
The refactoring added `next_is` which takes a `&str` as parameter, while we only use it with strings of lengths 2 and 3. Replacing this by 2 dedicated methods (which can be added to the trait interface and only specialized if needed) removes almost all the overhead that was added by `Input`.
This commit is contained in:
parent
d9bb7a1693
commit
f8b6d849d3
3 changed files with 23 additions and 14 deletions
|
@ -90,10 +90,4 @@ impl<T: Iterator<Item = char>> Input for BufferedInput<T> {
|
||||||
fn peek_nth(&self, n: usize) -> char {
|
fn peek_nth(&self, n: usize) -> char {
|
||||||
self.buffer[n]
|
self.buffer[n]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn next_is(&self, pat: &str) -> bool {
|
|
||||||
assert!(self.buffer.len() >= pat.len());
|
|
||||||
self.buffer.iter().zip(pat.chars()).all(|(a, b)| *a == b)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,10 +102,25 @@ pub trait Input {
|
||||||
self.peek_nth(n) == c
|
self.peek_nth(n) == c
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return whether the next characters in the input source match the given pattern.
|
/// Return whether the next 2 characters in the input source match the given characters.
|
||||||
///
|
///
|
||||||
/// This function assumes that the next `pat.len()` characters in the input has already been
|
/// This function assumes that the next 2 characters in the input has already been fetched
|
||||||
/// fetched through [`Input::lookahead`].
|
/// through [`Input::lookahead`].
|
||||||
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn next_is(&self, pat: &str) -> bool;
|
fn next_2_are(&self, c1: char, c2: char) -> bool {
|
||||||
|
assert!(self.buflen() >= 2);
|
||||||
|
self.peek() == c1 && self.peek_nth(1) == c2
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return whether the next 3 characters in the input source match the given characters.
|
||||||
|
///
|
||||||
|
/// This function assumes that the next 3 characters in the input has already been fetched
|
||||||
|
/// through [`Input::lookahead`].
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
fn next_3_are(&self, c1: char, c2: char, c3: char) -> bool {
|
||||||
|
assert!(self.buflen() >= 3);
|
||||||
|
self.peek() == c1 && self.peek_nth(1) == c2 && self.peek_nth(2) == c3
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -528,7 +528,7 @@ impl<T: Input> Scanner<T> {
|
||||||
/// Consume a linebreak (either CR, LF or CRLF), if any. Do nothing if there's none.
|
/// Consume a linebreak (either CR, LF or CRLF), if any. Do nothing if there's none.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn skip_linebreak(&mut self) {
|
fn skip_linebreak(&mut self) {
|
||||||
if self.input.next_is("\r\n") {
|
if self.input.next_2_are('\r', '\n') {
|
||||||
// While technically not a blank, this does not matter as `self.leading_whitespace`
|
// While technically not a blank, this does not matter as `self.leading_whitespace`
|
||||||
// will be reset by `skip_nl`.
|
// will be reset by `skip_nl`.
|
||||||
self.skip_blank();
|
self.skip_blank();
|
||||||
|
@ -597,7 +597,7 @@ impl<T: Input> Scanner<T> {
|
||||||
/// [`Self::lookahead`] must have been called before calling this function.
|
/// [`Self::lookahead`] must have been called before calling this function.
|
||||||
fn next_is_document_start(&self) -> bool {
|
fn next_is_document_start(&self) -> bool {
|
||||||
assert!(self.input.buflen() >= 4);
|
assert!(self.input.buflen() >= 4);
|
||||||
self.input.next_is("---") && is_blank_or_breakz(self.input.peek_nth(3))
|
self.input.next_3_are('-', '-', '-') && is_blank_or_breakz(self.input.peek_nth(3))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether the next characters correspond to an end of document.
|
/// Check whether the next characters correspond to an end of document.
|
||||||
|
@ -605,7 +605,7 @@ impl<T: Input> Scanner<T> {
|
||||||
/// [`Self::lookahead`] must have been called before calling this function.
|
/// [`Self::lookahead`] must have been called before calling this function.
|
||||||
fn next_is_document_end(&self) -> bool {
|
fn next_is_document_end(&self) -> bool {
|
||||||
assert!(self.input.buflen() >= 4);
|
assert!(self.input.buflen() >= 4);
|
||||||
self.input.next_is("...") && is_blank_or_breakz(self.input.peek_nth(3))
|
self.input.next_3_are('.', '.', '.') && is_blank_or_breakz(self.input.peek_nth(3))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether the next characters correspond to a document indicator.
|
/// Check whether the next characters correspond to a document indicator.
|
||||||
|
@ -615,7 +615,7 @@ impl<T: Input> Scanner<T> {
|
||||||
fn next_is_document_indicator(&self) -> bool {
|
fn next_is_document_indicator(&self) -> bool {
|
||||||
assert!(self.input.buflen() >= 4);
|
assert!(self.input.buflen() >= 4);
|
||||||
is_blank_or_breakz(self.input.peek_nth(3))
|
is_blank_or_breakz(self.input.peek_nth(3))
|
||||||
&& (self.input.next_is("...") || self.input.next_is("---"))
|
&& (self.input.next_3_are('.', '.', '.') || self.input.next_3_are('-', '-', '-'))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a token at the given position.
|
/// Insert a token at the given position.
|
||||||
|
|
Loading…
Reference in a new issue