diff --git a/uxn/file.ha b/uxn/file.ha index 4e16a76..8b918b2 100644 --- a/uxn/file.ha +++ b/uxn/file.ha @@ -5,6 +5,7 @@ use io; use bytes; use bufio; use strings; +use strconv; fn generate_dir_string(name: str) str = { // fmt::println("Generating dir string!")!; @@ -116,109 +117,79 @@ fn read_file_to_addr(fi: u8, state: *uxn) void = { }; return; }; + +export type stattype = enum { + FILE, + DIR, + BIG, + MISS, +}; + fn filestat_to_addr(fi: u8, state: *uxn) void = { const length = if(fi == 0) { yield short_from_bytes(state.dev[0xaa],state.dev[0xab]); } else { yield short_from_bytes(state.dev[0xba],state.dev[0xbb]); }; const destaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa4],state.dev[0xa5]); } else { yield short_from_bytes(state.dev[0xb4],state.dev[0xb5]); }; - // fmt::printfln("Reading {} bytes to 0x{:x}", length, destaddr)!; let bytesread = 0; + const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } + else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; + const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; + const name: str = match(strings::fromutf8(nameslice)){ + case let s: str => + yield s; + case => + fmt::fatal("Bad String encoding in filename"); + }; - if(!state.files[fi].dir){ - const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } - else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; - const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; - const name: str = match(strings::fromutf8(nameslice)){ - case let s: str => - yield s; - case => - fmt::fatal("Bad String encoding in filename"); + const fstat = match(os::fstat(state.files[fi].file: io::file)){ + case let fstat: fs::filestat => + yield fstat; + case let err: fs::error => + yield void; + }; + const fsize = match(fstat){ + case let stat: fs::filestat => + yield stat.sz: u32; + case => + yield void; + }; + const ftype: stattype = { + if(state.files[fi].dir) yield stattype::DIR; + yield match(fsize){ + case let num: u32 => + if(num > 0xFFFF) yield stattype::BIG; + yield stattype::FILE; + case void => + yield stattype::MISS; }; - const fstat = match(os::fstat(state.files[fi].file: io::file)){ - case let fstat: fs::filestat => - yield fstat; - case let err: fs::error => - yield void; - - }; - const fsize = match(fstat){ - case let stat: fs::filestat => - yield stat.sz: u32; - case => - yield 0: u32; - - }; - const modestring = if(fsize <= 0xFFFF){ - yield fmt::asprintf("{:x.4}",fsize)!; - }else { - yield "????"; - }; - let modestringiter = strings::iter(modestring); - for(let i: u16 =0; i - yield r; - case done => - break; - }; - bytesread += 1; - state.ram[destaddr+i] = char: u8; - }; - for(let i: u16 =0; i - bytesread += 1; - // fmt::printfln("Reading byte {}: from file",b)!; - state.ram[destaddr+i] = b; - case let eof: io::EOF => - state.ram[destaddr+i] = 0; //This might need to be done differently - case let err: io::error => - fmt::fatalf("Error reading: {}", io::strerror(err)); - }; - }; - - }else { - const nameaddr = if(fi == 0) { yield short_from_bytes(state.dev[0xa8],state.dev[0xa9]); } - else { yield short_from_bytes(state.dev[0xb8],state.dev[0xb9]); }; - const nameslice: []u8 = bytes::cut(state.ram[nameaddr..],0x00).0; - const name: str = match(strings::fromutf8(nameslice)){ - case let s: str => - yield s; - case => - fmt::fatal("Bad String encoding in filename"); - }; - let dfs = os::diropen(name)!; - let df = os::dirfile(dfs); - const stat = os::fstat(df)!; - const fsize = stat.sz: u32; - const modestring = if(fsize <= 0xFFFF){ - yield fmt::asprintf("{:x.4}",fsize)!; - }else { - yield "????"; - }; - let modestringiter = strings::iter(modestring); - for(let i: u16 =0; i - yield r; - case done => - break; - }; - bytesread += 1; - state.ram[destaddr+i] = char: u8; - }; - for(let i: u16 =0; i - bytesread += 1; - // fmt::printfln("Reading byte {}: from file",b)!; - state.ram[destaddr+i] = b; - case let eof: io::EOF => - state.ram[destaddr+i] = 0; //This might need to be done differently - case let err: io::error => - fmt::fatalf("Error reading: {}", io::strerror(err)); - }; + }; + const sz = match(fsize){ + case void => + yield 0; + case let s: u32 => + yield s; + }; + const modestring: str = switch(ftype){ + case stattype::FILE => + yield fmt::asprintf("{%}",sz,&fmt::mods { base = strconv::base::HEX, prec = length, ...})!; + case stattype::DIR => + yield fmt::asprintf("{%}","-",&fmt::mods { pad = '-', width = length, ...})!; + case stattype::BIG => + yield fmt::asprintf("{%}","?",&fmt::mods { pad = '?', width = length, ...})!; + case stattype::MISS => + yield fmt::asprintf("{%}","!",&fmt::mods { pad = '!', width = length, ...})!; + }; + + let modestringiter = strings::iter(modestring); + for(let i: u16 =0; i + yield r; + case done => + fmt::fatal("Stat string messed up"); }; + bytesread += 1; + state.ram[destaddr+i] = char: u8; }; if(fi == 0){ @@ -240,7 +211,7 @@ fn write_file_from_addr(fi: u8,state: *uxn) void = { const appendf: bool = if(fi == 0) { yield state.dev[0xa7] != 0; } else { yield state.dev[0xb7] != 0; }; // fmt::printfln("Writing {} bytes from 0x{:x}", length, srcaddr)!; - fmt::printfln("Writing {} bytes from 0x{:x} to 0x{:x}", endaddr-srcaddr, srcaddr,endaddr)!; + // fmt::printfln("Writing {} bytes from 0x{:x} to 0x{:x}", endaddr-srcaddr, srcaddr,endaddr)!; // const bytes: []u8 = state.ram[srcaddr..endaddr]; const bytes: []u8 = if(endaddr < srcaddr){ yield state.ram[srcaddr..]; @@ -384,7 +355,7 @@ fn write_file_from_addr(fi: u8,state: *uxn) void = { match (io::write(state.files[fi].file,bytes)){ case let s: size => byteswritten += s: u16; - fmt::printfln("Writing {} bytes to file",s)!; + // fmt::printfln("Writing {} bytes to file",s)!; case let err: io::error => fmt::fatalf("Error writing file: {}", io::strerror(err)); };