mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-11 06:08:41 +01:00
Add an optional offset to File.readBytes().
This commit is contained in:
@ -12,7 +12,7 @@ a file descriptor.
|
||||
|
||||
### File.**open**(path, fn)
|
||||
|
||||
Opens the file at [path] and passes it to [fn]. After the function returns, the
|
||||
Opens the file at `path` and passes it to `fn`. After the function returns, the
|
||||
file is automatically closed.
|
||||
|
||||
:::wren
|
||||
@ -22,7 +22,7 @@ file is automatically closed.
|
||||
|
||||
### File.**read**(path)
|
||||
|
||||
Reads the entire contents of the file at [path] and returns it as a string.
|
||||
Reads the entire contents of the file at `path` and returns it as a string.
|
||||
|
||||
:::wren
|
||||
File.read("words.txt")
|
||||
@ -33,13 +33,13 @@ whatever encoding the file uses.
|
||||
|
||||
### File.**size**(path)
|
||||
|
||||
Returns the size in bytes of the contents of the file at [path].
|
||||
Returns the size in bytes of the contents of the file at `path`.
|
||||
|
||||
## Constructors
|
||||
|
||||
### File.**open**(path)
|
||||
|
||||
Opens the file at [path] for reading.
|
||||
Opens the file at `path` for reading.
|
||||
|
||||
## Methods
|
||||
|
||||
@ -61,6 +61,21 @@ Closes the file. After calling this, you can read or write from it.
|
||||
|
||||
### **readBytes**(count)
|
||||
|
||||
Reads up to [count] bytes starting from the beginning of the file.
|
||||
Reads up to `count` bytes starting from the beginning of the file.
|
||||
|
||||
(Allowing an offset to read elsewhere from the file isn't implemented yet.)
|
||||
:::wren
|
||||
// Assume this file contains "I am a file!".
|
||||
File.open("example.txt") {|file|
|
||||
System.print(file.readBytes(6)) //> I am a
|
||||
}
|
||||
|
||||
### **readBytes**(count, offset)
|
||||
|
||||
Reads up to `count` bytes starting at `offset` bytes from the beginning of
|
||||
the file.
|
||||
|
||||
:::wren
|
||||
// Assume this file contains "I am a file!".
|
||||
File.open("example.txt") {|file|
|
||||
System.print(file.readBytes(6, 2)) //> am a f
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ static ModuleRegistry modules[] =
|
||||
STATIC_METHOD("sizePath_(_,_)", fileSizePath)
|
||||
METHOD("close_(_)", fileClose)
|
||||
METHOD("descriptor", fileDescriptor)
|
||||
METHOD("readBytes_(_,_)", fileReadBytes)
|
||||
METHOD("readBytes_(_,_,_)", fileReadBytes)
|
||||
METHOD("size_(_)", fileSize)
|
||||
END_CLASS
|
||||
CLASS(Stdin)
|
||||
|
||||
@ -228,12 +228,13 @@ static void fileReadBytesCallback(uv_fs_t* request)
|
||||
|
||||
FileRequestData* data = (FileRequestData*)request->data;
|
||||
uv_buf_t buffer = data->buffer;
|
||||
size_t count = request->result;
|
||||
|
||||
// TODO: Having to copy the bytes here is a drag. It would be good if Wren's
|
||||
// embedding API supported a way to *give* it bytes that were previously
|
||||
// allocated using Wren's own allocator.
|
||||
schedulerResume(freeRequest(request), true);
|
||||
wrenSetSlotBytes(getVM(), 2, buffer.base, buffer.len);
|
||||
wrenSetSlotBytes(getVM(), 2, buffer.base, count);
|
||||
schedulerFinishResume();
|
||||
|
||||
// TODO: Likewise, freeing this after we resume is lame.
|
||||
@ -242,19 +243,20 @@ static void fileReadBytesCallback(uv_fs_t* request)
|
||||
|
||||
void fileReadBytes(WrenVM* vm)
|
||||
{
|
||||
uv_fs_t* request = createRequest(wrenGetSlotValue(vm, 2));
|
||||
uv_fs_t* request = createRequest(wrenGetSlotValue(vm, 3));
|
||||
|
||||
int fd = *(int*)wrenGetSlotForeign(vm, 0);
|
||||
// TODO: Assert fd != -1.
|
||||
|
||||
FileRequestData* data = (FileRequestData*)request->data;
|
||||
size_t length = (size_t)wrenGetSlotDouble(vm, 1);
|
||||
size_t offset = (size_t)wrenGetSlotDouble(vm, 2);
|
||||
|
||||
data->buffer.len = length;
|
||||
data->buffer.base = (char*)malloc(length);
|
||||
|
||||
// TODO: Allow passing in offset.
|
||||
uv_fs_read(getLoop(), request, fd, &data->buffer, 1, 0, fileReadBytesCallback);
|
||||
uv_fs_read(getLoop(), request, fd, &data->buffer, 1, offset,
|
||||
fileReadBytesCallback);
|
||||
}
|
||||
|
||||
void fileSize(WrenVM* vm)
|
||||
|
||||
@ -62,13 +62,19 @@ foreign class File {
|
||||
return Scheduler.runNextScheduled_()
|
||||
}
|
||||
|
||||
readBytes(count) {
|
||||
readBytes(count) { readBytes(count, 0) }
|
||||
|
||||
readBytes(count, offset) {
|
||||
if (!isOpen) Fiber.abort("File is not open.")
|
||||
if (!(count is Num)) Fiber.abort("Count must be an integer.")
|
||||
if (!count.isInteger) Fiber.abort("Count must be an integer.")
|
||||
if (count < 0) Fiber.abort("Count cannot be negative.")
|
||||
|
||||
readBytes_(count, Fiber.current)
|
||||
if (!(offset is Num)) Fiber.abort("Offset must be an integer.")
|
||||
if (!offset.isInteger) Fiber.abort("Offset must be an integer.")
|
||||
if (offset < 0) Fiber.abort("Offset cannot be negative.")
|
||||
|
||||
readBytes_(count, offset, Fiber.current)
|
||||
return Scheduler.runNextScheduled_()
|
||||
}
|
||||
|
||||
@ -76,7 +82,7 @@ foreign class File {
|
||||
foreign static sizePath_(path, fiber)
|
||||
|
||||
foreign close_(fiber)
|
||||
foreign readBytes_(count, fiber)
|
||||
foreign readBytes_(count, start, fiber)
|
||||
foreign size_(fiber)
|
||||
}
|
||||
|
||||
|
||||
@ -53,6 +53,8 @@ static const char* ioModuleSource =
|
||||
" Scheduler.runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" foreign descriptor\n"
|
||||
"\n"
|
||||
" isOpen { descriptor != -1 }\n"
|
||||
"\n"
|
||||
" size {\n"
|
||||
@ -62,13 +64,19 @@ static const char* ioModuleSource =
|
||||
" return Scheduler.runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" readBytes(count) {\n"
|
||||
" readBytes(count) { readBytes(count, 0) }\n"
|
||||
"\n"
|
||||
" readBytes(count, offset) {\n"
|
||||
" if (!isOpen) Fiber.abort(\"File is not open.\")\n"
|
||||
" if (!(count is Num)) Fiber.abort(\"Count must be an integer.\")\n"
|
||||
" if (!count.isInteger) Fiber.abort(\"Count must be an integer.\")\n"
|
||||
" if (count < 0) Fiber.abort(\"Count cannot be negative.\")\n"
|
||||
"\n"
|
||||
" readBytes_(count, Fiber.current)\n"
|
||||
" if (!(offset is Num)) Fiber.abort(\"Offset must be an integer.\")\n"
|
||||
" if (!offset.isInteger) Fiber.abort(\"Offset must be an integer.\")\n"
|
||||
" if (offset < 0) Fiber.abort(\"Offset cannot be negative.\")\n"
|
||||
"\n"
|
||||
" readBytes_(count, offset, Fiber.current)\n"
|
||||
" return Scheduler.runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
@ -76,8 +84,7 @@ static const char* ioModuleSource =
|
||||
" foreign static sizePath_(path, fiber)\n"
|
||||
"\n"
|
||||
" foreign close_(fiber)\n"
|
||||
" foreign descriptor\n"
|
||||
" foreign readBytes_(count, fiber)\n"
|
||||
" foreign readBytes_(count, start, fiber)\n"
|
||||
" foreign size_(fiber)\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
|
||||
@ -10,4 +10,10 @@ System.print(file.readBytes(7)) // expect: this is
|
||||
// Allows zero.
|
||||
System.print(file.readBytes(0).bytes.count) // expect: 0
|
||||
|
||||
// A longer number reads the whole file.
|
||||
System.print(file.readBytes(100)) // expect: this is a text file
|
||||
|
||||
// Reading past the end truncates the buffer.
|
||||
System.print(file.readBytes(100).bytes.count) // expect: 19
|
||||
|
||||
file.close()
|
||||
|
||||
20
test/io/file/read_bytes_from.wren
Normal file
20
test/io/file/read_bytes_from.wren
Normal file
@ -0,0 +1,20 @@
|
||||
import "io" for File
|
||||
|
||||
var file = File.open("test/io/file/file.txt")
|
||||
|
||||
// Zero starts at the beginning.
|
||||
System.print(file.readBytes(3, 0)) // expect: thi
|
||||
|
||||
// Starts at the offset.
|
||||
System.print(file.readBytes(8, 3)) // expect: s is a t
|
||||
|
||||
// Allows zero.
|
||||
System.print(file.readBytes(0, 4).bytes.count) // expect: 0
|
||||
|
||||
// A longer number length reads until the end.
|
||||
System.print(file.readBytes(100, 2)) // expect: is is a text file
|
||||
|
||||
// An offset past the end returns an empty string.
|
||||
System.print(file.readBytes(100, 30).bytes.count) // expect: 0
|
||||
|
||||
file.close()
|
||||
6
test/io/file/read_bytes_from_after_close.wren
Normal file
6
test/io/file/read_bytes_from_after_close.wren
Normal file
@ -0,0 +1,6 @@
|
||||
import "io" for File
|
||||
|
||||
var file = File.open("test/io/file/file.txt")
|
||||
file.close()
|
||||
|
||||
file.readBytes(3, 0) // expect runtime error: File is not open.
|
||||
4
test/io/file/read_bytes_from_count_negative.wren
Normal file
4
test/io/file/read_bytes_from_count_negative.wren
Normal file
@ -0,0 +1,4 @@
|
||||
import "io" for File
|
||||
|
||||
var file = File.open("test/io/file/file.txt")
|
||||
file.readBytes(-1, 0) // expect runtime error: Count cannot be negative.
|
||||
4
test/io/file/read_bytes_from_count_not_integer.wren
Normal file
4
test/io/file/read_bytes_from_count_not_integer.wren
Normal file
@ -0,0 +1,4 @@
|
||||
import "io" for File
|
||||
|
||||
var file = File.open("test/io/file/file.txt")
|
||||
file.readBytes(1.2, 0) // expect runtime error: Count must be an integer.
|
||||
4
test/io/file/read_bytes_from_count_not_num.wren
Normal file
4
test/io/file/read_bytes_from_count_not_num.wren
Normal file
@ -0,0 +1,4 @@
|
||||
import "io" for File
|
||||
|
||||
var file = File.open("test/io/file/file.txt")
|
||||
file.readBytes("not num", 0) // expect runtime error: Count must be an integer.
|
||||
4
test/io/file/read_bytes_from_offset_negative.wren
Normal file
4
test/io/file/read_bytes_from_offset_negative.wren
Normal file
@ -0,0 +1,4 @@
|
||||
import "io" for File
|
||||
|
||||
var file = File.open("test/io/file/file.txt")
|
||||
file.readBytes(1, -1) // expect runtime error: Offset cannot be negative.
|
||||
4
test/io/file/read_bytes_from_offset_not_integer.wren
Normal file
4
test/io/file/read_bytes_from_offset_not_integer.wren
Normal file
@ -0,0 +1,4 @@
|
||||
import "io" for File
|
||||
|
||||
var file = File.open("test/io/file/file.txt")
|
||||
file.readBytes(1, 1.2) // expect runtime error: Offset must be an integer.
|
||||
4
test/io/file/read_bytes_from_offset_not_num.wren
Normal file
4
test/io/file/read_bytes_from_offset_not_num.wren
Normal file
@ -0,0 +1,4 @@
|
||||
import "io" for File
|
||||
|
||||
var file = File.open("test/io/file/file.txt")
|
||||
file.readBytes(1, "not num") // expect runtime error: Offset must be an integer.
|
||||
Reference in New Issue
Block a user