mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-20 04:35:00 -07:00
Fix array bounds checking
This commit is contained in:
+2
-5
@@ -1,9 +1,6 @@
|
||||
#load "basic.odin"
|
||||
|
||||
main :: proc() {
|
||||
str := "Hellope"
|
||||
|
||||
println(str, true, 6.28)
|
||||
|
||||
println([4]int{1, 2, 3, 4})
|
||||
println("% % % %", "Hellope", true, 6.28, [4]int{1, 2, 3, 4})
|
||||
println("%0 %1 %0", "Hellope", 34)
|
||||
}
|
||||
|
||||
+10
-10
@@ -41,18 +41,18 @@ File_Standard :: type enum {
|
||||
COUNT,
|
||||
}
|
||||
|
||||
__std_file_set := false;
|
||||
__std_files: [File_Standard.COUNT as int]File;
|
||||
|
||||
__std_files := __set_file_standards();
|
||||
|
||||
__set_file_standards :: proc() -> [File_Standard.COUNT as int]File {
|
||||
return [File_Standard.COUNT as int]File{
|
||||
File{handle = GetStdHandle(STD_INPUT_HANDLE)},
|
||||
File{handle = GetStdHandle(STD_OUTPUT_HANDLE)},
|
||||
File{handle = GetStdHandle(STD_ERROR_HANDLE)},
|
||||
}
|
||||
}
|
||||
|
||||
file_get_standard :: proc(std: File_Standard) -> ^File {
|
||||
// using File_Standard;
|
||||
if (!__std_file_set) {
|
||||
using File_Standard
|
||||
__std_files[INPUT] .handle = GetStdHandle(STD_INPUT_HANDLE)
|
||||
__std_files[OUTPUT].handle = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
__std_files[ERROR] .handle = GetStdHandle(STD_ERROR_HANDLE)
|
||||
__std_file_set = true
|
||||
}
|
||||
return ^__std_files[std]
|
||||
}
|
||||
|
||||
|
||||
+97
-33
@@ -2,7 +2,7 @@
|
||||
#load "win32.odin"
|
||||
#load "file.odin"
|
||||
|
||||
print_string_to_buffer :: proc(buf: ^[]byte, s: string) {
|
||||
print_byte_buffer :: proc(buf: ^[]byte, b: []byte) {
|
||||
// NOTE(bill): This is quite a hack
|
||||
// TODO(bill): Should I allow the raw editing of a slice by exposing its
|
||||
// internal members?
|
||||
@@ -14,13 +14,20 @@ print_string_to_buffer :: proc(buf: ^[]byte, s: string) {
|
||||
|
||||
slice := buf as ^Raw_Bytes
|
||||
if slice.len < slice.cap {
|
||||
n := min(slice.cap-slice.len, len(s))
|
||||
offset := ptr_offset(slice.data, slice.len)
|
||||
memory_copy(offset, ^s[0], n)
|
||||
slice.len += n
|
||||
n := min(slice.cap-slice.len, len(b))
|
||||
if n > 0 {
|
||||
offset := ptr_offset(slice.data, slice.len)
|
||||
memory_copy(offset, ^b[0], n)
|
||||
slice.len += n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print_string_to_buffer :: proc(buf: ^[]byte, s: string) {
|
||||
print_byte_buffer(buf, s as []byte)
|
||||
}
|
||||
|
||||
|
||||
byte_reverse :: proc(b: []byte) {
|
||||
n := len(b)
|
||||
for i := 0; i < n/2; i++ {
|
||||
@@ -357,43 +364,100 @@ type_info_is_string :: proc(info: ^Type_Info) -> bool {
|
||||
return false
|
||||
}
|
||||
|
||||
print_to_buffer :: proc(buf: ^[]byte, args: ..any) {
|
||||
prev_string := false
|
||||
for i := 0; i < len(args); i++ {
|
||||
arg := args[i]
|
||||
is_string := arg.data != null && type_info_is_string(arg.type_info)
|
||||
if i > 0 && !is_string && !prev_string {
|
||||
// Add space between two non-string arguments
|
||||
print_space_to_buffer(buf)
|
||||
}
|
||||
print_any_to_buffer(buf, arg)
|
||||
prev_string = is_string
|
||||
|
||||
print_to_buffer :: proc(buf: ^[]byte, fmt: string, args: ..any) {
|
||||
is_digit :: proc(r: rune) -> bool #inline {
|
||||
return r >= #rune "0" && r <= #rune "9"
|
||||
}
|
||||
}
|
||||
|
||||
println_to_buffer :: proc(buf: ^[]byte, args: ..any) {
|
||||
for i := 0; i < len(args); i++ {
|
||||
arg := args[i]
|
||||
if i > 0 {
|
||||
print_space_to_buffer(buf)
|
||||
parse_int :: proc(s: string, offset: int) -> (int, int) {
|
||||
result := 0
|
||||
|
||||
for ; offset < len(s); offset++ {
|
||||
c := s[offset] as rune
|
||||
if !is_digit(c) {
|
||||
break
|
||||
}
|
||||
|
||||
result *= 10
|
||||
result += (c - #rune "0") as int
|
||||
}
|
||||
print_any_to_buffer(buf, arg)
|
||||
|
||||
return result, offset
|
||||
}
|
||||
print_nl_to_buffer(buf)
|
||||
|
||||
prev := 0
|
||||
implicit_index := 0
|
||||
|
||||
for i := 0; i < len(fmt); i++ {
|
||||
r := fmt[i] as rune
|
||||
|
||||
if r != #rune "%" {
|
||||
continue
|
||||
}
|
||||
|
||||
print_string_to_buffer(buf, fmt[prev:i])
|
||||
i++ // Skip %
|
||||
if i >= len(fmt) {
|
||||
return
|
||||
}
|
||||
|
||||
next := fmt[i] as rune
|
||||
if next == #rune "%" {
|
||||
print_string_to_buffer(buf, "%")
|
||||
i++
|
||||
prev = i
|
||||
continue
|
||||
}
|
||||
|
||||
index := implicit_index
|
||||
set_prev := true
|
||||
|
||||
if is_digit(next) {
|
||||
index, i = parse_int(fmt, i)
|
||||
}
|
||||
|
||||
if 0 <= index && index < len(args) {
|
||||
print_any_to_buffer(buf, args[index])
|
||||
implicit_index = index+1
|
||||
} else {
|
||||
// TODO(bill): Error check index out bounds
|
||||
print_string_to_buffer(buf, "<invalid>")
|
||||
}
|
||||
|
||||
prev = i
|
||||
}
|
||||
|
||||
print_string_to_buffer(buf, fmt[prev:])
|
||||
}
|
||||
|
||||
PRINT_BUF_SIZE :: 1<<12
|
||||
|
||||
print :: proc(args: ..any) {
|
||||
data: [4096]byte
|
||||
print_to_file :: proc(f: ^File, fmt: string, args: ..any) {
|
||||
data: [PRINT_BUF_SIZE]byte
|
||||
buf := data[:0]
|
||||
print_to_buffer(^buf, ..args)
|
||||
file_write(file_get_standard(File_Standard.OUTPUT), buf)
|
||||
print_to_buffer(^buf, fmt, ..args)
|
||||
file_write(f, buf)
|
||||
}
|
||||
|
||||
|
||||
println :: proc(args: ..any) {
|
||||
data: [4096]byte
|
||||
println_to_file :: proc(f: ^File, fmt: string, args: ..any) {
|
||||
data: [PRINT_BUF_SIZE]byte
|
||||
buf := data[:0]
|
||||
println_to_buffer(^buf, ..args)
|
||||
file_write(file_get_standard(File_Standard.OUTPUT), buf)
|
||||
print_to_buffer(^buf, fmt, ..args)
|
||||
print_nl_to_buffer(^buf)
|
||||
file_write(f, buf)
|
||||
}
|
||||
|
||||
|
||||
print :: proc(fmt: string, args: ..any) {
|
||||
print_to_file(file_get_standard(File_Standard.OUTPUT), fmt, ..args)
|
||||
}
|
||||
print_err :: proc(fmt: string, args: ..any) {
|
||||
print_to_file(file_get_standard(File_Standard.ERROR), fmt, ..args)
|
||||
}
|
||||
println :: proc(fmt: string, args: ..any) {
|
||||
println_to_file(file_get_standard(File_Standard.OUTPUT), fmt, ..args)
|
||||
}
|
||||
println_err :: proc(fmt: string, args: ..any) {
|
||||
println_to_file(file_get_standard(File_Standard.ERROR), fmt, ..args)
|
||||
}
|
||||
|
||||
+12
-6
@@ -290,17 +290,23 @@ __assert :: proc(msg: string) {
|
||||
__debug_trap()
|
||||
}
|
||||
|
||||
__abc_error :: proc(file: string, line, column: int, index, len: int) {
|
||||
print(file, "(", line, ":", line, ") Index `", index, "` is of bounds range [0, ", len, ")\n")
|
||||
__bounds_check_error :: proc(file: string, line, column: int,
|
||||
index, count: int) {
|
||||
println_err("%(%:%) Index % is out of bounds range [0, %)",
|
||||
file, line, column, index, count)
|
||||
__debug_trap()
|
||||
}
|
||||
|
||||
__slice_expr_error :: proc(file: string, line, column: int, low, high, max: int) {
|
||||
print(file, "(", line, ":", line, ") Invalid slice indices: [", low, ":", high, ":", max, "]\n")
|
||||
__slice_expr_error :: proc(file: string, line, column: int,
|
||||
low, high, max: int) {
|
||||
print_err("%(%:%) Invalid slice indices: [%:%:%]\n",
|
||||
file, line, column, low, high, max)
|
||||
__debug_trap()
|
||||
}
|
||||
__substring_expr_error :: proc(file: string, line, column: int, low, high: int) {
|
||||
print(file, "(", line, ":", line, ") Invalid substring indices: [", low, ":", high, "]\n")
|
||||
__substring_expr_error :: proc(file: string, line, column: int,
|
||||
low, high: int) {
|
||||
print_err("%(%:%) Invalid substring indices: [%:%:%]\n",
|
||||
file, line, column, low, high)
|
||||
__debug_trap()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user