diff options
| author | San Jacobs | 2026-05-11 23:10:39 +0200 |
|---|---|---|
| committer | San Jacobs | 2026-05-11 23:10:39 +0200 |
| commit | 8fdea54e718157389ef5c2df6864d9cd3e895897 (patch) | |
| tree | 6940b3a4b4b4efb97cb4c4a8773c797045f036b7 | |
| parent | b4da4c036cb6e32754dd4a26ef7de9633bf4ef0d (diff) | |
| download | better-report-8fdea54e718157389ef5c2df6864d9cd3e895897.tar.gz better-report-8fdea54e718157389ef5c2df6864d9cd3e895897.tar.bz2 better-report-8fdea54e718157389ef5c2df6864d9cd3e895897.zip | |
New odin version and fixed various file handle and memory leaks
| -rwxr-xr-x | build.bat | 2 | ||||
| -rw-r--r-- | src/main.odin | 125 | ||||
| -rw-r--r-- | src/wav/wav.odin | 16 | ||||
| -rw-r--r-- | src/wav/xml/xml_reader.odin | 4 |
4 files changed, 76 insertions, 71 deletions
@@ -4,4 +4,6 @@ rem -knekt rem && bin\better-report.exe test\ && bin\better-report.exe rem odin build src/ -o:speed -out:C:/tools/better-report.exe rem odin run src/wav +if %errorlevel% neq 0 exit /b %errorlevel% +md bin\release 2>nul odin build src/ -resource:src/graphics/windows.rc -o:speed -out:bin/release/better-report.exe
\ No newline at end of file diff --git a/src/main.odin b/src/main.odin index 404700f..4d0ac88 100644 --- a/src/main.odin +++ b/src/main.odin @@ -2,7 +2,7 @@ package main import "core:fmt" import "core:os" -import "core:os/os2" +import os_old "core:os/old" import "core:path/filepath" import "core:sys/windows" import "core:strings" @@ -22,7 +22,7 @@ when ODIN_OS == .Windows { SEPARATOR :: "/" } -VERSION :: "1.7" +VERSION :: "1.7.2" BRANDING : Brand = .NONE @@ -117,7 +117,7 @@ main :: proc() { fmt.printfln("Report v{} - Copyright (C) 2025 Sander J. Skjegstad\n", VERSION) - exe_path, _ := os2.get_executable_directory(context.allocator) + exe_path, _ := os.get_executable_directory(context.allocator) exe_local_fields_file := fmt.aprint(exe_path, HEADER_FIELDS_FILENAME, sep=SEPARATOR) instant_run_paths : [dynamic]string @@ -125,8 +125,12 @@ main :: proc() { if os.is_file(exe_local_fields_file) { when ODIN_DEBUG do fmt.printfln("\"%v\" exists.", exe_local_fields_file) } else { - os.write_entire_file(exe_local_fields_file, transmute([]u8)HEADER_TEMPLATE) - fmt.printfln("Created \"%v\".", exe_local_fields_file) + write_err := os.write_entire_file(exe_local_fields_file, transmute([]u8)HEADER_TEMPLATE) + if write_err == nil { + fmt.printfln("Created \"%v\".", exe_local_fields_file) + } else { + fmt.printfln("Failed to create \"%v\".", exe_local_fields_file) + } } } else { for arg in os.args[1:] { @@ -145,7 +149,7 @@ main :: proc() { header_fields_file = exe_local_fields_file info_txt, info_txt_ok := os.read_entire_file(header_fields_file, context.temp_allocator) - if info_txt_ok { + if info_txt_ok == nil { it := string(info_txt) for line in strings.split_lines_iterator(&it) { if len(line)==len("KNEKT") { @@ -234,7 +238,7 @@ main :: proc() { scan :: proc(input_path : string) { fmt.printf("Input path: {}\n", input_path) - path_info, error := os.stat(input_path) + path_info, error := os.stat(input_path, context.temp_allocator) previous_header_file := header_fields_file defer header_fields_file = previous_header_file @@ -244,7 +248,7 @@ scan :: proc(input_path : string) { if error == os.ERROR_NONE { - if(path_info.is_dir) { + if path_info.type == .Directory { input_local_fields_file := fmt.aprint(path_info.fullpath, HEADER_FIELDS_FILENAME, sep="") if os.is_file(input_local_fields_file) { @@ -253,12 +257,7 @@ scan :: proc(input_path : string) { fmt.printf("Directory submitted! Walking directory...\n\n") fmt.printf("š {}\n", path_info.name) - try_os2 := walk_directory(path_info.fullpath, &file_count, 1) - if len(job_list) == 0 && try_os2 { - fmt.printf("\nNot_Dir error encountered. Trying os2 version...\n\n") - fmt.printf("š {}\n", path_info.name) - walk_directory_os2(path_info.fullpath, &file_count, 1) - } + walk_directory(path_info.fullpath, &file_count, 1) } else { fmt.println("File submitted! Processing file...") append(&job_list, CSV(strings.clone(path_info.fullpath))) @@ -270,7 +269,7 @@ scan :: proc(input_path : string) { parse_ok : bool switch file in job { case CSV: - file_info, _ := os.stat(file) + file_info, _ := os.stat(file, context.temp_allocator) fmt.printf("\nš File {}: {}\n", i+1, file_info.name) parsed, parse_ok = parse_file(file_info.fullpath) if !parse_ok { @@ -284,7 +283,7 @@ scan :: proc(input_path : string) { if parse_ok { fmt.printf("\nParsed %d WAV(s).\n", parsed.row_count) } else { - file_info, _ := os.stat(file[0]) + file_info, _ := os.stat(file[0], context.temp_allocator) fmt.printf("\nParse failed: {}\n", file_info.fullpath) continue } @@ -328,11 +327,11 @@ parse_folder :: proc(paths : Directory) -> (Report, bool) { append(&header_build, "Take") append(&header_build, "Duration") append(&header_build, "Timecode") + append(&header_build, "Project") append(&header_build, "TC FPS") append(&header_build, "User Bits") append(&header_build, "Tape") append(&header_build, "Date") - append(&header_build, "Project") append(&header_build, "Sample Rate") append(&header_build, "Format") // Bit depth and int vs float first_channel_index := len(header_build) @@ -368,8 +367,8 @@ parse_folder :: proc(paths : Directory) -> (Report, bool) { } info_txt, info_txt_ok := os.read_entire_file(header_file, context.temp_allocator) - - if info_txt_ok { + + if info_txt_ok == nil { it := string(info_txt) line_index := 0 for line in strings.split_lines_iterator(&it) { @@ -575,7 +574,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { device := device output : Report = {} data, ok := os.read_entire_file(path, context.temp_allocator) - if !ok { + if ok != nil { fmt.printf("ERROR: Could not read file: {}\n", path) return {}, false } @@ -739,7 +738,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { // Missing newline on 8-series means we get info on the title line stage = .INFO - line_elements := strings.split(line, ",") + line_elements := strings.split(line, ",", context.temp_allocator) when VERBOSE do fmt.printf(".INFO {}: {}\n", line_index, line_elements) field := fmt.tprintf("{}:", line_elements[1]) entry := line_elements[2] @@ -753,7 +752,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { stage = .HEADER continue } - line_elements := strings.split(line, ",") + line_elements := strings.split(line, ",", context.temp_allocator) when VERBOSE do fmt.printf(".INFO {}: {}\n", line_index, line_elements) if line_elements[0] == "Date" { when VERBOSE do fmt.printf("Skipping line {}, because it's the retarded date field on an 8-series\n", line_index) @@ -773,7 +772,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { } else if len(line)>3 { when VERBOSE do fmt.printf(".HEADER {}:", line_index) // No trailing comma in the header?? - for element, e in strings.split(line, ",") { + for element, e in strings.split(line, ",", context.temp_allocator) { when VERBOSE do fmt.printf(" {}", element) output.header[e] = element @@ -797,7 +796,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { case .BODY: if len(line) > 2 { when VERBOSE do fmt.printf(".BODY {}:", line_index) - for element, e in strings.split(line, ",") { + for element, e in strings.split(line, ",", context.temp_allocator) { when VERBOSE do fmt.printf(" {}", element) entry : string = element output.table[body_line_index][e] = entry @@ -844,7 +843,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { stage = .HEADER continue } - line_elements := strings.split(line, ",") + line_elements := strings.split(line, ",", context.temp_allocator) when VERBOSE do fmt.printf(".INFO {}: {}\n", line_index, line_elements) field := line_elements[0] entry_raw := line_elements[1] @@ -860,7 +859,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { } else if len(line)>3 { when VERBOSE do fmt.printf(".HEADER {}:", line_index) // No trailing comma in the header?? - for element, e in strings.split(line, ",") { + for element, e in strings.split(line, ",", context.temp_allocator) { when VERBOSE do fmt.printf(" {}", element) output.header[e] = element @@ -885,7 +884,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { if len(line) > 2 { when VERBOSE do fmt.printf(".BODY {}:", line_index) // to skip empty entry after trailing comma we do a silly slice - for element, e in strings.split(line, ",")[:output.column_count] { + for element, e in strings.split(line, ",", context.temp_allocator)[:output.column_count] { when VERBOSE do fmt.printf(" {}", element) entry : string = element // Stripping quotes if after tracks begin @@ -940,7 +939,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { stage = .HEADER continue } - line_elements := strings.split(line, ",") + line_elements := strings.split(line, ",", context.temp_allocator) when VERBOSE do fmt.printf(".INFO {}: {}\n", line_index, line_elements) field_raw := line_elements[0] entry_raw := line_elements[1] @@ -953,7 +952,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { case .HEADER: when VERBOSE do fmt.printf(".HEADER {}:", line_index) // to skip empty entry after trailing comma we do a silly slice - for element, e in strings.split(line, ",")[:output.column_count] { + for element, e in strings.split(line, ",", context.temp_allocator)[:output.column_count] { when VERBOSE do fmt.printf(" {}", element) output.header[e] = element[1:len(element)-1] @@ -975,7 +974,7 @@ parse_file :: proc(path : CSV, device : Device = .UNSET) -> (Report, bool) { if line == "" do break when VERBOSE do fmt.printf(".BODY {}:", line_index) // to skip empty entry after trailing comma we do a silly slice - for element, e in strings.split(line, ",")[:output.column_count] { + for element, e in strings.split(line, ",", context.temp_allocator)[:output.column_count] { when VERBOSE do fmt.printf(" {}", element) output.table[body_line_index][e] = element[1:len(element)-1] } @@ -1152,7 +1151,9 @@ render :: proc(report : Report) { } output_text := strings.to_string(builder) - os.write_entire_file(output_path, transmute([]u8)output_text) + _ = os.write_entire_file(output_path, transmute([]u8)output_text) + + strings.builder_destroy(&builder) fmt.printf("Output: {}\n", output_path) } @@ -1163,40 +1164,40 @@ indent_by :: proc(i : int) { } } -walk_directory :: proc(path : string, file_number : ^int, depth : int = 0) -> bool { - handle, ok := os.open(path) - defer os.close(handle) - if ok != os.ERROR_NONE { +walk_directory_old :: proc(path : string, file_number : ^int, depth : int = 0) -> bool { + handle, ok := os_old.open(path) + defer os_old.close(handle) + if ok != os_old.ERROR_NONE { indent_by(depth) fmt.printf("ERROR opening dir: %s\n", path) return false } - - files, okr := os.read_dir(handle, -1, context.temp_allocator) - if okr != os.ERROR_NONE { + + files, okr := os_old.read_dir(handle, -1, context.temp_allocator) + if okr != os_old.ERROR_NONE { indent_by(depth) fmt.printf("ERROR [{}] reading dir: %s\n", okr, path) when ODIN_OS == .Windows { - if okr == os.ERROR_FILE_IS_NOT_DIR do return true + if okr == os_old.ERROR_FILE_IS_NOT_DIR do return true } return true } - + wav_files : [dynamic]string clear(&wav_files) has_csv := false - + for file in files { - + full_path := file.fullpath - + if file.is_dir { indent_by(depth) fmt.printf("š %s\n", file.name) - walk_directory(full_path, file_number, depth+1) // Recurse - + walk_directory_old(full_path, file_number, depth+1) // Recurse + } else { // If file is actually a file - + extension := strings.to_lower(filepath.ext(file.name)) defer delete(extension) if extension == ".csv" { @@ -1225,47 +1226,47 @@ walk_directory :: proc(path : string, file_number : ^int, depth : int = 0) -> bo return false } -walk_directory_os2 :: proc(path : string, file_number : ^int, depth : int = 0) { - handle, ok := os2.open(path) - if ok != os2.ERROR_NONE { +walk_directory :: proc(path : string, file_number : ^int, depth : int = 0) { + handle, ok := os.open(path) + if ok != os.ERROR_NONE { indent_by(depth) fmt.printf("ERROR opening dir: %s\n", path) return } - defer os2.close(handle) - - files, okr := os2.read_dir(handle, -1, context.temp_allocator) - if okr != os2.ERROR_NONE { + defer os.close(handle) + + files, okr := os.read_dir(handle, -1, context.temp_allocator) + if okr != os.ERROR_NONE { indent_by(depth) fmt.printf("ERROR [{}] reading dir: %s\n", okr, path) return } - + wav_files : [dynamic]string has_csv := false - + for file in files { - + full_path := file.fullpath - + if os.is_dir(full_path) { indent_by(depth) fmt.printf("š %s\n", file.name) - walk_directory_os2(full_path, file_number, depth+1) // Recurse - + walk_directory(full_path, file_number, depth+1) // Recurse + } else { // If file is actually a file - + extension := strings.to_lower(filepath.ext(file.name)) defer delete(extension) if extension == ".csv" { indent_by(depth) fmt.printf("š [#%d] %s\n", file_number^, file.name) - append(&job_list, strings.clone(file.fullpath)) + append(&job_list, strings.clone(file.fullpath, context.temp_allocator)) file_number^ += 1 has_csv = true } if extension == ".wav" { - append(&wav_files, strings.clone(full_path)) + append(&wav_files, strings.clone(full_path, context.temp_allocator)) } } } diff --git a/src/wav/wav.odin b/src/wav/wav.odin index 0d148c7..dc5923f 100644 --- a/src/wav/wav.odin +++ b/src/wav/wav.odin @@ -29,7 +29,7 @@ Wav :: struct { audio : [][]f32, // Internals - handle : os.Handle, + handle : ^os.File, load_head : int, // Metadata @@ -120,9 +120,7 @@ read :: proc(path : string, allocator := context.allocator) -> (Wav, bool) #opti load_err : os.Error file.handle, load_err = os.open(path) - defer os.close(file.handle) - defer file.handle = 0 - if load_err != os.General_Error.None { + if load_err != nil { fmt.eprintfln("ERROR %v: Unable to load file \"%v\"", load_err, path) return {}, false } @@ -471,7 +469,8 @@ read :: proc(path : string, allocator := context.allocator) -> (Wav, bool) #opti naming_channel := 0 description := string(temp_bext[:256]) - for line in strings.split_lines(description) { + lines := strings.split_lines(description) + for line in lines { if len(line)<1 do continue if file.channel_names[naming_channel] == "" && (strings.starts_with(line, "sTRK") || strings.starts_with(line, "zTRK")) { @@ -512,6 +511,7 @@ read :: proc(path : string, allocator := context.allocator) -> (Wav, bool) #opti } } } + delete(lines) head := 0 when VERBOSE do fmt.printf("Description: \n%v\n", string(temp_bext[head:256])) head += 256 @@ -548,6 +548,9 @@ read :: proc(path : string, allocator := context.allocator) -> (Wav, bool) #opti // just here to make some printing prettier temp_bext = nil + os.close(file.handle) + file.handle = nil + return file, true } @@ -640,8 +643,7 @@ tprint_timecode :: proc(file : Wav) -> string { } print_timecode :: proc(file : Wav, allocator := context.allocator) -> string { tc := get_timecode(file) - using tc - return fmt.aprintf("%02d:%02d:%02d:%02d",hour,minute,second,frame, + return fmt.aprintf("%02d:%02d:%02d:%02d", tc.hour, tc.minute, tc.second, tc.frame, allocator=allocator) } get_timecode :: proc(file : Wav) -> (output:Timecode) { diff --git a/src/wav/xml/xml_reader.odin b/src/wav/xml/xml_reader.odin index c19cbf6..b277a5e 100644 --- a/src/wav/xml/xml_reader.odin +++ b/src/wav/xml/xml_reader.odin @@ -377,8 +377,8 @@ load_from_file :: proc(filename: string, options := DEFAULT_OPTIONS, error_handl context.allocator = allocator options := options - data, data_ok := os.read_entire_file(filename) - if !data_ok { return {}, .File_Error } + data, data_err := os.read_entire_file(filename, context.allocator) + if data_err != nil { return {}, .File_Error } options.flags += { .Input_May_Be_Modified } |