Ctrl K
ComunidadGuías…

vlib/bytes/bytes.v

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Module bytes provides byte-oriented manipulation of raw []u8 data.
// Returned arrays own their data; no function decodes or normalizes UTF-8.
module bytes

const max_len = 2147483647

// compare returns -1 if a < b, 0 if equal, 1 if a > b (lexicographic).
pub fn compare(a []u8, b []u8) int {
	n := if a.len < b.len { a.len } else { b.len }
	for i in 0 .. n {
		if a[i] < b[i] {
			return -1
		}
		if a[i] > b[i] {
			return 1
		}
	}
	if a.len < b.len {
		return -1
	}
	if a.len > b.len {
		return 1
	}
	return 0
}

// equal reports whether a and b are the same length and contain the same bytes.
pub fn equal(a []u8, b []u8) bool {
	if a.len != b.len {
		return false
	}
	for i in 0 .. a.len {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}

// contains reports whether subslice is within b.
pub fn contains(b []u8, subslice []u8) bool {
	return index(b, subslice) >= 0
}

// count counts non-overlapping instances of sep in s.
// An empty sep matches at every byte boundary, including both ends.
// It panics if the count does not fit in an int.
pub fn count(s []u8, sep []u8) int {
	if sep.len == 0 {
		if s.len == max_len {
			panic('bytes.count: count overflow')
		}
		return s.len + 1
	}
	if sep.len > s.len {
		return 0
	}
	mut n := 0
	mut i := 0
	for {
		idx := index(s[i..], sep)
		if idx < 0 {
			break
		}
		n++
		i += idx + sep.len
		if i > s.len {
			break
		}
	}
	return n
}

// has_prefix reports whether s begins with prefix.
pub fn has_prefix(s []u8, prefix []u8) bool {
	if prefix.len > s.len {
		return false
	}
	for i in 0 .. prefix.len {
		if s[i] != prefix[i] {
			return false
		}
	}
	return true
}

// has_suffix reports whether s ends with suffix.
pub fn has_suffix(s []u8, suffix []u8) bool {
	if suffix.len > s.len {
		return false
	}
	start := s.len - suffix.len
	for i in 0 .. suffix.len {
		if s[start + i] != suffix[i] {
			return false
		}
	}
	return true
}

// index returns the index of the first occurrence of sep in s, or -1.
pub fn index(s []u8, sep []u8) int {
	if sep.len == 0 {
		return 0
	}
	if sep.len > s.len {
		return -1
	}
	for i in 0 .. s.len - sep.len + 1 {
		mut ok := true
		for j in 0 .. sep.len {
			if s[i + j] != sep[j] {
				ok = false
				break
			}
		}
		if ok {
			return i
		}
	}
	return -1
}

// index_byte returns the index of the first occurrence of c in s, or -1.
pub fn index_byte(s []u8, c u8) int {
	for i, b in s {
		if b == c {
			return i
		}
	}
	return -1
}

// join concatenates elems with sep between them into a new array.
// It panics if the result length does not fit in an int.
pub fn join(elems [][]u8, sep []u8) []u8 {
	mut length := i64(0)
	for i, e in elems {
		length += e.len
		if i > 0 {
			length += sep.len
		}
		if length > max_len {
			panic('bytes.join: length overflow')
		}
	}
	mut out := []u8{cap: int(length)}
	for i, e in elems {
		if i > 0 {
			out << sep
		}
		out << e
	}
	return out
}

// repeat returns a new array with b repeated count times.
// A nonpositive count returns an empty array.
// It panics if the result length does not fit in an int.
pub fn repeat(b []u8, count int) []u8 {
	if count <= 0 || b.len == 0 {
		return []u8{}
	}
	if count > max_len / b.len {
		panic('bytes.repeat: length overflow')
	}
	mut out := []u8{cap: b.len * count}
	for _ in 0 .. count {
		out << b
	}
	return out
}

// replace returns a copy of s with the first n (or all if n < 0) non-overlapping
// instances of old replaced by new.
// An empty old matches at every byte boundary, including both ends.
// It panics if the result length does not fit in an int.
pub fn replace(s []u8, old []u8, new []u8, n int) []u8 {
	if n == 0 || equal(old, new) {
		return s.clone()
	}
	mut replacements := if old.len == 0 { i64(s.len) + 1 } else { i64(count(s, old)) }
	if n > 0 && replacements > n {
		replacements = n
	}
	if replacements == 0 {
		return s.clone()
	}
	length := i64(s.len) + replacements * (i64(new.len) - old.len)
	if length > max_len {
		panic('bytes.replace: length overflow')
	}
	mut out := []u8{cap: int(length)}
	if old.len == 0 {
		for i, b in s {
			if i64(i) < replacements {
				out << new
			}
			out << b
		}
		if replacements > s.len {
			out << new
		}
		return out
	}
	mut i := 0
	mut done := 0
	for i < s.len {
		if i64(done) < replacements && old.len <= s.len - i {
			mut ok := true
			for j in 0 .. old.len {
				if s[i + j] != old[j] {
					ok = false
					break
				}
			}
			if ok {
				out << new
				i += old.len
				done++
				continue
			}
		}
		out << s[i]
		i++
	}
	return out
}

// split returns copies of the parts of s separated by sep.
// An empty sep splits into individual bytes; an empty s then yields no parts.
pub fn split(s []u8, sep []u8) [][]u8 {
	return split_n(s, sep, -1)
}

// split_n returns at most n copied parts, with the unsplit remainder in the last part.
// A zero n returns no parts; a negative n returns all parts.
// An empty sep splits into individual bytes; an empty s then yields no parts.
pub fn split_n(s []u8, sep []u8, n int) [][]u8 {
	if n == 0 {
		return [][]u8{}
	}
	if sep.len == 0 {
		mut out := [][]u8{}
		for i, b in s {
			if n > 0 && out.len == n - 1 {
				out << s[i..].clone()
				break
			}
			out << [b]
		}
		return out
	}
	mut out := [][]u8{}
	mut start := 0
	mut done := 0
	for {
		if n > 0 && done >= n - 1 {
			break
		}
		idx := index(s[start..], sep)
		if idx < 0 {
			break
		}
		out << s[start..start + idx].clone()
		start += idx + sep.len
		done++
		if start > s.len {
			break
		}
	}
	out << s[start..].clone()
	return out
}

// to_lower returns a copy with ASCII letters lowercased.
pub fn to_lower(s []u8) []u8 {
	mut out := s.clone()
	for i, b in out {
		if b >= `A` && b <= `Z` {
			out[i] = b + 32
		}
	}
	return out
}

// to_upper returns a copy with ASCII letters uppercased.
pub fn to_upper(s []u8) []u8 {
	mut out := s.clone()
	for i, b in out {
		if b >= `a` && b <= `z` {
			out[i] = b - 32
		}
	}
	return out
}

// trim_space trims leading/trailing ASCII whitespace.
pub fn trim_space(s []u8) []u8 {
	mut start := 0
	for start < s.len && is_space_byte(s[start]) {
		start++
	}
	mut end := s.len
	for end > start && is_space_byte(s[end - 1]) {
		end--
	}
	return s[start..end].clone()
}

fn is_space_byte(b u8) bool {
	return b == ` ` || b == `\t` || b == `\n` || b == `\r` || b == `\f` || b == `\v`
}

// trim removes leading/trailing bytes that are in cutset.
pub fn trim(s []u8, cutset []u8) []u8 {
	mut start := 0
	for start < s.len && in_cutset(s[start], cutset) {
		start++
	}
	mut end := s.len
	for end > start && in_cutset(s[end - 1], cutset) {
		end--
	}
	return s[start..end].clone()
}

fn in_cutset(b u8, cutset []u8) bool {
	for c in cutset {
		if c == b {
			return true
		}
	}
	return false
}

// trim_prefix removes prefix from s if present.
pub fn trim_prefix(s []u8, prefix []u8) []u8 {
	if has_prefix(s, prefix) {
		return s[prefix.len..].clone()
	}
	return s.clone()
}

// trim_suffix removes suffix from s if present.
pub fn trim_suffix(s []u8, suffix []u8) []u8 {
	if has_suffix(s, suffix) {
		return s[..s.len - suffix.len].clone()
	}
	return s.clone()
}

// clone returns a copy of b.
pub fn clone(b []u8) []u8 {
	return b.clone()
}