feat: add Stat.isFile, Stat.isDirectory, File.exists, and Directory.exists methods

Add four new file system checking functions: Stat.isFile and Stat.isDirectory for querying entry type from a Stat object, and File.exists and Directory.exists static methods that return booleans by attempting to stat the path and checking the appropriate type. Also bump MAX_METHODS_PER_CLASS from 12 to 14 to accommodate the new Stat foreign methods, and clean up unused Scheduler imports in existing stat tests.
This commit is contained in:
Bob Nystrom
2016-02-21 20:23:33 +00:00
parent 7f744565fc
commit 1973934fa2
15 changed files with 149 additions and 28 deletions
+5 -1
View File
@@ -32,6 +32,8 @@ extern void statMode(WrenVM* vm);
extern void statSize(WrenVM* vm);
extern void statSpecialDevice(WrenVM* vm);
extern void statUser(WrenVM* vm);
extern void statIsDirectory(WrenVM* vm);
extern void statIsFile(WrenVM* vm);
extern void stdinReadStart(WrenVM* vm);
extern void stdinReadStop(WrenVM* vm);
extern void schedulerCaptureMethods(WrenVM* vm);
@@ -45,7 +47,7 @@ extern void timerStartTimer(WrenVM* vm);
// If you add a new method to the longest class below, make sure to bump this.
// Note that it also includes an extra slot for the sentinel value indicating
// the end of the list.
#define MAX_METHODS_PER_CLASS 12
#define MAX_METHODS_PER_CLASS 14
// The maximum number of foreign classes a single built-in module defines.
//
@@ -133,6 +135,8 @@ static ModuleRegistry modules[] =
METHOD("size", statSize)
METHOD("specialDevice", statSpecialDevice)
METHOD("user", statUser)
METHOD("isDirectory", statIsDirectory)
METHOD("isFile", statIsFile)
END_CLASS
CLASS(Stdin)
STATIC_METHOD("readStart_()", stdinReadStart)
+12
View File
@@ -442,6 +442,18 @@ void statUser(WrenVM* vm)
wrenSetSlotDouble(vm, 0, (double)stat->st_uid);
}
void statIsDirectory(WrenVM* vm)
{
uv_stat_t* stat = (uv_stat_t*)wrenGetSlotForeign(vm, 0);
wrenSetSlotBool(vm, 0, S_ISDIR(stat->st_mode));
}
void statIsFile(WrenVM* vm)
{
uv_stat_t* stat = (uv_stat_t*)wrenGetSlotForeign(vm, 0);
wrenSetSlotBool(vm, 0, S_ISREG(stat->st_mode));
}
static void allocCallback(uv_handle_t* handle, size_t suggestedSize,
uv_buf_t* buf)
{
+32 -4
View File
@@ -6,6 +6,18 @@ class Directory {
if (!(path is String)) Fiber.abort("Path must be a string.")
}
static exists(path) {
ensurePath_(path)
var stat
Fiber.new {
stat = Stat.path(path)
}.try()
// If we can't stat it, there's nothing there.
if (stat == null) return false
return stat.isDirectory
}
static list(path) {
ensurePath_(path)
list_(path, Fiber.current)
@@ -31,11 +43,23 @@ foreign class File {
}
static delete(path) {
File.ensurePath_(path)
ensurePath_(path)
delete_(path, Fiber.current)
return Scheduler.runNextScheduled_()
}
static exists(path) {
ensurePath_(path)
var stat
Fiber.new {
stat = Stat.path(path)
}.try()
// If we can't stat it, there's nothing there.
if (stat == null) return false
return stat.isFile
}
static open(path) { openWithFlags(path, FileFlags.readOnly) }
static open(path, fn) { openWithFlags(path, FileFlags.readOnly, fn) }
@@ -43,8 +67,8 @@ foreign class File {
// TODO: Add named parameters and then call this "open(_,flags:_)"?
// TODO: Test.
static openWithFlags(path, flags) {
File.ensurePath_(path)
File.ensureInt_(flags, "Flags")
ensurePath_(path)
ensureInt_(flags, "Flags")
open_(path, flags, Fiber.current)
var fd = Scheduler.runNextScheduled_()
return new_(fd)
@@ -68,7 +92,7 @@ foreign class File {
}
static size(path) {
File.ensurePath_(path)
ensurePath_(path)
sizePath_(path, Fiber.current)
return Scheduler.runNextScheduled_()
}
@@ -175,6 +199,10 @@ foreign class Stat {
foreign size
foreign specialDevice
foreign user
foreign isFile
foreign isDirectory
// TODO: Other mode checks.
}
class Stdin {
+32 -4
View File
@@ -8,6 +8,18 @@ static const char* ioModuleSource =
" if (!(path is String)) Fiber.abort(\"Path must be a string.\")\n"
" }\n"
"\n"
" static exists(path) {\n"
" ensurePath_(path)\n"
" var stat\n"
" Fiber.new {\n"
" stat = Stat.path(path)\n"
" }.try()\n"
"\n"
" // If we can't stat it, there's nothing there.\n"
" if (stat == null) return false\n"
" return stat.isDirectory\n"
" }\n"
"\n"
" static list(path) {\n"
" ensurePath_(path)\n"
" list_(path, Fiber.current)\n"
@@ -33,11 +45,23 @@ static const char* ioModuleSource =
" }\n"
"\n"
" static delete(path) {\n"
" File.ensurePath_(path)\n"
" ensurePath_(path)\n"
" delete_(path, Fiber.current)\n"
" return Scheduler.runNextScheduled_()\n"
" }\n"
"\n"
" static exists(path) {\n"
" ensurePath_(path)\n"
" var stat\n"
" Fiber.new {\n"
" stat = Stat.path(path)\n"
" }.try()\n"
"\n"
" // If we can't stat it, there's nothing there.\n"
" if (stat == null) return false\n"
" return stat.isFile\n"
" }\n"
"\n"
" static open(path) { openWithFlags(path, FileFlags.readOnly) }\n"
"\n"
" static open(path, fn) { openWithFlags(path, FileFlags.readOnly, fn) }\n"
@@ -45,8 +69,8 @@ static const char* ioModuleSource =
" // TODO: Add named parameters and then call this \"open(_,flags:_)\"?\n"
" // TODO: Test.\n"
" static openWithFlags(path, flags) {\n"
" File.ensurePath_(path)\n"
" File.ensureInt_(flags, \"Flags\")\n"
" ensurePath_(path)\n"
" ensureInt_(flags, \"Flags\")\n"
" open_(path, flags, Fiber.current)\n"
" var fd = Scheduler.runNextScheduled_()\n"
" return new_(fd)\n"
@@ -70,7 +94,7 @@ static const char* ioModuleSource =
" }\n"
"\n"
" static size(path) {\n"
" File.ensurePath_(path)\n"
" ensurePath_(path)\n"
" sizePath_(path, Fiber.current)\n"
" return Scheduler.runNextScheduled_()\n"
" }\n"
@@ -177,6 +201,10 @@ static const char* ioModuleSource =
" foreign size\n"
" foreign specialDevice\n"
" foreign user\n"
"\n"
" foreign isFile\n"
" foreign isDirectory\n"
" // TODO: Other mode checks.\n"
"}\n"
"\n"
"class Stdin {\n"