1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
pub(crate) struct StringStream {
raw_text: String,
index: usize,
}
impl StringStream {
pub(crate) fn new(raw_text: String) -> Self {
Self { raw_text, index: 0 }
}
/// Read count characters starting at self.index, and return those characters as a string
pub(crate) fn read(&mut self, count: usize) -> &str {
let new_index = self.index + count;
let buf = if new_index > self.raw_text.len() {
&self.raw_text[self.index..]
} else {
&self.raw_text[self.index..new_index]
};
self.index = new_index;
buf
}
pub(crate) fn seek_back(&mut self, offset: usize) {
self.index = self.index.saturating_sub(offset);
}
/// Advance the index past specific chars
///
/// Return substring that was advanced past
pub(crate) fn advance_past_chars(&mut self, chars: &[char]) -> &str {
let start_index = self.index;
loop {
let current_char = self.raw_text.as_bytes()[self.index] as char;
self.index += 1;
if chars.contains(¤t_char) || self.index == self.raw_text.len() {
break;
}
}
&self.raw_text[start_index..self.index - 1]
}
/// Characters that gdb escapes that should not be escaped by this parser
pub(crate) fn advance_past_string_with_gdb_escapes(&mut self) -> String {
let mut buf = String::new();
loop {
let c = self.raw_text.as_bytes()[self.index] as char;
self.index += 1;
match c {
'\\' => {
// We are on a backslash and there is another character after the backslash
// to parse. Handle this case specially since gdb escaped it for
// Get the next char that is being escaped
let c2 = self.raw_text.as_bytes()[self.index] as char;
self.index += 1;
// only store the escaped character in the buffer; don't store the backslash
// (don't leave it escaped)
buf.push(c2);
}
'"' => {
// Quote is closed. Exit (and don't include the end quote).
break;
}
c => {
// capture this character, and keep capturing
buf.push(c);
}
}
}
buf
}
}