From b38caa7ff8beee7cc3b5c763c0377d23e121298a Mon Sep 17 00:00:00 2001 From: Riyyi Date: Sun, 2 Aug 2026 13:33:10 +0200 Subject: [PATCH] Dir listing with looping --- src/file/list_dir.odin | 73 ++++++++++++++++++++++++------------------ src/main.odin | 2 +- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/file/list_dir.odin b/src/file/list_dir.odin index 6039fbd..2dc86bf 100644 --- a/src/file/list_dir.odin +++ b/src/file/list_dir.odin @@ -13,12 +13,46 @@ DirectoryEntry :: struct #all_or_none { // ----------------------------------------- -list_dir_by_path :: proc(path: string) -> [dynamic]DirectoryEntry { +list_dir_recursive :: proc(f: ^os.File) -> [dynamic]DirectoryEntry { + path := os.name(f) + return list_dir_recursive_by_path_impl(path) +} + +list_dir_recursive_by_path :: proc(path: string) -> [dynamic]DirectoryEntry { + return list_dir_recursive_by_path_impl(path) +} + +@(private) +list_dir_recursive_by_path_impl :: proc( + path: string, +) -> [dynamic]DirectoryEntry { if !os.is_dir(path) { fmt.eprintln("error: path is not a directory:", path) os.exit(1) } + result := [dynamic]DirectoryEntry{} + + queue := [dynamic]string{} + append(&queue, path) + + for len(queue) > 0 { + list_dir_queue(&queue, &result) + } + + shrink(&result, len(result)) // shrink to fit + return result +} + +@(private) +list_dir_queue :: proc( + queue: ^[dynamic]string, + result: ^[dynamic]DirectoryEntry, +) { + assert(len(queue) > 0, "queue must not be empty") + + path := pop(queue) + f, open_err := os.open(path, {.Read}) if open_err != nil { fmt.eprintln("error: open failed:", open_err) @@ -26,25 +60,6 @@ list_dir_by_path :: proc(path: string) -> [dynamic]DirectoryEntry { } defer os.close(f) - result := [dynamic]DirectoryEntry{} - list_dir_impl(f, &result) - return result -} - -list_dir :: proc(f: ^os.File) -> [dynamic]DirectoryEntry { - path := os.name(f) - if !os.is_dir(path) { - fmt.eprintln("error: path is not a directory:", path) - os.exit(1) - } - - result := [dynamic]DirectoryEntry{} - list_dir_impl(f, &result) - return result -} - -@(private) -list_dir_impl :: proc(f: ^os.File, builder: ^[dynamic]DirectoryEntry) { entries, read_err := os.read_all_directory(f, context.allocator) if read_err != nil { fmt.eprintln("error: read directory failed:", read_err) @@ -53,7 +68,7 @@ list_dir_impl :: proc(f: ^os.File, builder: ^[dynamic]DirectoryEntry) { defer delete(entries) // Reserve space for new entries - reserve(builder, cap(builder) + len(entries)) + reserve(result, cap(result) + len(entries)) working_dir, wd_err := os.get_working_directory(context.allocator) if wd_err != nil { @@ -64,6 +79,10 @@ list_dir_impl :: proc(f: ^os.File, builder: ^[dynamic]DirectoryEntry) { for entry, i in entries { + if entry.type == os.File_Type.Directory { + append(queue, entry.fullpath) + } + if entry.type == os.File_Type.Regular { relpath, rel_err := strings.replace( entry.fullpath, @@ -73,19 +92,9 @@ list_dir_impl :: proc(f: ^os.File, builder: ^[dynamic]DirectoryEntry) { context.allocator, ) append( - builder, + result, DirectoryEntry{relpath = relpath, size = entry.size}, ) } - - if entry.type == os.File_Type.Directory { - dir, dir_err := os.open(entry.fullpath, {.Read}) - if dir_err != nil { - fmt.eprintln("error: open directory failed:", dir_err) - os.exit(1) - } - defer os.close(dir) - list_dir_impl(dir, builder) // recurse into directory - } } } diff --git a/src/main.odin b/src/main.odin index c51d5b9..4086c10 100644 --- a/src/main.odin +++ b/src/main.odin @@ -19,6 +19,6 @@ main :: proc() { fmt.println("size:", asset.size) fmt.println("data:", asset.data) - entries := file.list_dir_by_path("./src") + entries := file.list_dir_recursive_by_path("./src") fmt.println("entries:", entries) }