Skip to content

Commit

Permalink
add more functions
Browse files Browse the repository at this point in the history
  • Loading branch information
kbkpbot committed Mar 6, 2025
1 parent 9789151 commit b9b4389
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 3 deletions.
78 changes: 75 additions & 3 deletions vlib/strings/textscanner/textscanner.v
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ pub fn (mut ss TextScanner) skip() {
@[inline]
pub fn (mut ss TextScanner) skip_n(n int) {
ss.pos += n
if ss.pos > ss.ilen {
if ss.pos < 0 {
ss.pos = 0
} else if ss.pos > ss.ilen {
ss.pos = ss.ilen
}
}
Expand Down Expand Up @@ -126,8 +128,7 @@ pub fn (mut ss TextScanner) back_n(n int) {
ss.pos -= n
if ss.pos < 0 {
ss.pos = 0
}
if ss.pos > ss.ilen {
} else if ss.pos > ss.ilen {
ss.pos = ss.ilen
}
}
Expand Down Expand Up @@ -185,3 +186,74 @@ pub fn (mut ss TextScanner) skip_whitespace() {
ss.next()
}
}

// next_line advances the scanner’s position to the start of
// the next line, and return the line.
// Returns true if successful, or false if the end of the input
// is reached.
@[direct_array_access]
pub fn (mut ss TextScanner) next_line() (string, bool) {
if ss.pos == ss.ilen {
return '', false
}
start := ss.pos
mut end := ss.ilen
for i in start .. ss.ilen {
if ss.input[i] == `\n` || ss.input[i] == `\r` {
end = i
break
}
}

if end >= ss.ilen {
ss.pos = ss.ilen
return ss.input[start..], false
}
if ss.input[end] == `\r` {
// check next char is `\n`
if end + 1 < ss.ilen && ss.input[end + 1] == `\n` {
ss.pos = end + 2
} else {
ss.pos = end + 1
}
} else {
ss.pos = end + 1
}
if ss.pos > ss.ilen {
ss.pos = ss.ilen
}
return ss.input[start..end], true
}

// read_until reads characters from the current scanning position
// until a delimiter (from the provided list `delimiters`) is encountered.
// The returned string includes all characters from the starting
// position up to (but ​not​ including) the first encountered
// delimiter. The scanner's position is advanced to the character
// immediately after the delimiter (or to the end of the input if
// no delimiter is found).
@[direct_array_access]
pub fn (mut ss TextScanner) read_until(delimiters []rune) !string {
if delimiters.len == 0 {
return error('delimiters cannot be empty')
}
if ss.pos >= ss.ilen {
return error('already at EOF')
}
start := ss.pos
mut current_pos := ss.pos
for {
if current_pos >= ss.ilen {
break
}
r := ss.input[current_pos]
if r in delimiters {
end := current_pos
ss.pos = end + 1
return ss.input[start..end]
}
current_pos += 1
}
ss.pos = ss.ilen
return ss.input[start..]
}
54 changes: 54 additions & 0 deletions vlib/strings/textscanner/textscanner_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ fn test_skip_n() {
assert s.peek() == `a`
s.skip_n(4)
assert s.peek() == -1

s.reset()
assert s.peek() == `a`
s.skip_n(-3)
assert s.peek() == `a`
}

fn test_peek() {
Expand Down Expand Up @@ -214,3 +219,52 @@ fn test_peek_n_u8() {
assert s.peek_n_u8(3) == 0
assert s.peek_n_u8(4) == 0
}

fn test_next_line() {
mut s := textscanner.new('abc\r\n123\n\n8')
line1, end1 := s.next_line()
assert line1 == 'abc'
assert end1 == true

line2, end2 := s.next_line()
assert line2 == '123'
assert end2 == true

line3, end3 := s.next_line()
assert line3 == ''
assert end3 == true

line4, end4 := s.next_line()
assert line4 == '8'
assert end4 == false

line5, end5 := s.next_line()
assert line5 == ''
assert end5 == false
}

fn test_read_until() {
mut s := textscanner.new('abc\r\n12|3#')
t1 := s.read_until([`|`]) or { panic(err) }
assert t1 == 'abc\r\n12'

t2 := s.read_until([`#`]) or { panic(err) }
assert t2 == '3'
t3 := s.read_until([`#`]) or {
assert err.msg() == 'already at EOF'
'not exist'
}
assert t3 == 'not exist'

mut ss := textscanner.new('abc\r\n12|3#')
tt1 := ss.read_until([`|`, `#`]) or { panic(err) }
assert tt1 == 'abc\r\n12'

tt2 := ss.read_until([`|`, `#`]) or { panic(err) }
assert tt2 == '3'
tt3 := ss.read_until([`|`, `#`]) or {
assert err.msg() == 'already at EOF'
'not exist'
}
assert tt3 == 'not exist'
}

0 comments on commit b9b4389

Please sign in to comment.