Skip to content

Commit 6d2a9ba

Browse files
authored
Improve std file read/write ergonomics (#1365)
- make `pos` and `len` arguments optional - accept strings in file.write()
1 parent 3eb0605 commit 6d2a9ba

3 files changed

Lines changed: 41 additions & 14 deletions

File tree

docs/docs/stdlib.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -566,15 +566,15 @@ Return true if there was an error.
566566

567567
Clear the error indication.
568568

569-
#### `read(buffer, position, length)`
569+
#### `read(buffer, position = 0, length = buffer.length)`
570570

571571
Read `length` bytes from the file to the ArrayBuffer `buffer` at byte
572-
position `position` (wrapper to the libc `fread`).
572+
position `position`. Wrapper to the libc function `fread`.
573573

574-
#### `write(buffer, position, length)`
574+
#### `write(buffer, position = 0, length = buffer.length)`
575575

576-
Write `length` bytes to the file from the ArrayBuffer `buffer` at byte
577-
position `position` (wrapper to the libc `fwrite`).
576+
Write `length` bytes to the file from the ArrayBuffer or string `buffer`
577+
at byte position `position`. Wrapper to the libc function `fwrite`.
578578

579579
#### `getline()`
580580

quickjs-libc.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,25 +1519,41 @@ static JSValue js_std_file_read_write(JSContext *ctx, JSValueConst this_val,
15191519
int argc, JSValueConst *argv, int magic)
15201520
{
15211521
FILE *f = js_std_file_get(ctx, this_val);
1522+
bool is_write = (magic != 0);
15221523
uint64_t pos, len;
15231524
size_t size, ret;
1525+
const char *str;
15241526
uint8_t *buf;
15251527

15261528
if (!f)
15271529
return JS_EXCEPTION;
1528-
if (JS_ToIndex(ctx, &pos, argv[1]))
1530+
pos = 0;
1531+
if (argc > 1 && JS_ToIndex(ctx, &pos, argv[1]))
15291532
return JS_EXCEPTION;
1530-
if (JS_ToIndex(ctx, &len, argv[2]))
1533+
len = 0;
1534+
if (argc > 2 && JS_ToIndex(ctx, &len, argv[2]))
15311535
return JS_EXCEPTION;
1532-
buf = JS_GetArrayBuffer(ctx, &size, argv[0]);
1536+
if (is_write && JS_IsString(argv[0])) {
1537+
str = JS_ToCStringLen(ctx, &size, argv[0]);
1538+
buf = (void *)str;
1539+
} else {
1540+
str = NULL;
1541+
buf = JS_GetArrayBuffer(ctx, &size, argv[0]);
1542+
}
15331543
if (!buf)
15341544
return JS_EXCEPTION;
1545+
if (pos > size)
1546+
pos = size;
1547+
if (argc < 3)
1548+
len = size - pos;
15351549
if (pos + len > size)
1536-
return JS_ThrowRangeError(ctx, "read/write array buffer overflow");
1537-
if (magic)
1550+
len = size - pos;
1551+
if (is_write) {
15381552
ret = fwrite(buf + pos, 1, len, f);
1539-
else
1553+
} else {
15401554
ret = fread(buf + pos, 1, len, f);
1555+
}
1556+
JS_FreeCString(ctx, str);
15411557
return JS_NewInt64(ctx, ret);
15421558
}
15431559

@@ -1909,8 +1925,8 @@ static const JSCFunctionListEntry js_std_file_proto_funcs[] = {
19091925
JS_CFUNC_DEF("fileno", 0, js_std_file_fileno ),
19101926
JS_CFUNC_DEF("error", 0, js_std_file_error ),
19111927
JS_CFUNC_DEF("clearerr", 0, js_std_file_clearerr ),
1912-
JS_CFUNC_MAGIC_DEF("read", 3, js_std_file_read_write, 0 ),
1913-
JS_CFUNC_MAGIC_DEF("write", 3, js_std_file_read_write, 1 ),
1928+
JS_CFUNC_MAGIC_DEF("read", 1, js_std_file_read_write, 0 ),
1929+
JS_CFUNC_MAGIC_DEF("write", 1, js_std_file_read_write, 1 ),
19141930
JS_CFUNC_DEF("getline", 0, js_std_file_getline ),
19151931
JS_CFUNC_MAGIC_DEF("readAsArrayBuffer", 0, js_std_file_readAs, 0 ),
19161932
JS_CFUNC_MAGIC_DEF("readAsString", 0, js_std_file_readAs, 1 ),

tests/test_std.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,18 @@ function test_os()
223223
[fpath, fd] = os.mkstemp(`${fdir}/XXXXXX`);
224224
assert(fdir.startsWith(`${fdir}`));
225225
assert(fd >= 0);
226-
os.close(fd);
226+
227+
const f = std.fdopen(fd, "w+");
228+
f.write("xyzzy");
229+
f.flush();
230+
const b = new Uint8Array(5);
231+
f.seek(0, std.SEEK_SET);
232+
assert(5, f.read(b.buffer));
233+
const s = [...b].map(c => String.fromCharCode(c)).join("");
234+
assert(s, "xyzzy");
235+
f.seek(0, std.SEEK_SET);
236+
assert(0, f.read(b.buffer, 5, 42));
237+
f.close();
227238

228239
assert(os.remove(fpath), 0);
229240
assert(os.remove(fdir), 0);

0 commit comments

Comments
 (0)