package d2; import "core:os" import "core:fmt" die :: proc (eno: os.Errno) { fmt.printf("Fatal error: %s\n", os.get_last_error_string()); os.exit(int(eno)); } usage :: proc() { fmt.printf("Usage: ./%s FILENAME\n", os.args[0]); } BUFFER_SIZE :: 1024; State :: enum { NONE, READ_ID, READ_RESULT, READ_DELIM, READ_COLON, READ_NEWLINE } Result :: struct{ red: int, green: int, blue: int, }; TARGET_GAME :: Result{12, 13, 14}; games: [dynamic]Result = make([dynamic]Result); stack: [dynamic]State = make([dynamic]State); collect_digits :: proc(buffer: []u8, index: ^int) -> int { assert(index^ < len(buffer)); result := 0 for '0' <= buffer[index^] && buffer[index^] <= '9' && index^ < len(buffer) { result *= 10; result += int(buffer[index^] - '0'); index^ += 1; } return result; } consume_token :: proc(token: string, buffer: []u8, index: ^int) -> bool { bi := index^; ti := 0; for ti < len(token) { if bi >= len(buffer) || buffer[bi] != token[ti] { return false; } else { ti += 1; bi += 1; } } return true; } attempt_1 :: proc() { if len(os.args) < 2 { usage(); os.exit(-1); } fh, eno := os.open(os.args[1], os.O_RDONLY); if eno != os.ERROR_NONE { die(eno); } defer os.close(fh); id := -1; red, green, blue, num_read: int; state := State.READ_ID; total := 0; buffer, ok := os.read_entire_file_from_handle(fh); if !ok { // die(os.get_last_error()); // TODO os.exit(-1); } ix := 0; for ix < len(buffer) { if eno != os.ERROR_NONE { die(eno); } switch pop(&stack) { case .READ_ID: id = collect_digits(buffer, &ix); append(&stack, State.READ_RESULT); append(&stack, State.READ_DELIM); append(&stack, State.READ_COLON); case .READ_COLON: if !consume_token(":", buffer, &ix) { // TODO os.exit(-1); } case .READ_DELIM: for ix < len(buffer) && buffer[ix] == ' ' { ix += 1; } case .READ_NEWLINE: if !consume_token("\n", buffer, &ix) { // TODO os.exit(-1); } case .READ_RESULT: append(&stack, State.READ_ID); append(&stack, State.READ_NEWLINE); case .NONE: os.exit(-1); } } } main :: proc() { attempt_1(); }