diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-11 17:47:30 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-11 17:47:30 +0000 |
| commit | ba5ee94871e670fbe1ea091dd5731e593df0b29f (patch) | |
| tree | 3b706a9ab11effa4acb094482f3d657c986ef501 /std/fs.zc | |
| parent | aba9191ab3ef0699b0f9507ee3d03161f9ee7771 (diff) | |
Some std for you
Diffstat (limited to 'std/fs.zc')
| -rw-r--r-- | std/fs.zc | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/std/fs.zc b/std/fs.zc new file mode 100644 index 0000000..4223054 --- /dev/null +++ b/std/fs.zc @@ -0,0 +1,162 @@ + +import "./core.zc" +import "./result.zc" +import "./string.zc" +import "./vec.zc" + +raw { + #include <dirent.h> + #include <sys/stat.h> + #include <unistd.h> + + // Helper to get file size for stat + int _z_fs_get_metadata(char* path, uint64_t* size, int* is_dir, int* is_file) { + struct stat st; + if (stat(path, &st) != 0) return -1; + *size = st.st_size; + *is_dir = S_ISDIR(st.st_mode); + *is_file = S_ISREG(st.st_mode); + return 0; + } + + int _z_fs_read_entry(void* dir, char* out_name, int* is_dir) { + struct dirent* ent = readdir((DIR*)dir); + if (!ent) return 0; + strcpy(out_name, ent->d_name); + *is_dir = (ent->d_type == DT_DIR); + return 1; + } + + int _z_fs_mkdir(char* path) { + #ifdef _WIN32 + return mkdir(path); + #else + return mkdir(path, 0777); + #endif + } +} + +extern fn _z_fs_mkdir(path: char*) -> int; +extern fn _z_fs_get_metadata(path: char*, size: U64*, is_dir: int*, is_file: int*) -> int; +extern fn _z_fs_read_entry(dir: void*, out_name: char*, is_dir: int*) -> int; + +struct File { + handle: void*; // FILE* +} + +struct Metadata { + size: U64; + is_dir: bool; + is_file: bool; +} + +@derive(Eq) +struct DirEntry { + name: String; + is_dir: bool; +} + +impl File { + fn open(path: char*, mode: char*) -> Result<File> { + var h = fopen(path, mode); + if (h == NULL) { + return Result<File>::Err("Failed to open file"); + } + return Result<File>::Ok(File { handle: h }); + } + + fn close(self) { + if (self.handle) { + fclose(self.handle); + self.handle = NULL; + } + } + + fn read_to_string(self) -> Result<String> { + if (self.handle == NULL) return Result<String>::Err("File not open"); + + fseek(self.handle, 0, SEEK_END); + var size = ftell(self.handle); + fseek(self.handle, 0, SEEK_SET); + + var buffer: char* = malloc((usize)size + 1); + if (buffer == NULL) return Result<String>::Err("Out of memory"); + + var read = fread(buffer, 1, size, self.handle); + buffer[read] = 0; + + var s = String::new(buffer); + free(buffer); + return Result<String>::Ok(s); + } + + fn read_all(path: char*) -> Result<String> { + var res = File::open(path, "rb"); + if (res.is_err()) return Result<String>::Err(res.err); + + var f: File = res.unwrap(); + var s_res = f.read_to_string(); + f.close(); + return s_res; + } + + fn write_string(self, content: char*) -> Result<bool> { + if (self.handle == NULL) return Result<bool>::Err("File not open"); + var len = strlen(content); + var written = fwrite(content, 1, len, self.handle); + if (written != len) return Result<bool>::Err("Write incomplete"); + return Result<bool>::Ok(true); + } + + fn exists(path: char*) -> bool { + return access(path, F_OK) == 0; + } + + fn metadata(path: char*) -> Result<Metadata> { + var size: uint64_t; + var is_d: int; + var is_f: int; + if (_z_fs_get_metadata(path, &size, &is_d, &is_f) != 0) { + return Result<Metadata>::Err("Failed to get metadata"); + } + return Result<Metadata>::Ok(Metadata { size: (U64)size, is_dir: is_d != 0, is_file: is_f != 0 }); + } + + fn create_dir(path: char*) -> Result<bool> { + if (_z_fs_mkdir(path) != 0) return Result<bool>::Err("Failed to create directory"); + return Result<bool>::Ok(true); + } + + fn remove_file(path: char*) -> Result<bool> { + if (unlink(path) != 0) return Result<bool>::Err("Failed to remove file"); + return Result<bool>::Ok(true); + } + + fn remove_dir(path: char*) -> Result<bool> { + if (rmdir(path) != 0) return Result<bool>::Err("Failed to remove directory"); + return Result<bool>::Ok(true); + } + + fn read_dir(path: char*) -> Result< Vec<DirEntry> > { + var dir = opendir(path); + if (dir == NULL) return Result< Vec<DirEntry> >::Err("Failed to open directory"); + + var entries = Vec<DirEntry>::new(); + var name_buf = malloc(256); + var is_d: int = 0; + + while (_z_fs_read_entry(dir, name_buf, &is_d)) { + // Skip . and .. + if (strcmp(name_buf, ".") == 0 || strcmp(name_buf, "..") == 0) continue; + + entries.push(DirEntry { + name: String::new(name_buf), + is_dir: is_d != 0 + }); + } + + free(name_buf); + closedir(dir); + return Result< Vec<DirEntry> >::Ok(entries); + } +} |
