posix.ha (2564B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use bytes; 5 use strings; 6 7 // These functions have been confined here to POSIX jail. They are 8 // POSIX-compliant, for their sins, but they do not fit in semantically 9 // with the other stack-paradigm functions. Hence this POSIX-complaint. 10 // They are based primarily off of `man 1p basename/dirname`, and secondarily 11 // off of the examples in `man 3p basename`. 12 13 // A POSIX-compliant implementation of dirname. See the POSIX specification 14 // for more information. Note that this function does *not* normalize the 15 // input. The return value is either borrowed from the input or statically 16 // allocated; use [[strings::dup]] to extend its lifetime. 17 export fn dirname(path: const str) const str = { 18 let path = strings::toutf8(path); 19 if (len(path) == 0) return "."; 20 21 path = bytes::rtrim(path, SEP); 22 if (len(path) == 0) return sepstr; 23 24 match (bytes::rindex(path, SEP)) { 25 case void => return "."; 26 case let z: size => path = path[..z]; 27 }; 28 path = bytes::rtrim(path, SEP); 29 30 if (len(path) == 0) return sepstr; 31 return strings::fromutf8_unsafe(path); 32 }; 33 34 // A POSIX-compliant implementation of basename. See the POSIX specification 35 // for more information. Note that this function does *not* normalize the 36 // input. The return value is either borrowed from the input or statically 37 // allocated; use [[strings::dup]] to extend its lifetime. 38 export fn basename(path: const str) const str = { 39 let path = strings::toutf8(path); 40 if (len(path) == 0) return "."; 41 42 path = bytes::rtrim(path, SEP); 43 if (len(path) == 0) return sepstr; 44 45 match (bytes::rindex(path, SEP)) { 46 case void => void; 47 case let z: size => path = path[z+1..]; 48 }; 49 return strings::fromutf8_unsafe(path); 50 }; 51 52 @test fn dirname_basename() void = { 53 const table = [ 54 // input , dirname , basename 55 ["usr" , "." , "usr" ], 56 ["usr/" , "." , "usr" ], 57 ["" , "." , "." ], 58 ["/" , "/" , "/" ], 59 ["//" , "/" , "/" ], // implementation defined 60 ["///" , "/" , "/" ], 61 ["/usr/" , "/" , "usr" ], 62 ["/usr/lib" , "/usr" , "lib" ], 63 ["//usr//lib//" , "//usr" , "lib" ], 64 ["/home//dwc//test", "/home//dwc", "test"], 65 ]; 66 for (let i = 0z; i < len(table); i += 1) { 67 let input: [MAX]u8 = [0...]; 68 const input = _local(table[i][0], &input); 69 assert(dirname(input) == local(table[i][1])); 70 assert(basename(input) == local(table[i][2])); 71 }; 72 };