zero copy blob
This commit is contained in:
@@ -102,18 +102,15 @@ JSC_CCALL(fd_read,
|
||||
if (argc > 1)
|
||||
size = js2number(js, argv[1]);
|
||||
|
||||
void *buf = malloc(size);
|
||||
if (!buf)
|
||||
return JS_RaiseDisrupt(js, "malloc failed");
|
||||
|
||||
ssize_t bytes_read = read(fd, buf, size);
|
||||
if (bytes_read < 0) {
|
||||
free(buf);
|
||||
void *out;
|
||||
ret = js_new_blob_alloc(js, size, &out);
|
||||
if (JS_IsException(ret)) return ret;
|
||||
|
||||
ssize_t bytes_read = read(fd, out, size);
|
||||
if (bytes_read < 0)
|
||||
return JS_RaiseDisrupt(js, "read failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
ret = js_new_blob_stoned_copy(js, buf, bytes_read);
|
||||
free(buf);
|
||||
|
||||
js_blob_stone(ret, bytes_read);
|
||||
return ret;
|
||||
)
|
||||
|
||||
@@ -128,39 +125,48 @@ JSC_SCALL(fd_slurp,
|
||||
size_t size = st.st_size;
|
||||
if (size == 0)
|
||||
return js_new_blob_stoned_copy(js, NULL, 0);
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
int fd = open(str, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return JS_RaiseDisrupt(js, "open failed: %s", strerror(errno));
|
||||
|
||||
void *data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (data == MAP_FAILED) {
|
||||
close(fd);
|
||||
return JS_RaiseDisrupt(js, "mmap failed: %s", strerror(errno));
|
||||
|
||||
void *out;
|
||||
ret = js_new_blob_alloc(js, size, &out);
|
||||
if (JS_IsException(ret)) { close(fd); return ret; }
|
||||
|
||||
size_t total = 0;
|
||||
while (total < size) {
|
||||
ssize_t n = read(fd, (uint8_t *)out + total, size - total);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR) continue;
|
||||
close(fd);
|
||||
return JS_RaiseDisrupt(js, "read failed: %s", strerror(errno));
|
||||
}
|
||||
if (n == 0) break;
|
||||
total += n;
|
||||
}
|
||||
ret = js_new_blob_stoned_copy(js, data, size);
|
||||
munmap(data, size);
|
||||
close(fd);
|
||||
js_blob_stone(ret, total);
|
||||
#else
|
||||
// Windows: use memory mapping for optimal performance
|
||||
HANDLE hFile = CreateFileA(str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return JS_RaiseDisrupt(js, "CreateFile failed: %lu", GetLastError());
|
||||
|
||||
|
||||
HANDLE hMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (hMapping == NULL) {
|
||||
CloseHandle(hFile);
|
||||
return JS_RaiseDisrupt(js, "CreateFileMapping failed: %lu", GetLastError());
|
||||
}
|
||||
|
||||
|
||||
void *data = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
|
||||
if (data == NULL) {
|
||||
CloseHandle(hMapping);
|
||||
CloseHandle(hFile);
|
||||
return JS_RaiseDisrupt(js, "MapViewOfFile failed: %lu", GetLastError());
|
||||
}
|
||||
|
||||
|
||||
ret = js_new_blob_stoned_copy(js, data, size);
|
||||
UnmapViewOfFile(data);
|
||||
CloseHandle(hMapping);
|
||||
|
||||
@@ -8,26 +8,25 @@
|
||||
JSC_CCALL(kim_encode,
|
||||
const char *utf8_str = JS_ToCString(js, argv[0]);
|
||||
if (!utf8_str) return JS_EXCEPTION;
|
||||
|
||||
|
||||
// Count runes to estimate kim buffer size
|
||||
int rune_count = utf8_count(utf8_str);
|
||||
|
||||
// Allocate kim buffer (worst case: 5 bytes per rune)
|
||||
|
||||
// Allocate blob (worst case: 5 bytes per rune)
|
||||
size_t kim_size = rune_count * 5;
|
||||
char *kim_buffer = malloc(kim_size);
|
||||
char *kim_ptr = kim_buffer;
|
||||
|
||||
// Encode utf8 to kim
|
||||
void *out;
|
||||
ret = js_new_blob_alloc(js, kim_size, &out);
|
||||
if (JS_IsException(ret)) { JS_FreeCString(js, utf8_str); return ret; }
|
||||
|
||||
// Encode utf8 to kim directly into blob
|
||||
char *kim_ptr = (char *)out;
|
||||
long long runes_encoded;
|
||||
utf8_to_kim(&utf8_str, &kim_ptr, &runes_encoded);
|
||||
|
||||
// Calculate actual size used
|
||||
size_t actual_size = kim_ptr - kim_buffer;
|
||||
|
||||
// Create blob with the encoded data
|
||||
ret = js_new_blob_stoned_copy(js, kim_buffer, actual_size);
|
||||
|
||||
free(kim_buffer);
|
||||
|
||||
// Stone with actual size used
|
||||
size_t actual_size = kim_ptr - (char *)out;
|
||||
js_blob_stone(ret, actual_size);
|
||||
|
||||
JS_FreeCString(js, utf8_str);
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user