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;
}
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;
}
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;
}
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;
}
}
-// HACK: NullProcHack
+@NullProcHack
null_proc :: proc () #null ---
null :: cast(rawptr) 0;
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];
package core.list
+use package core.intrinsics.onyx { __zero_value }
+
ListElem :: struct (T: type_expr) {
next: ^ListElem(T) = null;
prev: ^ListElem(T) = null;
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;
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;
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;
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;
package core.io
+memory :: package core.memory
+
Reader :: struct {
stream : ^Stream;
}
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;
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;
if curr != until {
count += 1;
} else {
- break;
+ if skip == 0 do break;
+ else do skip -= 1;
}
err, curr = stream_read_byte(stream);
}
}
}
+
+skip_bytes :: (use reader: ^Reader, bytes: u32) {
+ for _: bytes do stream_read_byte(stream);
+}
\ No newline at end of file
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);
}
}
+
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;
},
}
-// 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;
// 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) {
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;
s.data += adv + 1;
s.count -= adv + 1;
}
-
-read :: proc {
- read_u32, read_char
-}
// 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
return str.{ data.data, data.count };
}
+}
\ No newline at end of file
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;
s := skip;
- // HACK(Brendan): See above.
for ch: *(cast(^str) reader) {
for upto: uptos do if ch == upto {
if s == 0 do break break;
// 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
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;
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);
}
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;
// 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 {