Skip to content

Commit fa2b4f7

Browse files
committed
time: avoid autofree parser temporaries
1 parent d5ca492 commit fa2b4f7

1 file changed

Lines changed: 76 additions & 46 deletions

File tree

‎vlib/time/date_time_parser.v‎

Lines changed: 76 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ mut:
77
current_pos_datetime int
88
}
99

10+
@[inline]
11+
fn (p &DateTimeParser) matches_at(chars string) bool {
12+
end := p.current_pos_datetime + chars.len
13+
if end > p.datetime.len {
14+
return false
15+
}
16+
for i in 0 .. chars.len {
17+
if p.datetime[p.current_pos_datetime + i] != chars[i] {
18+
return false
19+
}
20+
}
21+
return true
22+
}
23+
1024
fn (mut p DateTimeParser) next(length int) !string {
1125
if p.current_pos_datetime + length > p.datetime.len {
1226
return error('end of string')
@@ -24,38 +38,61 @@ fn (mut p DateTimeParser) peek(length int) !string {
2438
}
2539

2640
fn (mut p DateTimeParser) must_be_int(length int) !int {
27-
val := p.next(length)!
28-
if !val.contains_only('0123456789') {
29-
return error('expected int, found: ${val}')
41+
end := p.current_pos_datetime + length
42+
if end > p.datetime.len {
43+
return error('end of string')
44+
}
45+
mut val := 0
46+
for i in p.current_pos_datetime .. end {
47+
ch := p.datetime[i]
48+
if ch < `0` || ch > `9` {
49+
return error('expected int, found: ${p.datetime[p.current_pos_datetime..end]}')
50+
}
51+
val = val * 10 + int(ch - `0`)
3052
}
31-
return val.int()
53+
p.current_pos_datetime = end
54+
return val
3255
}
3356

3457
fn (mut p DateTimeParser) must_be_int_with_minimum_length(min int, max int, allow_leading_zero bool) !int {
35-
mut length := max + 1 - min
36-
mut val := ''
37-
for _ in 0 .. length {
38-
tok := p.peek(1) or { break }
39-
if !tok.contains_only('0123456789') {
58+
max_len := max + 1 - min
59+
start := p.current_pos_datetime
60+
mut end := start
61+
for _ in 0 .. max_len {
62+
if end >= p.datetime.len {
4063
break
4164
}
42-
p.next(1)!
43-
val += tok
65+
ch := p.datetime[end]
66+
if ch < `0` || ch > `9` {
67+
break
68+
}
69+
end++
4470
}
45-
if val.len < min {
46-
return error('expected int with a minimum length of ${min}, found: ${val.len}')
71+
if end - start < min {
72+
return error('expected int with a minimum length of ${min}, found: ${end - start}')
4773
}
48-
if !allow_leading_zero && val.starts_with('0') {
74+
if !allow_leading_zero && p.datetime[start] == `0` {
4975
return error('0 is not allowed for this format')
5076
}
51-
return val.int()
77+
mut val := 0
78+
for i in start .. end {
79+
val = val * 10 + int(p.datetime[i] - `0`)
80+
}
81+
p.current_pos_datetime = end
82+
return val
5283
}
5384

5485
fn (mut p DateTimeParser) must_be_string(must string) ! {
55-
val := p.next(must.len)!
56-
if val != must {
57-
return error('invalid string: "${val}"!="${must}" at: ${p.current_pos_datetime}')
86+
start := p.current_pos_datetime
87+
end := p.current_pos_datetime + must.len
88+
if end > p.datetime.len {
89+
return error('end of string')
90+
}
91+
if !p.matches_at(must) {
92+
p.current_pos_datetime = end
93+
return error('invalid string: "${p.datetime[start..end]}"!="${must}" at: ${p.current_pos_datetime}')
5894
}
95+
p.current_pos_datetime = end
5996
}
6097

6198
fn (mut p DateTimeParser) must_be_string_one_of(oneof []string) !string {
@@ -70,22 +107,19 @@ fn (mut p DateTimeParser) must_be_string_one_of(oneof []string) !string {
70107

71108
fn (mut p DateTimeParser) must_be_valid_month() !int {
72109
for v in long_months {
73-
if p.current_pos_datetime + v.len < p.datetime.len {
74-
month_name := p.datetime[p.current_pos_datetime..p.current_pos_datetime + v.len]
75-
if v == month_name {
76-
p.current_pos_datetime += v.len
77-
return long_months.index(month_name) + 1
78-
}
110+
if p.current_pos_datetime + v.len < p.datetime.len && p.matches_at(v) {
111+
p.current_pos_datetime += v.len
112+
return long_months.index(v) + 1
79113
}
80114
}
81115
return error_invalid_time(0, 'invalid month name, at: ${p.current_pos_datetime}')
82116
}
83117

84118
fn (mut p DateTimeParser) must_be_valid_three_letter_month() !int {
85119
if p.current_pos_datetime + 3 < p.datetime.len {
86-
letters := p.datetime[p.current_pos_datetime..p.current_pos_datetime + 3]
87120
for m := 1; m <= long_months.len; m++ {
88-
if months_string[(m - 1) * 3..m * 3] == letters {
121+
token := months_string[(m - 1) * 3..m * 3]
122+
if p.matches_at(token) {
89123
p.current_pos_datetime += 3
90124
return m
91125
}
@@ -96,22 +130,19 @@ fn (mut p DateTimeParser) must_be_valid_three_letter_month() !int {
96130

97131
fn (mut p DateTimeParser) must_be_valid_week_day() !string {
98132
for v in long_days {
99-
if p.current_pos_datetime + v.len < p.datetime.len {
100-
weekday := p.datetime[p.current_pos_datetime..p.current_pos_datetime + v.len]
101-
if v == weekday {
102-
p.current_pos_datetime += v.len
103-
return weekday
104-
}
133+
if p.current_pos_datetime + v.len < p.datetime.len && p.matches_at(v) {
134+
p.current_pos_datetime += v.len
135+
return v
105136
}
106137
}
107138
return error_invalid_time(0, 'invalid weekday, at: ${p.current_pos_datetime}')
108139
}
109140

110141
fn (mut p DateTimeParser) must_be_valid_two_letter_week_day() !int {
111142
if p.current_pos_datetime + 2 < p.datetime.len {
112-
letters := p.datetime[p.current_pos_datetime..p.current_pos_datetime + 2]
113143
for d := 1; d <= long_days.len; d++ {
114-
if days_string[(d - 1) * 3..d * 3 - 1] == letters {
144+
token := days_string[(d - 1) * 3..d * 3 - 1]
145+
if p.matches_at(token) {
115146
p.current_pos_datetime += 2
116147
return d
117148
}
@@ -122,9 +153,9 @@ fn (mut p DateTimeParser) must_be_valid_two_letter_week_day() !int {
122153

123154
fn (mut p DateTimeParser) must_be_valid_three_letter_week_day() !int {
124155
if p.current_pos_datetime + 3 < p.datetime.len {
125-
letters := p.datetime[p.current_pos_datetime..p.current_pos_datetime + 3]
126156
for d := 1; d <= long_days.len; d++ {
127-
if days_string[(d - 1) * 3..d * 3] == letters {
157+
token := days_string[(d - 1) * 3..d * 3]
158+
if p.matches_at(token) {
128159
p.current_pos_datetime += 3
129160
return d
130161
}
@@ -135,18 +166,17 @@ fn (mut p DateTimeParser) must_be_valid_three_letter_week_day() !int {
135166

136167
fn extract_tokens(s string) ![]string {
137168
mut tokens := []string{}
138-
mut current := ''
139-
for r in s {
140-
if current.contains_only(r.ascii_str()) || current == '' {
141-
current += r.ascii_str()
142-
} else {
143-
tokens << current
144-
current = r.ascii_str()
145-
}
169+
if s.len == 0 {
170+
return tokens
146171
}
147-
if current != '' {
148-
tokens << current
172+
mut start := 0
173+
for i := 1; i < s.len; i++ {
174+
if s[i] != s[i - 1] {
175+
tokens << s[start..i]
176+
start = i
177+
}
149178
}
179+
tokens << s[start..s.len]
150180
return tokens
151181
}
152182

0 commit comments

Comments
 (0)