Skip to main content

[text]

# =============================================================================
# TEXT (FRAMEWORK FILE) VERSION 2026-04-04
# =============================================================================
# This file provides basic operations for working with text strings.
# If your program doesn't need these functions, you could delete this file.

class text
view var _chars: char[]
view var length: int

# ---------------------------------------------------------------------------
constructor()
._chars <- new char[](4)
end constructor

# ---------------------------------------------------------------------------
func _grow_if_needed(new_size: int)
var size: int
size <- ._chars.size

if new_size > size then
# round up
new_size <- math::bit_and(new_size + 7, math::bit_not(7))

var new_chars: char[]
new_chars <- new char[](new_size)
new_chars.copy_from(0, ._chars, 0, .length)

._chars <- new_chars
end if
end func

# ---------------------------------------------------------------------------
func clear()
if ._chars.size > 4
do ._chars <- new char[](4)

0 -> .length
end func

# ---------------------------------------------------------------------------
func get[](i: int): char
if i < 0 or i >= .length then
kernel::fail("out of bounds")
end if

var result: char
result <- unsafe(._chars)[i]
return result
end func

# ---------------------------------------------------------------------------
func set[](i: int, value: char)
if i < 0 or i >= .length then
kernel::fail("out of bounds")
end if

unsafe(._chars)[i] <- value
end func

# ---------------------------------------------------------------------------
func write(s: string)
._write(s, s.size)
end func

# ---------------------------------------------------------------------------
func write_text(text: text)
._write(text._chars, text.length)
end func

# ---------------------------------------------------------------------------
func _write(chars: char[], size: int)
var length: int, new_length: int
length <- .length
new_length <- length + size
._grow_if_needed(new_length)
._chars.copy_from(.length, chars, 0, size)
.length <- new_length
end func

# ---------------------------------------------------------------------------
func write_int(n: int)
var c: int
n -> c

# To handle MIN_INT properly, the trick is to use negative math
if n > 0 then
-c -> c
end if

# Extract digits from right-to-left, putting them into scratch_bytes[]
var i: int, digit: int
0 -> i
loop
-(c % 10) -> digit
to_byte(48 + digit) -> unsafe(kernel::scratch_bytes)[i]

c / 10 -> c
if c = 0
do drop

i + 1 -> i
end loop

var target_index: int
target_index <- .length

var new_length: int
new_length <- target_index + i + 1
if n < 0 then
new_length <- new_length + 1 # minus sign
end if

._grow_if_needed(new_length)
.length <- new_length

if n < 0 then
._chars[target_index] <- '-'
target_index <- target_index + 1
end if

# Now read scratch_bytes[] in reverse order, so digits are left-to-right
loop
._chars[target_index] <- kernel::scratch_bytes[i]
target_index <- target_index + 1

i <- i - 1
if i < 0
do drop
end loop
end func

# ---------------------------------------------------------------------------
func write_char(c: char)
var length: int
length <- .length
var new_length: int
new_length <- length + 1
._grow_if_needed(new_length)
unsafe(._chars)[length] <- c
.length <- new_length
end func

# ---------------------------------------------------------------------------
func to_string(): string
var result: char[]
result <- new char[](.length)
result.copy_from(0, ._chars, 0, .length)
return result
end func

# ---------------------------------------------------------------------------
func compare_string(s: string): int
return kernel::compare_strings(._chars, .length, s, s.size)
end func

# ---------------------------------------------------------------------------
func compare_text(text: text): int
return kernel::compare_strings(._chars, .length, text._chars, text.length)
end func
end class

module text
func compare(a: string, b: string): int
return kernel::compare_strings(a, a.size, b, b.size)
end func

func index_of(string: string, substring: string): int
return kernel::index_of_string(string, string.size, substring, substring.size)
end func
end module