mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-12 22:58:40 +01:00
File.stat().
This commit is contained in:
@ -4,4 +4,5 @@ Provides access to operating system streams and the file system.
|
||||
|
||||
* [Directory](directory.html)
|
||||
* [File](file.html)
|
||||
* [Stat](stat.html)
|
||||
* [Stdin](stdin.html)
|
||||
|
||||
50
doc/site/modules/io/stat.markdown
Normal file
50
doc/site/modules/io/stat.markdown
Normal file
@ -0,0 +1,50 @@
|
||||
^title Stat Class
|
||||
|
||||
Contains the data returned by [File.stat()][stat].
|
||||
|
||||
[stat]: file.html#file.stat(path)
|
||||
|
||||
## Methods
|
||||
|
||||
### **device**
|
||||
|
||||
The ID of the device containing the entry.
|
||||
|
||||
### **inode**
|
||||
|
||||
The [inode][] number of the entry.
|
||||
|
||||
[inode]: https://en.wikipedia.org/wiki/Inode
|
||||
|
||||
### **mode**
|
||||
|
||||
A bit field describing the entry's type and protection flags.
|
||||
|
||||
### **linkCount**
|
||||
|
||||
The number of hard links to the entry.
|
||||
|
||||
### **user**
|
||||
|
||||
Numeric user ID of the file's owner.
|
||||
|
||||
### **group**
|
||||
|
||||
Numeric group ID of the file's owner.
|
||||
|
||||
### **specialDevice**
|
||||
|
||||
The device ID for the entry, if it's a special file.
|
||||
|
||||
### **size**
|
||||
|
||||
The size of the entry in bytes.
|
||||
|
||||
### **blockSize**
|
||||
|
||||
The preferred block size in bytes for interacting with the file. It may vary
|
||||
from file to file.
|
||||
|
||||
### **blockCount**
|
||||
|
||||
The number of system blocks allocated on disk for the file.
|
||||
@ -12,6 +12,7 @@ extern void fileAllocate(WrenVM* vm);
|
||||
extern void fileFinalize(void* data);
|
||||
extern void fileOpen(WrenVM* vm);
|
||||
extern void fileSizePath(WrenVM* vm);
|
||||
extern void fileStatPath(WrenVM* vm);
|
||||
extern void fileClose(WrenVM* vm);
|
||||
extern void fileDescriptor(WrenVM* vm);
|
||||
extern void fileReadBytes(WrenVM* vm);
|
||||
@ -29,7 +30,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 9
|
||||
#define MAX_METHODS_PER_CLASS 10
|
||||
|
||||
// The maximum number of foreign classes a single built-in module defines.
|
||||
//
|
||||
@ -97,6 +98,7 @@ static ModuleRegistry modules[] =
|
||||
FINALIZER(fileFinalize)
|
||||
STATIC_METHOD("open_(_,_)", fileOpen)
|
||||
STATIC_METHOD("sizePath_(_,_)", fileSizePath)
|
||||
STATIC_METHOD("statPath_(_,_)", fileStatPath)
|
||||
METHOD("close_(_)", fileClose)
|
||||
METHOD("descriptor", fileDescriptor)
|
||||
METHOD("readBytes_(_,_,_)", fileReadBytes)
|
||||
|
||||
@ -188,6 +188,62 @@ void fileSizePath(WrenVM* vm)
|
||||
uv_fs_stat(getLoop(), request, path, fileSizeCallback);
|
||||
}
|
||||
|
||||
// Called by libuv when the stat call completes.
|
||||
static void fileStatPathCallback(uv_fs_t* request)
|
||||
{
|
||||
if (handleRequestError(request)) return;
|
||||
|
||||
WrenVM* vm = getVM();
|
||||
wrenEnsureSlots(vm, 4);
|
||||
wrenSetSlotNewList(vm, 2);
|
||||
|
||||
wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_dev);
|
||||
wrenInsertInList(vm, 2, -1, 3);
|
||||
|
||||
wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_ino);
|
||||
wrenInsertInList(vm, 2, -1, 3);
|
||||
|
||||
wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_mode);
|
||||
wrenInsertInList(vm, 2, -1, 3);
|
||||
|
||||
wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_nlink);
|
||||
wrenInsertInList(vm, 2, -1, 3);
|
||||
|
||||
wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_uid);
|
||||
wrenInsertInList(vm, 2, -1, 3);
|
||||
|
||||
wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_gid);
|
||||
wrenInsertInList(vm, 2, -1, 3);
|
||||
|
||||
wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_rdev);
|
||||
wrenInsertInList(vm, 2, -1, 3);
|
||||
|
||||
wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_size);
|
||||
wrenInsertInList(vm, 2, -1, 3);
|
||||
|
||||
wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_blksize);
|
||||
wrenInsertInList(vm, 2, -1, 3);
|
||||
|
||||
wrenSetSlotDouble(vm, 3, (double)request->statbuf.st_blocks);
|
||||
wrenInsertInList(vm, 2, -1, 3);
|
||||
|
||||
// TODO: Include access, modification, and change times once we figure out
|
||||
// how we want to represent it.
|
||||
// time_t st_atime; /* time of last access */
|
||||
// time_t st_mtime; /* time of last modification */
|
||||
// time_t st_ctime; /* time of last status change */
|
||||
|
||||
schedulerResume(freeRequest(request), true);
|
||||
schedulerFinishResume();
|
||||
}
|
||||
|
||||
void fileStatPath(WrenVM* vm)
|
||||
{
|
||||
const char* path = wrenGetSlotString(vm, 1);
|
||||
uv_fs_t* request = createRequest(wrenGetSlotValue(vm, 2));
|
||||
uv_fs_stat(getLoop(), request, path, fileStatPathCallback);
|
||||
}
|
||||
|
||||
static void fileCloseCallback(uv_fs_t* request)
|
||||
{
|
||||
if (handleRequestError(request)) return;
|
||||
|
||||
@ -44,6 +44,13 @@ foreign class File {
|
||||
return Scheduler.runNextScheduled_()
|
||||
}
|
||||
|
||||
static stat(path) {
|
||||
if (!(path is String)) Fiber.abort("Path must be a string.")
|
||||
|
||||
statPath_(path, Fiber.current)
|
||||
return Stat.new_(Scheduler.runNextScheduled_())
|
||||
}
|
||||
|
||||
construct new_(fd) {}
|
||||
|
||||
close() {
|
||||
@ -80,12 +87,30 @@ foreign class File {
|
||||
|
||||
foreign static open_(path, fiber)
|
||||
foreign static sizePath_(path, fiber)
|
||||
foreign static statPath_(path, fiber)
|
||||
|
||||
foreign close_(fiber)
|
||||
foreign readBytes_(count, start, fiber)
|
||||
foreign size_(fiber)
|
||||
}
|
||||
|
||||
class Stat {
|
||||
construct new_(fields) {
|
||||
_fields = fields
|
||||
}
|
||||
|
||||
device { _fields[0] }
|
||||
inode { _fields[1] }
|
||||
mode { _fields[2] }
|
||||
linkCount { _fields[3] }
|
||||
user { _fields[4] }
|
||||
group { _fields[5] }
|
||||
specialDevice { _fields[6] }
|
||||
size { _fields[7] }
|
||||
blockSize { _fields[8] }
|
||||
blockCount { _fields[9] }
|
||||
}
|
||||
|
||||
class Stdin {
|
||||
static readLine() {
|
||||
if (__isClosed == true) {
|
||||
|
||||
@ -46,6 +46,13 @@ static const char* ioModuleSource =
|
||||
" return Scheduler.runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static stat(path) {\n"
|
||||
" if (!(path is String)) Fiber.abort(\"Path must be a string.\")\n"
|
||||
"\n"
|
||||
" statPath_(path, Fiber.current)\n"
|
||||
" return Stat.new_(Scheduler.runNextScheduled_())\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" construct new_(fd) {}\n"
|
||||
"\n"
|
||||
" close() {\n"
|
||||
@ -82,12 +89,30 @@ static const char* ioModuleSource =
|
||||
"\n"
|
||||
" foreign static open_(path, fiber)\n"
|
||||
" foreign static sizePath_(path, fiber)\n"
|
||||
" foreign static statPath_(path, fiber)\n"
|
||||
"\n"
|
||||
" foreign close_(fiber)\n"
|
||||
" foreign readBytes_(count, start, fiber)\n"
|
||||
" foreign size_(fiber)\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class Stat {\n"
|
||||
" construct new_(fields) {\n"
|
||||
" _fields = fields\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" device { _fields[0] }\n"
|
||||
" inode { _fields[1] }\n"
|
||||
" mode { _fields[2] }\n"
|
||||
" linkCount { _fields[3] }\n"
|
||||
" user { _fields[4] }\n"
|
||||
" group { _fields[5] }\n"
|
||||
" specialDevice { _fields[6] }\n"
|
||||
" size { _fields[7] }\n"
|
||||
" blockSize { _fields[8] }\n"
|
||||
" blockCount { _fields[9] }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class Stdin {\n"
|
||||
" static readLine() {\n"
|
||||
" if (__isClosed == true) {\n"
|
||||
|
||||
@ -1,13 +1,6 @@
|
||||
import "io" for File
|
||||
import "scheduler" for Scheduler
|
||||
|
||||
System.print(File.size("test/io/file/size.wren")) // expect: 270
|
||||
|
||||
// Runs asynchronously.
|
||||
Scheduler.add {
|
||||
System.print("async")
|
||||
}
|
||||
|
||||
System.print(File.size("test/io/file/size.wren"))
|
||||
// expect: async
|
||||
// expect: 270
|
||||
var file = File.open("test/io/file/file.txt")
|
||||
System.print(file.size) // expect: 19
|
||||
file.close()
|
||||
|
||||
13
test/io/file/size_static.wren
Normal file
13
test/io/file/size_static.wren
Normal file
@ -0,0 +1,13 @@
|
||||
import "io" for File
|
||||
import "scheduler" for Scheduler
|
||||
|
||||
System.print(File.size("test/io/file/file.txt")) // expect: 19
|
||||
|
||||
// Runs asynchronously.
|
||||
Scheduler.add {
|
||||
System.print("async")
|
||||
}
|
||||
|
||||
System.print(File.size("test/io/file/file.txt"))
|
||||
// expect: async
|
||||
// expect: 19
|
||||
16
test/io/file/stat_static.wren
Normal file
16
test/io/file/stat_static.wren
Normal file
@ -0,0 +1,16 @@
|
||||
import "io" for File, Stat
|
||||
import "scheduler" for Scheduler
|
||||
|
||||
var stat = File.stat("test/io/file/file.txt")
|
||||
|
||||
System.print(stat is Stat) // expect: true
|
||||
System.print(stat.device is Num) // expect: true
|
||||
System.print(stat.inode is Num) // expect: true
|
||||
System.print(stat.mode is Num) // expect: true
|
||||
System.print(stat.linkCount) // expect: 1
|
||||
System.print(stat.user is Num) // expect: true
|
||||
System.print(stat.group is Num) // expect: true
|
||||
System.print(stat.specialDevice) // expect: 0
|
||||
System.print(stat.size) // expect: 19
|
||||
System.print(stat.blockSize is Num) // expect: true
|
||||
System.print(stat.blockCount is Num) // expect: true
|
||||
3
test/io/file/stat_static_nonexistent.wren
Normal file
3
test/io/file/stat_static_nonexistent.wren
Normal file
@ -0,0 +1,3 @@
|
||||
import "io" for File
|
||||
|
||||
File.stat("nonexistent") // expect runtime error: no such file or directory
|
||||
Reference in New Issue
Block a user