129 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			V
		
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			V
		
	
	
module strings
 | 
						|
 | 
						|
// import rand
 | 
						|
// random returns a random string with `n` characters
 | 
						|
/*
 | 
						|
pub fn random(n int) string {
 | 
						|
	buf := vmalloc(n)
 | 
						|
	for i in 0..n {
 | 
						|
		buf[i] = rand.next()
 | 
						|
	}
 | 
						|
	return tos(buf)
 | 
						|
}
 | 
						|
*/
 | 
						|
 | 
						|
// find_between_pair_byte returns the string found between the pair of marks defined
 | 
						|
// by `start` and `end`.
 | 
						|
// As opposed to the `find_between`, `all_after*`, `all_before*` methods defined on the
 | 
						|
// `string` type, this function can extract content between *nested* marks in `input`.
 | 
						|
// If `start` and `end` marks are nested in `input`, the characters
 | 
						|
// between the *outermost* mark pair is returned. It is expected that `start` and `end`
 | 
						|
// marks are *balanced*, meaning that the amount of `start` marks equal the
 | 
						|
// amount of `end` marks in the `input`. An empty string is returned otherwise.
 | 
						|
// Using two identical marks as `start` and `end` results in undefined output behavior.
 | 
						|
// find_between_pair_byte is the fastest in the find_between_pair_* family of functions.
 | 
						|
// Example: assert strings.find_between_pair_byte('(V) (NOT V)',`(`,`)`) == 'V'
 | 
						|
// Example: assert strings.find_between_pair_byte('s {X{Y}} s',`{`,`}`) == 'X{Y}'
 | 
						|
pub fn find_between_pair_byte(input string, start byte, end byte) string {
 | 
						|
	mut marks := 0
 | 
						|
	mut start_index := -1
 | 
						|
	for i, b in input {
 | 
						|
		if b == start {
 | 
						|
			if start_index == -1 {
 | 
						|
				start_index = i + 1
 | 
						|
			}
 | 
						|
			marks++
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if start_index > 0 {
 | 
						|
			if b == end {
 | 
						|
				marks--
 | 
						|
				if marks == 0 {
 | 
						|
					return input[start_index..i]
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return ''
 | 
						|
}
 | 
						|
 | 
						|
// find_between_pair_rune returns the string found between the pair of marks defined
 | 
						|
// by `start` and `end`.
 | 
						|
// As opposed to the `find_between`, `all_after*`, `all_before*` methods defined on the
 | 
						|
// `string` type, this function can extract content between *nested* marks in `input`.
 | 
						|
// If `start` and `end` marks are nested in `input`, the characters
 | 
						|
// between the *outermost* mark pair is returned. It is expected that `start` and `end`
 | 
						|
// marks are *balanced*, meaning that the amount of `start` marks equal the
 | 
						|
// amount of `end` marks in the `input`. An empty string is returned otherwise.
 | 
						|
// Using two identical marks as `start` and `end` results in undefined output behavior.
 | 
						|
// find_between_pair_rune is inbetween the fastest and slowest in the find_between_pair_* family of functions.
 | 
						|
// Example: assert strings.find_between_pair_rune('(V) (NOT V)',`(`,`)`) == 'V'
 | 
						|
// Example: assert strings.find_between_pair_rune('s {X{Y}} s',`{`,`}`) == 'X{Y}'
 | 
						|
pub fn find_between_pair_rune(input string, start rune, end rune) string {
 | 
						|
	mut marks := 0
 | 
						|
	mut start_index := -1
 | 
						|
	runes := input.runes()
 | 
						|
	for i, r in runes {
 | 
						|
		if r == start {
 | 
						|
			if start_index == -1 {
 | 
						|
				start_index = i + 1
 | 
						|
			}
 | 
						|
			marks++
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if start_index > 0 {
 | 
						|
			if r == end {
 | 
						|
				marks--
 | 
						|
				if marks == 0 {
 | 
						|
					return runes[start_index..i].string()
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return ''
 | 
						|
}
 | 
						|
 | 
						|
// find_between_pair_string returns the string found between the pair of marks defined
 | 
						|
// by `start` and `end`.
 | 
						|
// As opposed to the `find_between`, `all_after*`, `all_before*` methods defined on the
 | 
						|
// `string` type, this function can extract content between *nested* marks in `input`.
 | 
						|
// If `start` and `end` marks are nested in `input`, the characters
 | 
						|
// between the *outermost* mark pair is returned. It is expected that `start` and `end`
 | 
						|
// marks are *balanced*, meaning that the amount of `start` marks equal the
 | 
						|
// amount of `end` marks in the `input`. An empty string is returned otherwise.
 | 
						|
// Using two identical marks as `start` and `end` results in undefined output behavior.
 | 
						|
// find_between_pair_string is the slowest in the find_between_pair_* function family.
 | 
						|
// Example: assert strings.find_between_pair_string('/*V*/ /*NOT V*/','/*','*/') == 'V'
 | 
						|
// Example: assert strings.find_between_pair_string('s {{X{{Y}}}} s','{{','}}') == 'X{{Y}}'
 | 
						|
pub fn find_between_pair_string(input string, start string, end string) string {
 | 
						|
	mut start_index := -1
 | 
						|
	mut marks := 0
 | 
						|
	start_runes := start.runes()
 | 
						|
	end_runes := end.runes()
 | 
						|
	runes := input.runes()
 | 
						|
	mut i := 0
 | 
						|
	for ; i < runes.len; i++ {
 | 
						|
		start_slice := runes#[i..i + start_runes.len]
 | 
						|
		if start_slice == start_runes {
 | 
						|
			i = i + start_runes.len - 1
 | 
						|
			if start_index < 0 {
 | 
						|
				start_index = i + 1
 | 
						|
			}
 | 
						|
			marks++
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if start_index > 0 {
 | 
						|
			end_slice := runes#[i..i + end_runes.len]
 | 
						|
			if end_slice == end_runes {
 | 
						|
				marks--
 | 
						|
				if marks == 0 {
 | 
						|
					return runes[start_index..i].string()
 | 
						|
				}
 | 
						|
				i = i + end_runes.len - 1
 | 
						|
				continue
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return ''
 | 
						|
}
 |