diff --git a/src/file/file.odin b/src/file/file.odin index ac6d5aa..c1b5dc6 100644 --- a/src/file/file.odin +++ b/src/file/file.odin @@ -1,150 +1,7 @@ package file -import "core:fmt" -import "core:os" -import "core:strings" - // TODO: // - list files in directory // - get relative path // - read file contents // - write file contents - -// ----------------------------------------- - -Asset :: struct #all_or_none { - relpath: string, - size: i64, - data: []u8, -} - -DirectoryEntry :: struct #all_or_none { - relpath: string, - size: i64, -} - -// ----------------------------------------- - -list_dir_by_path :: proc(path: string) -> [dynamic]DirectoryEntry { - if !os.is_dir(path) { - fmt.eprintln("error: path is not a directory:", path) - os.exit(1) - } - - f, open_err := os.open(path, {.Read}) - if open_err != nil { - fmt.eprintln("error: open failed:", open_err) - os.exit(1) - } - 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) - os.exit(1) - } - defer delete(entries) - - // Reserve space for new entries - reserve(builder, cap(builder) + len(entries)) - - working_dir, wd_err := os.get_working_directory(context.allocator) - if wd_err != nil { - fmt.eprintln("error: get working directory failed:", wd_err) - os.exit(1) - } - defer delete(working_dir) - - for entry, i in entries { - - if entry.type == os.File_Type.Regular { - relpath, rel_err := strings.replace( - entry.fullpath, - working_dir, - ".", - 1, - context.allocator, - ) - append( - builder, - 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 - } - } -} - -read_by_path :: proc(path: string) -> []u8 { - f, open_err := os.open(path, {.Read}) - if open_err != nil { - fmt.eprintln("error: open failed:", open_err) - os.exit(1) - } - defer os.close(f) - - if !os.is_file(path) { - fmt.eprintln("error: path is not a file:", path) - os.exit(1) - } - - path := path // shadow parameter - path = strings.clone(path) - - size, size_err := os.file_size(f) - if size_err != nil { - fmt.eprintln("error: get file size failed:", size_err) - os.exit(1) - } - - data := make([]u8, size) - - n, read_err := os.read_full(f, data) - if read_err != nil { - delete(data) - fmt.eprintln( - "error: file read failed:", - read_err, - "got", - n, - "of", - size, - "bytes", - ) - os.exit(1) - } - - return data -} - -get_asset_by_path :: proc(path: string) -> Asset { - data := read_by_path(path) - return Asset{relpath = path, size = cast(i64)len(data), data = data} -} diff --git a/src/file/list_dir.odin b/src/file/list_dir.odin new file mode 100644 index 0000000..6039fbd --- /dev/null +++ b/src/file/list_dir.odin @@ -0,0 +1,91 @@ +package file + +import "core:fmt" +import "core:os" +import "core:strings" + +// ----------------------------------------- + +DirectoryEntry :: struct #all_or_none { + relpath: string, + size: i64, +} + +// ----------------------------------------- + +list_dir_by_path :: proc(path: string) -> [dynamic]DirectoryEntry { + if !os.is_dir(path) { + fmt.eprintln("error: path is not a directory:", path) + os.exit(1) + } + + f, open_err := os.open(path, {.Read}) + if open_err != nil { + fmt.eprintln("error: open failed:", open_err) + os.exit(1) + } + 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) + os.exit(1) + } + defer delete(entries) + + // Reserve space for new entries + reserve(builder, cap(builder) + len(entries)) + + working_dir, wd_err := os.get_working_directory(context.allocator) + if wd_err != nil { + fmt.eprintln("error: get working directory failed:", wd_err) + os.exit(1) + } + defer delete(working_dir) + + for entry, i in entries { + + if entry.type == os.File_Type.Regular { + relpath, rel_err := strings.replace( + entry.fullpath, + working_dir, + ".", + 1, + context.allocator, + ) + append( + builder, + 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/file/read_contents.odin b/src/file/read_contents.odin new file mode 100644 index 0000000..9a0651d --- /dev/null +++ b/src/file/read_contents.odin @@ -0,0 +1,62 @@ +package file + +import "core:fmt" +import "core:os" +import "core:strings" + +// ----------------------------------------- + +Asset :: struct #all_or_none { + relpath: string, + size: i64, + data: []u8, +} + +// ----------------------------------------- + +read_by_path :: proc(path: string) -> []u8 { + f, open_err := os.open(path, {.Read}) + if open_err != nil { + fmt.eprintln("error: open failed:", open_err) + os.exit(1) + } + defer os.close(f) + + if !os.is_file(path) { + fmt.eprintln("error: path is not a file:", path) + os.exit(1) + } + + path := path // shadow parameter + path = strings.clone(path) + + size, size_err := os.file_size(f) + if size_err != nil { + fmt.eprintln("error: get file size failed:", size_err) + os.exit(1) + } + + data := make([]u8, size) + + n, read_err := os.read_full(f, data) + if read_err != nil { + delete(data) + fmt.eprintln( + "error: file read failed:", + read_err, + "got", + n, + "of", + size, + "bytes", + ) + os.exit(1) + } + + return data +} + +get_asset_by_path :: proc(path: string) -> Asset { + data := read_by_path(path) + return Asset{relpath = path, size = cast(i64)len(data), data = data} +}