From: Brendan Hansen Date: Sat, 29 May 2021 03:20:55 +0000 (-0500) Subject: getting rid of uses of string.builder, string.reader X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=9ba5b11ecf8b5432bb491ffae570c8214efe11b0;p=onyx.git getting rid of uses of string.builder, string.reader --- diff --git a/core/alloc/arena.onyx b/core/alloc/arena.onyx index df6b90b2..46665d6a 100644 --- a/core/alloc/arena.onyx +++ b/core/alloc/arena.onyx @@ -30,7 +30,7 @@ arena_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, alloc_arena := cast(^ArenaState) data; if aa == AllocationAction.Alloc { - // NOTE: An allocation of this size does not fit into a single arena. + // An allocation of this size does not fit into a single arena. if size > alloc_arena.arena_size - sizeof rawptr { return null; } @@ -59,8 +59,10 @@ arena_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, return null; } -// NOTE: `arena_size` must be at least 4 +@Note // `arena_size` must be at least 4 make :: (backing: Allocator, arena_size: u32) -> ArenaState { + assert(arena_size >= 4, "Arena size was expected to be at least 4 bytes."); + initial_arena := cast(^Arena) raw_alloc(backing, arena_size); initial_arena.next = null; diff --git a/core/alloc/pool.onyx b/core/alloc/pool.onyx index b32c29bd..1bf8504c 100644 --- a/core/alloc/pool.onyx +++ b/core/alloc/pool.onyx @@ -46,7 +46,9 @@ pool_alloc :: (pool: ^PoolAllocator($Elem)) -> ^Elem { } pool_free :: (pool: ^PoolAllocator($Elem), elem: ^Elem) { - // TODO: Maybe add a check that the elem pointer is actually in the buffer?? + @TODO + // Add a check that the elem pointer is actually in the buffer?? + *(cast(^rawptr) elem) = cast(rawptr) pool.first_free; pool.first_free = elem; } diff --git a/core/builtin.onyx b/core/builtin.onyx index 2ea67a66..f252db25 100644 --- a/core/builtin.onyx +++ b/core/builtin.onyx @@ -8,7 +8,8 @@ package builtin str :: #type []u8; cstr :: #type ^u8; -// NOTE: Because of many implementation details, all fields of this +@Note +// Because of many implementation details, all fields of this // struct are required to be i32's. range :: struct { low : i32; @@ -39,7 +40,7 @@ vararg_get :: proc { } } -// HACK: NullProcHack +@NullProcHack null_proc :: proc () #null --- null :: cast(rawptr) 0; diff --git a/core/container/array.onyx b/core/container/array.onyx index 98ca56b8..c1651dc4 100644 --- a/core/container/array.onyx +++ b/core/container/array.onyx @@ -184,7 +184,7 @@ sort :: (arr: ^[..] $T, cmp: (T, T) -> i32) { x := arr.data[i]; j := i - 1; - // NOTE: This is written this way because '&&' does not short circuit right now. + @ShortCircuitLogicalOps // This is written this way because '&&' does not short circuit right now. while j >= 0 { if cmp(arr.data[j], x) > 0 { arr.data[j + 1] = arr.data[j]; diff --git a/core/container/list.onyx b/core/container/list.onyx index d4bd0658..a831b2a2 100644 --- a/core/container/list.onyx +++ b/core/container/list.onyx @@ -1,5 +1,7 @@ package core.list +use package core.intrinsics.onyx { __zero_value } + ListElem :: struct (T: type_expr) { next: ^ListElem(T) = null; prev: ^ListElem(T) = null; @@ -39,7 +41,7 @@ push_begin :: (list: ^List($T), x: T) { if list.last == null do list.last = new_elem; } -pop_end :: (list: ^List($T), default: T = 0) -> T { +pop_end :: (list: ^List($T), default: T = __zero_value(T)) -> T { if list.last == null do return default; end := list.last; @@ -50,7 +52,7 @@ pop_end :: (list: ^List($T), default: T = 0) -> T { return end.data; } -pop_begin :: (list: ^List($T), default: T = 0) -> T { +pop_begin :: (list: ^List($T), default: T = __zero_value(T)) -> T { if list.last == null do return default; begin := list.first; @@ -71,6 +73,23 @@ contains :: (list: ^List($T), x: T) -> bool { return false; } +fold :: (list: ^List($T), init: $R, f: (T, R) -> R) -> R { + val := init; + + link := list.first; + while link != null { + val = f(link.data, val); + link = link.next; + } + + return val; +} + +map :: proc { + (list: ^List($T), f: (^T) -> void) { + } +} + get_iterator :: (list: ^List($T)) -> Iterator(T) { iterator_next :: ($T: type_expr, data: rawptr) -> (T, bool) { list_iter := cast(^ListIterator(T)) data; diff --git a/core/conv.onyx b/core/conv.onyx index 6bfab2af..5c7383cc 100644 --- a/core/conv.onyx +++ b/core/conv.onyx @@ -86,7 +86,7 @@ i64_to_str :: (n: i64, base: u64, buf: [] u8, min_length := 0) -> str { return str.{ data = c + 1, count = len }; } -// NOTE: This is a big hack but it will work for now +@Hack @Cleanup // This is a big hack but it will work for now f64_to_str :: (f: f64, buf: [] u8) -> str { f *= 10000.0; v := cast(i64) f; diff --git a/core/io/reader.onyx b/core/io/reader.onyx index 8ab638a0..943d360b 100644 --- a/core/io/reader.onyx +++ b/core/io/reader.onyx @@ -1,5 +1,7 @@ package core.io +memory :: package core.memory + Reader :: struct { stream : ^Stream; } @@ -10,11 +12,24 @@ reader_make :: (s: ^Stream) -> Reader { return Reader.{ s }; } +reader_from_string :: (s: str) -> Reader { + stream_ptr := new(StringStream); @Leak + *stream_ptr = string_stream_make(s); + + return Reader.{ stream_ptr }; +} + read_byte :: (use reader: ^Reader) -> u8 { err, byte := stream_read_byte(stream); return byte; } +read_bytes :: (use reader: ^Reader, bytes := 1, allocator := context.allocator) -> str { + buffer := memory.make_slice(u8, bytes, allocator); + stream_read(stream, buffer); + return buffer; +} + read_u32 :: (use reader: ^Reader) -> u32 { n: u32 = 0; @@ -112,7 +127,7 @@ read_word :: (use reader: ^Reader, numeric_allowed := false, allocator := contex return out; } -read_until :: (use reader: ^Reader, until: u8, allocator := context.allocator, consume_end := false) -> str { +read_until :: (use reader: ^Reader, until: u8, skip: u32 = 0, allocator := context.allocator, consume_end := false) -> str { _, curr_pos := stream_tell(stream); count := 0; @@ -122,7 +137,8 @@ read_until :: (use reader: ^Reader, until: u8, allocator := context.allocator, c if curr != until { count += 1; } else { - break; + if skip == 0 do break; + else do skip -= 1; } err, curr = stream_read_byte(stream); @@ -173,3 +189,7 @@ skip_whitespace :: (use reader: ^Reader) { } } } + +skip_bytes :: (use reader: ^Reader, bytes: u32) { + for _: bytes do stream_read_byte(stream); +} \ No newline at end of file diff --git a/core/string.onyx b/core/string.onyx index 6bf5a7dc..a34f65ee 100644 --- a/core/string.onyx +++ b/core/string.onyx @@ -53,6 +53,25 @@ concat :: proc { return str.{ data, len1 + len2 }; }, + @Cleanup // Don't love that the allocator is necessary here, + // but it is impossible to specify a default value for the + // allocator while having a variadic number of strings. This + // is only due to the languages constraints however. This + // could easily be changed since there is no ambiguity. + (allocator: Allocator, strings: ..str) -> str { + total_length := 0; + for s: strings do total_length += s.count; + + data := cast(^u8) raw_alloc(allocator, total_length); + offset := 0; + for s: strings { + memory.copy(data + offset, s.data, s.count); + offset += s.count; + } + + return str.{ data, total_length }; + }, + (into: ^[..] u8, s: str) -> str { array.ensure_capacity(into, into.count + s.count); memory.copy(into.data, s.data, into.count); @@ -61,6 +80,7 @@ concat :: proc { } } + split :: (s: str, delim: u8, allocator := context.allocator) -> []str { delim_count := 0; for i: 0 .. s.count do if s[i] == delim do delim_count += 1; @@ -107,7 +127,8 @@ contains :: proc { }, } -// TODO: Check this for edge cases and other bugs. I'm not confident +@TODO +// Check this for edge cases and other bugs. I'm not confident // it will work perfectly yet. - brendanfh 2020/12/21 compare :: (str1: str, str2: str) -> i32 { i := 0; @@ -238,38 +259,6 @@ advance :: proc { // DEPRECATED // Everything below this point is deprecated -read_u32 :: (s: ^str, out: ^u32) { - n := 0; - - strip_leading_whitespace(s); - while s.data[0] >= #char "0" && s.data[0] <= #char "9" { - n *= 10; - n += cast(u32) (s.data[0] - #char "0"); - - s.data += 1; - s.count -= 1; - } - - *out = n; -} - -read_char :: (s: ^str, out: ^u8) { - *out = s.data[0]; - s.data += 1; - s.count -= 1; -} - -read_chars :: (s: ^str, out: ^str, char_count := 1) { - out.data = s.data; - out.count = char_count; - s.data += char_count; - s.count -= char_count; -} - -discard_chars :: (s: ^str, char_count := 1) { - s.data += char_count; - s.count -= char_count; -} // Goes up to but not including the closest newline or EOF read_line :: (s: ^str, out: ^str) { @@ -313,7 +302,7 @@ read_until :: (s: ^str, upto: u8, skip := 0) -> str { return out; } -read_until_either :: (s: ^str, skip: u32, uptos: ..u8) -> str { +read_until_any :: (s: ^str, skip: u32, uptos: ..u8) -> str { if s.count == 0 do return ""; out : str; @@ -347,7 +336,3 @@ advance_line :: (s: ^str) { s.data += adv + 1; s.count -= adv + 1; } - -read :: proc { - read_u32, read_char -} diff --git a/core/string/builder.onyx b/core/string/builder.onyx index 3f15861a..afbfc8ec 100644 --- a/core/string/builder.onyx +++ b/core/string/builder.onyx @@ -3,6 +3,8 @@ package core.string.builder // DEPRECATED: This package is deprecated in favor of using // an io.DynamicStringStream with an io.Writer. +#if false { + #private_file array :: package core.array #private_file string :: package core.string #private_file conv :: package core.conv @@ -71,3 +73,4 @@ to_str :: proc (use sb: ^Builder) -> str { return str.{ data.data, data.count }; } +} \ No newline at end of file diff --git a/core/string/reader.onyx b/core/string/reader.onyx index c950227d..4c323792 100644 --- a/core/string/reader.onyx +++ b/core/string/reader.onyx @@ -88,7 +88,6 @@ read_line :: proc (use reader: ^StringReader) -> str { out.data = data; out.count = 0; - // HACK(Brendan): I want to use a for loop, but I don't know why. for ch: *(cast(^str) reader) { if ch == #char "\n" do break; out.count += 1; @@ -114,7 +113,6 @@ read_until :: proc (use reader: ^StringReader, skip: u32, uptos: ..u8) -> str { s := skip; - // HACK(Brendan): See above. for ch: *(cast(^str) reader) { for upto: uptos do if ch == upto { if s == 0 do break break; diff --git a/examples/06_dynamic_arrays.onyx b/examples/06_dynamic_arrays.onyx index d41c7609..fb4d27c8 100644 --- a/examples/06_dynamic_arrays.onyx +++ b/examples/06_dynamic_arrays.onyx @@ -20,7 +20,7 @@ main :: (args: [] cstr) { // Currently, there are no implicit procedure calls anywhere // in the language because I find explicitly specifying // everything to be less bug prone in the long run, at the - // trade off of being mildly tedious. Since there are implicit + // trade off of being mildly tedious. Since there aren't implicit // procedure calls, we have to initialize and free the dynamic // array explicitly. The 'defer' simply runs array.free at the // end of this procedure scope. We will talk more about how to diff --git a/examples/07_structs.onyx b/examples/07_structs.onyx index b562d059..0d1acc55 100644 --- a/examples/07_structs.onyx +++ b/examples/07_structs.onyx @@ -73,7 +73,7 @@ main :: (args: [] cstr) { print_spacer(); - // Structs in Onyx can behave like C unions, simply by usings the '#union' directive. + // Structs in Onyx can behave like C unions, simply by using the '#union' directive. FloatIntUnion :: struct #union { i : i32; f : f32; diff --git a/tests/aoc-2020/day1.onyx b/tests/aoc-2020/day1.onyx index e3a570ec..d4728cae 100644 --- a/tests/aoc-2020/day1.onyx +++ b/tests/aoc-2020/day1.onyx @@ -4,13 +4,14 @@ use package core main :: (args: [] cstr) { contents := #file_contents "./tests/aoc-2020/input/day1.txt"; + reader := io.reader_from_string(contents); nums := array.make(u32, 128); defer array.free(^nums); while num := 1; num > 0 { // This sets num to be 0 if there is no number - string.read_u32(^contents, ^num); + num = io.read_u32(^reader); if num != 0 do array.push(^nums, num); } diff --git a/tests/aoc-2020/day2.onyx b/tests/aoc-2020/day2.onyx index 8e2be91b..1731a912 100644 --- a/tests/aoc-2020/day2.onyx +++ b/tests/aoc-2020/day2.onyx @@ -6,22 +6,22 @@ use package core main :: (args: [] cstr) { contents := #file_contents "./tests/aoc-2020/input/day2.txt"; + reader := io.reader_from_string(contents); valid := 0; - lo : u32; - hi : u32; - ch : u8; - pw := ""; while true { - string.read_u32(^contents, ^lo); + lo := io.read_u32(^reader); if lo == 0 do break; - string.discard_chars(^contents); - string.read_u32(^contents, ^hi); - string.discard_chars(^contents); - string.read_char(^contents, ^ch); - string.discard_chars(^contents, 2); - string.read_line(^contents, ^pw); + + io.read_byte(^reader); + hi := io.read_u32(^reader); + + io.read_byte(^reader); + ch := io.read_byte(^reader); + + io.skip_bytes(^reader, 2); + pw := io.read_line(^reader); // Part 1 // count := 0; diff --git a/tests/aoc-2020/day22.onyx b/tests/aoc-2020/day22.onyx index 29cab03d..c1d99d90 100644 --- a/tests/aoc-2020/day22.onyx +++ b/tests/aoc-2020/day22.onyx @@ -43,20 +43,20 @@ combat :: (player1: ^[..] u32, player2: ^[..] u32) -> u32 { // 4,5,2,8,|1,3,9,7, // Larger numbers are encoded in base 64. encode_hands :: (alloc: Allocator, p1: ^[..] u32, p2: ^[..] u32) -> str { - b :: package core.string.builder + stream := io.dynamic_string_stream_make(256, alloc); + writer := io.writer_make(^stream); - builder := b.make(256, alloc); for n: *p1 { - b.add_i64(^builder, ~~n, 64); - b.add_str(^builder, ","); + io.write_i64(^writer, ~~n, 64); + io.write_str(^writer, ","); } - b.add_str(^builder, "|"); + io.write_str(^writer, "|"); for n: *p2 { - b.add_i64(^builder, ~~n, 64); - b.add_str(^builder, ","); + io.write_i64(^writer, ~~n, 64); + io.write_str(^writer, ","); } - return b.to_str(^builder); + return io.dynamic_string_stream_to_str(^stream); } recursive_combat :: (player1: ^[..] u32, player2: ^[..] u32) -> u32 {