qopconv; now uses cell's own qopconv for building
This commit is contained in:
109
source/qjs_fd.c
109
source/qjs_fd.c
@@ -79,7 +79,7 @@ JSC_SCALL(fd_open,
|
||||
|
||||
int fd = open(str, flags, mode);
|
||||
if (fd < 0)
|
||||
ret = JS_ThrowReferenceError(js, "open failed: %s", strerror(errno));
|
||||
ret = JS_ThrowInternalError(js, "open failed: %s", strerror(errno));
|
||||
else
|
||||
ret = JS_NewInt32(js, fd);
|
||||
)
|
||||
@@ -90,7 +90,7 @@ JSC_CCALL(fd_write,
|
||||
|
||||
ssize_t wrote = js_fd_write_helper(js, fd, argv[1]);
|
||||
if (wrote < 0)
|
||||
return JS_ThrowReferenceError(js, "write failed: %s", strerror(errno));
|
||||
return JS_ThrowInternalError(js, "write failed: %s", strerror(errno));
|
||||
|
||||
return JS_NewInt64(js, wrote);
|
||||
)
|
||||
@@ -105,12 +105,12 @@ JSC_CCALL(fd_read,
|
||||
|
||||
void *buf = malloc(size);
|
||||
if (!buf)
|
||||
return JS_ThrowReferenceError(js, "malloc failed");
|
||||
return JS_ThrowInternalError(js, "malloc failed");
|
||||
|
||||
ssize_t bytes_read = read(fd, buf, size);
|
||||
if (bytes_read < 0) {
|
||||
free(buf);
|
||||
return JS_ThrowReferenceError(js, "read failed: %s", strerror(errno));
|
||||
return JS_ThrowInternalError(js, "read failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
ret = js_new_blob_stoned_copy(js, buf, bytes_read);
|
||||
@@ -121,7 +121,7 @@ JSC_CCALL(fd_read,
|
||||
JSC_SCALL(fd_slurp,
|
||||
struct stat st;
|
||||
if (stat(str, &st) != 0)
|
||||
return JS_ThrowReferenceError(js, "stat failed: %s", strerror(errno));
|
||||
return JS_ThrowInternalError(js, "stat failed: %s", strerror(errno));
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return JS_ThrowTypeError(js, "path is not a regular file");
|
||||
@@ -133,12 +133,12 @@ JSC_SCALL(fd_slurp,
|
||||
#ifndef _WIN32
|
||||
int fd = open(str, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return JS_ThrowReferenceError(js, "open failed: %s", strerror(errno));
|
||||
return JS_ThrowInternalError(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_ThrowReferenceError(js, "mmap failed: %s", strerror(errno));
|
||||
return JS_ThrowInternalError(js, "mmap failed: %s", strerror(errno));
|
||||
}
|
||||
ret = js_new_blob_stoned_copy(js, data, size);
|
||||
munmap(data, size);
|
||||
@@ -147,19 +147,19 @@ JSC_SCALL(fd_slurp,
|
||||
// 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_ThrowReferenceError(js, "CreateFile failed: %lu", GetLastError());
|
||||
return JS_ThrowInternalError(js, "CreateFile failed: %lu", GetLastError());
|
||||
|
||||
HANDLE hMapping = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (hMapping == NULL) {
|
||||
CloseHandle(hFile);
|
||||
return JS_ThrowReferenceError(js, "CreateFileMapping failed: %lu", GetLastError());
|
||||
return JS_ThrowInternalError(js, "CreateFileMapping failed: %lu", GetLastError());
|
||||
}
|
||||
|
||||
void *data = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
|
||||
if (data == NULL) {
|
||||
CloseHandle(hMapping);
|
||||
CloseHandle(hFile);
|
||||
return JS_ThrowReferenceError(js, "MapViewOfFile failed: %lu", GetLastError());
|
||||
return JS_ThrowInternalError(js, "MapViewOfFile failed: %lu", GetLastError());
|
||||
}
|
||||
|
||||
ret = js_new_blob_stoned_copy(js, data, size);
|
||||
@@ -185,7 +185,7 @@ JSC_CCALL(fd_lseek,
|
||||
|
||||
off_t new_pos = lseek(fd, offset, whence);
|
||||
if (new_pos < 0)
|
||||
return JS_ThrowReferenceError(js, "lseek failed: %s", strerror(errno));
|
||||
return JS_ThrowInternalError(js, "lseek failed: %s", strerror(errno));
|
||||
|
||||
return JS_NewInt64(js, new_pos);
|
||||
)
|
||||
@@ -193,23 +193,90 @@ JSC_CCALL(fd_lseek,
|
||||
JSC_CCALL(fd_getcwd,
|
||||
char buf[PATH_MAX];
|
||||
if (getcwd(buf, sizeof(buf)) == NULL)
|
||||
return JS_ThrowReferenceError(js, "getcwd failed: %s", strerror(errno));
|
||||
return JS_ThrowInternalError(js, "getcwd failed: %s", strerror(errno));
|
||||
return JS_NewString(js, buf);
|
||||
)
|
||||
|
||||
JSC_SCALL(fd_rmdir,
|
||||
if (rmdir(str) != 0)
|
||||
ret = JS_ThrowReferenceError(js, "could not remove directory %s: %s", str, strerror(errno));
|
||||
ret = JS_ThrowInternalError(js, "could not remove directory %s: %s", str, strerror(errno));
|
||||
)
|
||||
|
||||
JSC_SCALL(fd_mkdir,
|
||||
if (mkdir(str, 0755) != 0)
|
||||
ret = JS_ThrowReferenceError(js, "could not make directory %s: %s", str, strerror(errno));
|
||||
ret = JS_ThrowInternalError(js, "could not make directory %s: %s", str, strerror(errno));
|
||||
)
|
||||
|
||||
JSC_SCALL(fd_unlink,
|
||||
if (unlink(str) != 0)
|
||||
ret = JS_ThrowReferenceError(js, "could not remove file %s: %s", str, strerror(errno));
|
||||
ret = JS_ThrowInternalError(js, "could not remove file %s: %s", str, strerror(errno));
|
||||
)
|
||||
|
||||
JSC_SCALL(fd_mv,
|
||||
if (argc < 2)
|
||||
ret = JS_ThrowTypeError(js, "fd.mv requires 2 arguments: old path and new path");
|
||||
else if (!JS_IsString(argv[1]))
|
||||
ret = JS_ThrowTypeError(js, "second argument must be a string (new path)");
|
||||
else {
|
||||
const char *new_path = JS_ToCString(js, argv[1]);
|
||||
if (rename(str, new_path) != 0)
|
||||
ret = JS_ThrowInternalError(js, "could not rename %s to %s: %s", str, new_path, strerror(errno));
|
||||
JS_FreeCString(js, new_path);
|
||||
}
|
||||
)
|
||||
|
||||
// Helper function for recursive removal
|
||||
static int remove_recursive(const char *path) {
|
||||
struct stat st;
|
||||
if (stat(path, &st) != 0)
|
||||
return -1;
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
// Directory: remove contents first
|
||||
#ifdef _WIN32
|
||||
WIN32_FIND_DATA ffd;
|
||||
char search_path[PATH_MAX];
|
||||
snprintf(search_path, sizeof(search_path), "%s\\*", path);
|
||||
HANDLE hFind = FindFirstFile(search_path, &ffd);
|
||||
if (hFind != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0) continue;
|
||||
char child_path[PATH_MAX];
|
||||
snprintf(child_path, sizeof(child_path), "%s\\%s", path, ffd.cFileName);
|
||||
if (remove_recursive(child_path) != 0) {
|
||||
FindClose(hFind);
|
||||
return -1;
|
||||
}
|
||||
} while (FindNextFile(hFind, &ffd) != 0);
|
||||
FindClose(hFind);
|
||||
}
|
||||
#else
|
||||
DIR *d = opendir(path);
|
||||
if (d) {
|
||||
struct dirent *dir;
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) continue;
|
||||
char child_path[PATH_MAX];
|
||||
snprintf(child_path, sizeof(child_path), "%s/%s", path, dir->d_name);
|
||||
if (remove_recursive(child_path) != 0) {
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
#endif
|
||||
// Remove the now-empty directory
|
||||
return rmdir(path);
|
||||
} else {
|
||||
// File: just unlink
|
||||
return unlink(path);
|
||||
}
|
||||
}
|
||||
|
||||
JSC_SCALL(fd_rm,
|
||||
if (remove_recursive(str) != 0)
|
||||
ret = JS_ThrowInternalError(js, "could not remove %s: %s", str, strerror(errno));
|
||||
)
|
||||
|
||||
JSC_CCALL(fd_fsync,
|
||||
@@ -217,7 +284,7 @@ JSC_CCALL(fd_fsync,
|
||||
if (fd < 0) return JS_EXCEPTION;
|
||||
|
||||
if (fsync(fd) != 0)
|
||||
return JS_ThrowReferenceError(js, "fsync failed: %s", strerror(errno));
|
||||
return JS_ThrowInternalError(js, "fsync failed: %s", strerror(errno));
|
||||
|
||||
return JS_NULL;
|
||||
)
|
||||
@@ -227,7 +294,7 @@ JSC_CCALL(fd_close,
|
||||
if (fd < 0) return JS_EXCEPTION;
|
||||
|
||||
if (close(fd) != 0)
|
||||
return JS_ThrowReferenceError(js, "close failed: %s", strerror(errno));
|
||||
return JS_ThrowInternalError(js, "close failed: %s", strerror(errno));
|
||||
|
||||
return JS_NULL;
|
||||
)
|
||||
@@ -238,7 +305,7 @@ JSC_CCALL(fd_fstat,
|
||||
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) != 0)
|
||||
return JS_ThrowReferenceError(js, "fstat failed: %s", strerror(errno));
|
||||
return JS_ThrowInternalError(js, "fstat failed: %s", strerror(errno));
|
||||
|
||||
printf("fstat on %s\n", argv[0]);
|
||||
JSValue obj = JS_NewObject(js);
|
||||
@@ -317,7 +384,7 @@ JSC_SCALL(fd_readdir,
|
||||
snprintf(path, sizeof(path), "%s\\*", str);
|
||||
HANDLE hFind = FindFirstFile(path, &ffd);
|
||||
if (hFind == INVALID_HANDLE_VALUE) {
|
||||
ret = JS_ThrowReferenceError(js, "FindFirstFile failed for %s", path);
|
||||
ret = JS_ThrowInternalError(js, "FindFirstFile failed for %s", path);
|
||||
} else {
|
||||
ret = JS_NewArray(js);
|
||||
int i = 0;
|
||||
@@ -340,7 +407,7 @@ JSC_SCALL(fd_readdir,
|
||||
}
|
||||
closedir(d);
|
||||
} else {
|
||||
ret = JS_ThrowReferenceError(js, "opendir failed for %s: %s", str, strerror(errno));
|
||||
ret = JS_ThrowInternalError(js, "opendir failed for %s: %s", str, strerror(errno));
|
||||
}
|
||||
#endif
|
||||
)
|
||||
@@ -355,6 +422,8 @@ static const JSCFunctionListEntry js_fd_funcs[] = {
|
||||
MIST_FUNC_DEF(fd, rmdir, 1),
|
||||
MIST_FUNC_DEF(fd, unlink, 1),
|
||||
MIST_FUNC_DEF(fd, mkdir, 1),
|
||||
MIST_FUNC_DEF(fd, mv, 2),
|
||||
MIST_FUNC_DEF(fd, rm, 1),
|
||||
MIST_FUNC_DEF(fd, fsync, 1),
|
||||
MIST_FUNC_DEF(fd, close, 1),
|
||||
MIST_FUNC_DEF(fd, stat, 1),
|
||||
|
||||
268
source/qjs_qop.c
268
source/qjs_qop.c
@@ -21,6 +21,74 @@ static JSClassDef js_qop_archive_class = {
|
||||
.finalizer = js_qop_archive_finalizer,
|
||||
};
|
||||
|
||||
static JSClassID js_qop_writer_class_id;
|
||||
|
||||
typedef struct {
|
||||
FILE *fh;
|
||||
qop_file *files;
|
||||
int len;
|
||||
int capacity;
|
||||
unsigned int size;
|
||||
} qop_writer;
|
||||
|
||||
static void js_qop_writer_finalizer(JSRuntime *rt, JSValue val) {
|
||||
qop_writer *w = JS_GetOpaque(val, js_qop_writer_class_id);
|
||||
if (w) {
|
||||
if (w->fh) fclose(w->fh);
|
||||
if (w->files) js_free_rt(rt, w->files);
|
||||
js_free_rt(rt, w);
|
||||
}
|
||||
}
|
||||
|
||||
static JSClassDef js_qop_writer_class = {
|
||||
"qop writer",
|
||||
.finalizer = js_qop_writer_finalizer,
|
||||
};
|
||||
|
||||
static qop_writer *js2writer(JSContext *js, JSValue v) {
|
||||
return JS_GetOpaque(v, js_qop_writer_class_id);
|
||||
}
|
||||
|
||||
// Helper functions for writer
|
||||
static void write_16(unsigned int v, FILE *fh) {
|
||||
unsigned char b[2];
|
||||
b[0] = 0xff & (v);
|
||||
b[1] = 0xff & (v >> 8);
|
||||
fwrite(b, 2, 1, fh);
|
||||
}
|
||||
|
||||
static void write_32(unsigned int v, FILE *fh) {
|
||||
unsigned char b[4];
|
||||
b[0] = 0xff & (v);
|
||||
b[1] = 0xff & (v >> 8);
|
||||
b[2] = 0xff & (v >> 16);
|
||||
b[3] = 0xff & (v >> 24);
|
||||
fwrite(b, 4, 1, fh);
|
||||
}
|
||||
|
||||
static void write_64(unsigned long long v, FILE *fh) {
|
||||
unsigned char b[8];
|
||||
b[0] = 0xff & (v);
|
||||
b[1] = 0xff & (v >> 8);
|
||||
b[2] = 0xff & (v >> 16);
|
||||
b[3] = 0xff & (v >> 24);
|
||||
b[4] = 0xff & (v >> 32);
|
||||
b[5] = 0xff & (v >> 40);
|
||||
b[6] = 0xff & (v >> 48);
|
||||
b[7] = 0xff & (v >> 56);
|
||||
fwrite(b, 8, 1, fh);
|
||||
}
|
||||
|
||||
static unsigned long long qop_hash(const char *key) {
|
||||
unsigned long long h = 525201411107845655ull;
|
||||
for (;*key;++key) {
|
||||
h ^= (unsigned char)*key;
|
||||
h *= 0x5bd1e9955bd1e995ull;
|
||||
h ^= h >> 47;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
static qop_desc *js2qop(JSContext *js, JSValue v) {
|
||||
return JS_GetOpaque(v, js_qop_archive_class_id);
|
||||
}
|
||||
@@ -60,6 +128,36 @@ JSC_SCALL(qop_open,
|
||||
}
|
||||
)
|
||||
|
||||
JSC_SCALL(qop_write,
|
||||
const char *path = JS_ToCString(js, argv[0]);
|
||||
if (!path) return JS_EXCEPTION;
|
||||
|
||||
FILE *fh = fopen(path, "wb");
|
||||
JS_FreeCString(js, path);
|
||||
if (!fh) return JS_ThrowInternalError(js, "Could not open file for writing");
|
||||
|
||||
qop_writer *w = js_malloc(js, sizeof(qop_writer));
|
||||
if (!w) {
|
||||
fclose(fh);
|
||||
return JS_ThrowOutOfMemory(js);
|
||||
}
|
||||
|
||||
w->fh = fh;
|
||||
w->capacity = 1024;
|
||||
w->len = 0;
|
||||
w->size = 0;
|
||||
w->files = js_malloc(js, sizeof(qop_file) * w->capacity);
|
||||
if (!w->files) {
|
||||
fclose(fh);
|
||||
js_free(js, w);
|
||||
return JS_ThrowOutOfMemory(js);
|
||||
}
|
||||
|
||||
JSValue obj = JS_NewObjectClass(js, js_qop_writer_class_id);
|
||||
JS_SetOpaque(obj, w);
|
||||
ret = obj;
|
||||
)
|
||||
|
||||
|
||||
static JSValue js_qop_close(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
qop_desc *qop = js2qop(js, self);
|
||||
@@ -183,15 +281,179 @@ static JSValue js_qop_list(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
return arr;
|
||||
}
|
||||
|
||||
static JSValue js_qop_stat(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
qop_desc *qop = js2qop(js, self);
|
||||
if (!qop) return JS_ThrowInternalError(js, "Invalid QOP archive");
|
||||
|
||||
const char *path = JS_ToCString(js, argv[0]);
|
||||
if (!path) return JS_EXCEPTION;
|
||||
|
||||
if (!js_qop_ensure_index(js, qop)) {
|
||||
JS_FreeCString(js, path);
|
||||
return JS_ThrowReferenceError(js, "Failed to read QOP index");
|
||||
}
|
||||
|
||||
qop_file *file = qop_find(qop, path);
|
||||
JS_FreeCString(js, path);
|
||||
|
||||
if (!file) return JS_NULL;
|
||||
|
||||
JSValue obj = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, obj, "size", JS_NewInt64(js, file->size));
|
||||
JS_SetPropertyStr(js, obj, "modtime", JS_NewInt64(js, 0));
|
||||
JS_SetPropertyStr(js, obj, "isDirectory", JS_NewBool(js, 0));
|
||||
return obj;
|
||||
}
|
||||
|
||||
static JSValue js_qop_is_directory(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
qop_desc *qop = js2qop(js, self);
|
||||
if (!qop) return JS_ThrowInternalError(js, "Invalid QOP archive");
|
||||
|
||||
const char *path = JS_ToCString(js, argv[0]);
|
||||
if (!path) return JS_EXCEPTION;
|
||||
|
||||
if (!js_qop_ensure_index(js, qop)) {
|
||||
JS_FreeCString(js, path);
|
||||
return JS_ThrowReferenceError(js, "Failed to read QOP index");
|
||||
}
|
||||
|
||||
// Check if any file starts with path + "/"
|
||||
size_t path_len = strlen(path);
|
||||
char *prefix = js_malloc(js, path_len + 2);
|
||||
memcpy(prefix, path, path_len);
|
||||
prefix[path_len] = '/';
|
||||
prefix[path_len + 1] = '\0';
|
||||
|
||||
int found = 0;
|
||||
|
||||
// This is inefficient but simple. QOP doesn't have a directory structure.
|
||||
// We iterate all files to check prefixes.
|
||||
for (unsigned int i = 0; i < qop->hashmap_len; i++) {
|
||||
qop_file *file = &qop->hashmap[i];
|
||||
if (file->size == 0) continue;
|
||||
|
||||
// We need to read the path to check it
|
||||
// Optimization: check if we can read just the prefix?
|
||||
// qop_read_path reads the whole path.
|
||||
|
||||
// Let's read the path.
|
||||
char file_path[1024]; // MAX_PATH_LEN
|
||||
if (file->path_len > 1024) continue; // Should not happen based on spec
|
||||
|
||||
qop_read_path(qop, file, file_path);
|
||||
if (strncmp(file_path, prefix, path_len + 1) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
js_free(js, prefix);
|
||||
JS_FreeCString(js, path);
|
||||
return JS_NewBool(js, found);
|
||||
}
|
||||
|
||||
// Writer methods
|
||||
|
||||
static JSValue js_writer_add_file(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
qop_writer *w = js2writer(js, self);
|
||||
if (!w) return JS_ThrowInternalError(js, "Invalid QOP writer");
|
||||
|
||||
const char *path = JS_ToCString(js, argv[0]);
|
||||
if (!path) return JS_EXCEPTION;
|
||||
|
||||
size_t data_len;
|
||||
void *data = js_get_blob_data(js, &data_len, argv[1]);
|
||||
if (!data) {
|
||||
JS_FreeCString(js, path);
|
||||
return JS_ThrowTypeError(js, "Second argument must be a blob");
|
||||
}
|
||||
|
||||
if (w->len >= w->capacity) {
|
||||
w->capacity *= 2;
|
||||
qop_file *new_files = js_realloc(js, w->files, sizeof(qop_file) * w->capacity);
|
||||
if (!new_files) {
|
||||
JS_FreeCString(js, path);
|
||||
return JS_ThrowOutOfMemory(js);
|
||||
}
|
||||
w->files = new_files;
|
||||
}
|
||||
|
||||
// Strip leading "./"
|
||||
const char *archive_path = path;
|
||||
if (path[0] == '.' && path[1] == '/') {
|
||||
archive_path = path + 2;
|
||||
}
|
||||
|
||||
unsigned long long hash = qop_hash(archive_path);
|
||||
int path_len = strlen(archive_path) + 1;
|
||||
|
||||
// Write path
|
||||
fwrite(archive_path, 1, path_len, w->fh);
|
||||
|
||||
// Write data
|
||||
fwrite(data, 1, data_len, w->fh);
|
||||
|
||||
w->files[w->len] = (qop_file){
|
||||
.hash = hash,
|
||||
.offset = w->size,
|
||||
.size = (unsigned int)data_len,
|
||||
.path_len = (unsigned short)path_len,
|
||||
.flags = QOP_FLAG_NONE
|
||||
};
|
||||
|
||||
w->size += data_len + path_len;
|
||||
w->len++;
|
||||
|
||||
JS_FreeCString(js, path);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static JSValue js_writer_finalize(JSContext *js, JSValue self, int argc, JSValue *argv) {
|
||||
qop_writer *w = js2writer(js, self);
|
||||
if (!w || !w->fh) return JS_ThrowInternalError(js, "Invalid QOP writer or already closed");
|
||||
|
||||
unsigned int total_size = w->size + 12; // Header size
|
||||
|
||||
for (int i = 0; i < w->len; i++) {
|
||||
write_64(w->files[i].hash, w->fh);
|
||||
write_32(w->files[i].offset, w->fh);
|
||||
write_32(w->files[i].size, w->fh);
|
||||
write_16(w->files[i].path_len, w->fh);
|
||||
write_16(w->files[i].flags, w->fh);
|
||||
total_size += 20;
|
||||
}
|
||||
|
||||
// Magic "qopf"
|
||||
unsigned int magic = (((unsigned int)'q') << 0 | ((unsigned int)'o') << 8 |
|
||||
((unsigned int)'p') << 16 | ((unsigned int)'f') << 24);
|
||||
|
||||
write_32(w->len, w->fh);
|
||||
write_32(total_size, w->fh);
|
||||
write_32(magic, w->fh);
|
||||
|
||||
fclose(w->fh);
|
||||
w->fh = NULL;
|
||||
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_qop_archive_funcs[] = {
|
||||
JS_CFUNC_DEF("close", 0, js_qop_close),
|
||||
JS_CFUNC_DEF("list", 0, js_qop_list),
|
||||
JS_CFUNC_DEF("read", 1, js_qop_read),
|
||||
JS_CFUNC_DEF("read_ex", 3, js_qop_read_ex),
|
||||
JS_CFUNC_DEF("stat", 1, js_qop_stat),
|
||||
JS_CFUNC_DEF("is_directory", 1, js_qop_is_directory),
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_qop_writer_funcs[] = {
|
||||
JS_CFUNC_DEF("add_file", 2, js_writer_add_file),
|
||||
JS_CFUNC_DEF("finalize", 0, js_writer_finalize),
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_qop_funcs[] = {
|
||||
MIST_FUNC_DEF(qop, open, 1),
|
||||
MIST_FUNC_DEF(qop, write, 1),
|
||||
JS_PROP_INT32_DEF("FLAG_NONE", QOP_FLAG_NONE, JS_PROP_ENUMERABLE),
|
||||
JS_PROP_INT32_DEF("FLAG_COMPRESSED_ZSTD", QOP_FLAG_COMPRESSED_ZSTD, JS_PROP_ENUMERABLE),
|
||||
JS_PROP_INT32_DEF("FLAG_COMPRESSED_DEFLATE", QOP_FLAG_COMPRESSED_DEFLATE, JS_PROP_ENUMERABLE),
|
||||
@@ -205,6 +467,12 @@ JSValue js_qop_use(JSContext *js) {
|
||||
JS_SetPropertyFunctionList(js, archive_proto, js_qop_archive_funcs, countof(js_qop_archive_funcs));
|
||||
JS_SetClassProto(js, js_qop_archive_class_id, archive_proto);
|
||||
|
||||
JS_NewClassID(&js_qop_writer_class_id);
|
||||
JS_NewClass(JS_GetRuntime(js), js_qop_writer_class_id, &js_qop_writer_class);
|
||||
JSValue writer_proto = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js, writer_proto, js_qop_writer_funcs, countof(js_qop_writer_funcs));
|
||||
JS_SetClassProto(js, js_qop_writer_class_id, writer_proto);
|
||||
|
||||
JSValue mod = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js, mod, js_qop_funcs, countof(js_qop_funcs));
|
||||
return mod;
|
||||
|
||||
Reference in New Issue
Block a user