// ///// Example ////////////////// import io.directories.*; main() { for (x in directoryListing("/home")) println(x); } // //////////////////////////////// import libc.*; import unix.errno.*; // // directoryListing // directoryListing(x) = map(direntPointerToString, direntSequence(x)); private direntPointerToString(x) = String(Pointer[Int8](&x^.d_name)); // // DirentSequence // private record DirentSequence { dirp : Pointer[DIR]; } [T | String?(T)] direntSequence(x:T) = DirentSequence(cstring(x)); overload DirentSequence(x:Pointer[CChar]) { var ret = DirentSequence(opendir(x)); if (null?(ret.dirp)) { throw errno(); } return ret; } overload iterator(x:DirentSequence) = DirentIterator(x.dirp, false, null(Struct_dirent)); // // DirentIterator // private record DirentIterator { dirp : Pointer[DIR]; queued? : Bool; entry : Pointer[Struct_dirent]; } overload destroy(x:DirentIterator) { if (closedir(x.dirp) > 0) throw errno(); } overload hasNext?(x:DirentIterator) { if (not x.queued?) { x.queued? = true; if (not(null?(x.entry))) destroy(x.entry); var returnCode = readdir_r(x.dirp, allocateMemory(Struct_dirent, 1), &x.entry); if (returnCode != 0) throw returnCode; } return not(null?(x.entry)); } overload next(x:DirentIterator) { if (not x.queued?) hasNext?(x); x.queued? = false; return x.entry; }