kernel/cmdline/
tokenizer.rs1pub struct Tokenizer<'a> {
2 running_str: &'a str,
3 idx: usize,
4}
5
6impl<'a> Tokenizer<'a> {
7 pub fn new(inp: &'a str) -> Self {
8 Self {
9 running_str: inp,
10 idx: 0,
11 }
12 }
13
14 pub fn current_index(&self) -> usize {
15 self.idx
16 }
17
18 fn next_token<P1, P2, P3>(
19 &mut self,
20 find_pattern: P1,
21 starts_with_pattern: P2,
22 strip_pattern: P3,
23 ) -> Option<(usize, &'a str)>
24 where
25 P1: FnMut(char) -> bool,
26 P2: FnMut(char) -> bool,
27 P3: FnMut(char) -> bool,
28 {
29 if self.running_str.is_empty() {
30 return None;
31 }
32
33 let i = self.running_str.find(find_pattern)?;
34
35 let (value, rest) = self.running_str.split_at(i);
36
37 if value.is_empty() {
38 return None;
39 }
40
41 let rest_len = rest.len();
42
43 self.running_str = rest
44 .strip_prefix(starts_with_pattern)?
45 .trim_start_matches(strip_pattern);
46
47 let old_value_len = value.len();
48 let value = value.trim_start();
49
50 let leading_whitespace_size = value.len() - old_value_len;
51 let pos_start = self.idx + leading_whitespace_size;
52 self.idx += i + (rest_len - self.running_str.len());
53
54 Some((pos_start, value.trim_end()))
55 }
56
57 pub fn next_ident(&mut self) -> Option<(usize, &'a str)> {
58 self.next_token(
59 |c| !c.is_alphanumeric() && c != ',' && c != '_',
60 |c| c == '=',
61 |c| c.is_whitespace(),
62 )
63 }
64
65 pub fn next_value(&mut self) -> Option<(usize, &'a str)> {
66 self.next_token(
67 |c| c.is_whitespace() || c == ',' || c == '=',
68 |c| c.is_whitespace() || c == ',',
69 |c| c.is_whitespace() || c == ',',
70 )
71 .or_else(|| {
72 let rest = self.running_str;
73 self.running_str = "";
74 let pos_start = self.idx;
75 self.idx += rest.len();
76 Some((pos_start, rest))
77 })
78 }
79}