From 8bdcaf7d9dac2d9a8a569452989565cb3880811b Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sun, 23 Nov 2025 11:20:59 -0600 Subject: [PATCH] qop --- meson.build | 17 +-- source/cell.c | 34 ++---- source/config.c | 3 - source/jsffi.c | 10 +- source/qjs_qop.c | 205 ++++++++++++++++++++++++++++++++ source/qjs_qop.h | 8 ++ source/qjs_qr.c | 302 ----------------------------------------------- source/qjs_qr.h | 8 -- source/qop.h | 10 +- 9 files changed, 230 insertions(+), 367 deletions(-) create mode 100644 source/qjs_qop.c create mode 100644 source/qjs_qop.h delete mode 100644 source/qjs_qr.c delete mode 100644 source/qjs_qr.h diff --git a/meson.build b/meson.build index 6a89fd72..828391be 100644 --- a/meson.build +++ b/meson.build @@ -255,22 +255,6 @@ else deps += soloud_dep endif -# QR code support (optional) -qrencode_enabled = get_option('qrencode') -if qrencode_enabled - qr_dep = dependency('qrencode', static: true, required: false) - if not qr_dep.found() - message('⚙ System qrencode not found, building subproject...') - deps += dependency('libqrencode', static:true) - else - deps += qr_dep - endif - add_project_arguments('-DHAVE_QRENCODE', language: ['c', 'cpp']) - src += 'qjs_qr.c' -else - message('⚙ QR code support disabled') -endif - link_args = link sources = [] src += [ @@ -294,6 +278,7 @@ src += [ 'wildmatch.c', 'qjs_io.c', 'qjs_fd.c', + 'qjs_qop.c', 'qjs_os.c', 'qjs_actor.c', 'qjs_wota.c', diff --git a/source/cell.c b/source/cell.c index e1cad690..f588acba 100644 --- a/source/cell.c +++ b/source/cell.c @@ -954,26 +954,16 @@ int main(int argc, char **argv) return 1; } - /* Search for .cell directory up the tree */ - char *search_dir = SDL_GetCurrentDirectory(); + /* Check for .cell directory in the current directory */ char *cell_parent_dir = NULL; struct stat st; - - while (search_dir && strlen(search_dir) > 1) { - char test_path[PATH_MAX]; - snprintf(test_path, sizeof(test_path), "%s/.cell", search_dir); - if (stat(test_path, &st) == 0 && S_ISDIR(st.st_mode)) { - cell_parent_dir = strdup(search_dir); - break; - } - char *last_sep = strrchr(search_dir, '/'); - if (!last_sep || last_sep == search_dir) { - if (stat("/.cell", &st) == 0 && S_ISDIR(st.st_mode)) - cell_parent_dir = strdup("/"); - break; - } - *last_sep = '\0'; + char *current_dir = SDL_GetCurrentDirectory(); + char test_path[PATH_MAX]; + snprintf(test_path, sizeof(test_path), "%s/.cell", current_dir); + if (stat(test_path, &st) == 0 && S_ISDIR(st.st_mode)) { + cell_parent_dir = strdup(current_dir); } + SDL_free(current_dir); if (cell_parent_dir) { /* 1) Strip any trailing slash from cell_parent_dir (except if it's just "/") */ @@ -981,26 +971,18 @@ int main(int argc, char **argv) if (proj_len > 1 && cell_parent_dir[proj_len - 1] == '/') cell_parent_dir[proj_len - 1] = '\0'; - char scriptpath[PATH_MAX]; - snprintf(scriptpath, sizeof(scriptpath), "%s/scripts", cell_parent_dir); - char cellpath[PATH_MAX]; snprintf(cellpath, sizeof(cellpath), "%s/.cell/modules", cell_parent_dir); - PHYSFS_mount(scriptpath, NULL, 1); PHYSFS_mount(cellpath, NULL, 0); PHYSFS_mount(cell_parent_dir, NULL, 0); PHYSFS_setWriteDir(cell_parent_dir); free(cell_parent_dir); } else { - // Not in a project - use CELLPATH after confirming .. - // TODO: implement - printf("Could not find project! Exiting!\n"); + printf("Cell requires a .cell folder to run.\n"); exit(1); } - - SDL_free(search_dir); /* Create the initial actor from the command line */ int actor_argc = argc - script_start; diff --git a/source/config.c b/source/config.c index fe4dda1e..65051114 100644 --- a/source/config.c +++ b/source/config.c @@ -48,6 +48,3 @@ #define QOI_IMPLEMENTATION #include "qoi.h" - -#define QOP_IMPLEMENTATION -#include "qop.h" diff --git a/source/jsffi.c b/source/jsffi.c index 37097a2f..0c4d055d 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -29,9 +29,6 @@ #include "qjs_nota.h" #include "qjs_wota.h" #include "qjs_soloud.h" -#ifdef HAVE_QRENCODE -#include "qjs_qr.h" -#endif #include "qjs_sdl.h" #include "qjs_sdl_video.h" #include "qjs_math.h" @@ -55,6 +52,8 @@ #include "qjs_io.h" #include "qjs_fd.h" +#include "qjs_qop.h" + // External transform function declarations extern JSClassID js_transform_id; JSValue transform2js(JSContext *js, transform *t); @@ -1123,11 +1122,8 @@ void ffi_load(JSContext *js) // extra arrput(rt->module_registry, ((ModuleEntry){"io", js_io_use})); arrput(rt->module_registry, ((ModuleEntry){"fd", js_fd_use})); - arrput(rt->module_registry, MISTLINE(socket)); + arrput(rt->module_registry, ((ModuleEntry){"qop", js_qop_use})); arrput(rt->module_registry, ((ModuleEntry){"os", js_os_use})); -#ifdef HAVE_QRENCODE - arrput(rt->module_registry, MISTLINE(qr)); -#endif arrput(rt->module_registry, MISTLINE(http)); arrput(rt->module_registry, MISTLINE(crypto)); arrput(rt->module_registry, MISTLINE(miniz)); diff --git a/source/qjs_qop.c b/source/qjs_qop.c new file mode 100644 index 00000000..2d3f03b1 --- /dev/null +++ b/source/qjs_qop.c @@ -0,0 +1,205 @@ +#include "qjs_qop.h" +#define QOP_IMPLEMENTATION +#include "qop.h" +#include "qjs_blob.h" +#include "jsffi.h" + +static JSClassID js_qop_archive_class_id; + +static void js_qop_archive_finalizer(JSRuntime *rt, JSValue val) { + qop_desc *qop = JS_GetOpaque(val, js_qop_archive_class_id); + if (qop) { + if (qop->hashmap) { + js_free_rt(rt, qop->hashmap); + } + qop_close(qop); + js_free_rt(rt, qop); + } +} + +static JSClassDef js_qop_archive_class = { + "qop archive", + .finalizer = js_qop_archive_finalizer, +}; + +static qop_desc *js2qop(JSContext *js, JSValue v) { + return JS_GetOpaque(v, js_qop_archive_class_id); +} + +static int js_qop_ensure_index(JSContext *js, qop_desc *qop) { + if (qop->hashmap != NULL) return 1; + void *buffer = js_malloc(js, qop->hashmap_size); + if (!buffer) return 0; + int num = qop_read_index(qop, buffer); + if (num == 0) { + js_free(js, buffer); + return 0; + } + return 1; +} + +JSC_SCALL(qop_open, + qop_desc *qop = js_malloc(js, sizeof(qop_desc)); + if (!qop) + ret = JS_ThrowOutOfMemory(js); + + int size = qop_open(str, qop); + if (size == 0) { + js_free(js, qop); + ret = JS_ThrowReferenceError(js, "Failed to open QOP archive: %s", str); + } else { + JSValue obj = JS_NewObjectClass(js, js_qop_archive_class_id); + JS_SetOpaque(obj, qop); + ret = obj; + } +) + + +static JSValue js_qop_close(JSContext *js, JSValue self, int argc, JSValue *argv) { + qop_desc *qop = js2qop(js, self); + if (!qop) + return JS_ThrowInternalError(js, "Invalid QOP archive"); + + qop_close(qop); + JS_SetOpaque(self, NULL); // Prevent double free + return JS_NULL; +} + + + +static JSValue js_qop_read(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; + + unsigned char *dest = js_malloc(js, file->size); + if (!dest) + return JS_ThrowOutOfMemory(js); + + int bytes = qop_read(qop, file, dest); + if (bytes == 0) { + js_free(js, dest); + return JS_ThrowReferenceError(js, "Failed to read file"); + } + + JSValue blob = js_new_blob_stoned_copy(js, dest, bytes); + js_free(js, dest); + return blob; +} + +static JSValue js_qop_read_ex(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; + + unsigned int start; + unsigned int len; + if (JS_ToUint32(js, &start, argv[1]) < 0 || JS_ToUint32(js, &len, argv[2]) < 0) + return JS_ThrowTypeError(js, "Invalid start or len"); + + unsigned char *dest = js_malloc(js, len); + if (!dest) + return JS_ThrowOutOfMemory(js); + + int bytes = qop_read_ex(qop, file, dest, start, len); + if (bytes == 0) { + js_free(js, dest); + return JS_ThrowReferenceError(js, "Failed to read file part"); + } + + JSValue blob = js_new_blob_stoned_copy(js, dest, bytes); + js_free(js, dest); + return blob; +} + +static JSValue js_qop_list(JSContext *js, JSValue self, int argc, JSValue *argv) { + qop_desc *qop = js2qop(js, self); + if (!qop) + return JS_ThrowInternalError(js, "Invalid QOP archive"); + + if (!js_qop_ensure_index(js, qop)) { + return JS_ThrowReferenceError(js, "Failed to read QOP index"); + } + + JSValue arr = JS_NewArray(js); + int count = 0; + + for (unsigned int i = 0; i < qop->hashmap_len; i++) { + qop_file *file = &qop->hashmap[i]; + if (file->size == 0) continue; // empty slot + + char *path = js_malloc(js, file->path_len); + if (!path) { + return JS_ThrowOutOfMemory(js); + } + + int len = qop_read_path(qop, file, path); + if (len == 0) { + js_free(js, path); + continue; // skip on error + } + + JSValue str = JS_NewStringLen(js, path, len - 1); // -1 for null terminator + js_free(js, path); + JS_SetPropertyUint32(js, arr, count++, str); + } + + return arr; +} + +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), +}; + +static const JSCFunctionListEntry js_qop_funcs[] = { + MIST_FUNC_DEF(qop, open, 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), + JS_PROP_INT32_DEF("FLAG_ENCRYPTED", QOP_FLAG_ENCRYPTED, JS_PROP_ENUMERABLE), +}; + +JSValue js_qop_use(JSContext *js) { + JS_NewClassID(&js_qop_archive_class_id); + JS_NewClass(JS_GetRuntime(js), js_qop_archive_class_id, &js_qop_archive_class); + JSValue archive_proto = JS_NewObject(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); + + JSValue mod = JS_NewObject(js); + JS_SetPropertyFunctionList(js, mod, js_qop_funcs, countof(js_qop_funcs)); + return mod; +} \ No newline at end of file diff --git a/source/qjs_qop.h b/source/qjs_qop.h new file mode 100644 index 00000000..a2c0a0f7 --- /dev/null +++ b/source/qjs_qop.h @@ -0,0 +1,8 @@ +#ifndef QJS_QOP_H +#define QJS_QOP_H + +#include "cell.h" + +JSValue js_qop_use(JSContext *js); + +#endif // QJS_QOP_H \ No newline at end of file diff --git a/source/qjs_qr.c b/source/qjs_qr.c deleted file mode 100644 index d7d0d915..00000000 --- a/source/qjs_qr.c +++ /dev/null @@ -1,302 +0,0 @@ -#include "cell.h" -#include "qjs_blob.h" - -#include "quirc.h" -#include "qrencode.h" - -#include // for sqrt -#include // for size_t, etc. -#include // for memcpy, strcmp -#include - -#include - -// QR encode function -static JSValue js_qr_encode(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) { - if (argc < 1) { - return JS_ThrowTypeError(js, "encode expects a string or ArrayBuffer as first argument"); - } - - // Default options - int version = 0; // 0 means auto-select in qrencode - int errc = QR_ECLEVEL_L; // Default to "L" - int casesensitive = 1; // Default to true (qrencode treats 1 as case-sensitive) - int use_byte_mode = 0; - - // Handle options object (argv[1]) - if (argc > 1 && !JS_IsNull(argv[1]) && JS_IsObject(argv[1])) { - JSValue opt = argv[1]; - - JSValue m = JS_GetPropertyStr(js, opt, "mode"); - if (!JS_IsNull(m)) { - const char *smode = JS_ToCString(js, m); - if (!smode) { JS_FreeValue(js, m); return JS_EXCEPTION; } - if (!strcasecmp(smode, "byte") || !strcasecmp(smode, "binary")) - use_byte_mode = 1; - else if (!strcasecmp(smode, "text")) - use_byte_mode = 0; - else { - JS_FreeCString(js, smode); JS_FreeValue(js, m); - return JS_ThrowRangeError(js, "mode must be 'byte' or 'text'"); - } - JS_FreeCString(js, smode); - JS_FreeValue(js, m); - } - - // Version (1-40) - JSValue v = JS_GetPropertyStr(js, opt, "version"); - if (!JS_IsNull(v)) { - int32_t ver; - if (JS_ToInt32(js, &ver, v) || ver < 0 || ver > 40) { - JS_FreeValue(js, v); - return JS_ThrowRangeError(js, "version must be between 0 and 40"); - } - version = ver; - JS_FreeValue(js, v); - } - - // Error correction level ("l", "m", "q", "h") - JSValue l = JS_GetPropertyStr(js, opt, "level"); - if (!JS_IsNull(l)) { - const char *level = JS_ToCString(js, l); - if (!level) { - JS_FreeValue(js, l); - return JS_ThrowTypeError(js, "level must be a string"); - } - if (strcasecmp(level, "l") == 0) errc = QR_ECLEVEL_L; - else if (strcasecmp(level, "m") == 0) errc = QR_ECLEVEL_M; - else if (strcasecmp(level, "q") == 0) errc = QR_ECLEVEL_Q; - else if (strcasecmp(level, "h") == 0) errc = QR_ECLEVEL_H; - else { - JS_FreeCString(js, level); - JS_FreeValue(js, l); - return JS_ThrowRangeError(js, "level must be 'l', 'm', 'q', or 'h'"); - } - JS_FreeCString(js, level); - JS_FreeValue(js, l); - } - - // Case sensitivity (true/false) - JSValue ci = JS_GetPropertyStr(js, opt, "caseinsensitive"); - if (!JS_IsNull(ci)) { - int bool_val; - if (JS_ToBool(js, ci)) { - bool_val = 0; // qrencode: 0 = case-insensitive - } else { - bool_val = 1; // qrencode: 1 = case-sensitive - } - casesensitive = bool_val; - JS_FreeValue(js, ci); - } - } - - const char *data = NULL; - size_t data_len = 0; - int must_free_data = 0; - - // Handle string input - if (!use_byte_mode && JS_IsString(argv[0])) { - data = JS_ToCStringLen(js, &data_len, argv[0]); - if (!data) { - return JS_ThrowTypeError(js, "Invalid string input"); - } - must_free_data = 1; - } else { - /* treat everything else as raw bytes */ - use_byte_mode = 1; - uint8_t *buf = js_get_blob_data(js, &data_len, argv[0]); - if (!buf) { - return JS_ThrowTypeError(js, "encode expects a string or ArrayBuffer"); - } - data = (const char *)buf; // Cast to char* for qrencode - } - - // Encode using qrencode - QRcode *qrcode; - if (use_byte_mode) - qrcode = QRcode_encodeData(data_len, data, version, errc); - else - qrcode = QRcode_encodeString(data, version, errc, QR_MODE_8, casesensitive); - - if (!qrcode) { - if (must_free_data) - JS_FreeCString(js, data); - return JS_ThrowInternalError(js, "Failed to encode QR code: %s", strerror(errno)); - } - - // qrcode->width is the size of one side - // qrcode->data is width * width bytes - printf("Encoded %d of data into a QR of width %d\n", data_len, qrcode->width); - int width = qrcode->width; - size_t size = (size_t)width * width; // total modules - - // Create an array of booleans for the module data - JSValue dataArr = JS_NewArray(js); - for (size_t i = 0; i < size; i++) { - int is_black = (qrcode->data[i] & 1); - JSValue val = JS_NewBool(js, is_black); - JS_SetPropertyUint32(js, dataArr, (uint32_t)i, val); - } - - // Build a JS object to hold { width, data } - JSValue result = JS_NewObject(js); - JS_SetPropertyStr(js, result, "width", JS_NewInt32(js, width)); - JS_SetPropertyStr(js, result, "data", dataArr); - - // Clean up - QRcode_free(qrcode); - if (must_free_data) { - JS_FreeCString(js, data); - } - - return result; -} - -static uint8_t rgba_to_gray(uint8_t r, uint8_t g, uint8_t b) -{ - return (uint8_t)(( 299 * r + 587 * g + 114 * b + 500) / 1000); -} - -// QR decode function (unchanged) -static JSValue js_qr_decode(JSContext *js, JSValueConst this_val, int argc, JSValueConst *argv) { - size_t data_len; - uint8_t *src; - int w, h, pitch; - src = js_get_blob_data(js, &data_len, argv[0]); - - if (!src) - return JS_ThrowTypeError(js, "decode expects an ArrayBuffer"); - - JS_ToInt32(js, &w, argv[1]); - JS_ToInt32(js, &h, argv[2]); - JS_ToInt32(js, &pitch, argv[3]); - - if (w <= 0 || h <= 0) - return JS_ThrowInternalError(js, "Bad width or height: %dx%d", w, h); - - struct quirc *qr = quirc_new(); - if (!qr) - return JS_ThrowInternalError(js, "Failed to initialize QR decoder"); - - if (quirc_resize(qr, w, h) < 0) { - quirc_destroy(qr); - return JS_ThrowInternalError(js, "quirc_resize failed"); - } - - uint8_t *dst = quirc_begin(qr, NULL, NULL); - - printf("decoding image size %dx%d, pitch %d and size %d\n", w, h, pitch, data_len); - - for (int y = 0; y < h; ++y) { - uint8_t *row = src + y * pitch; - uint8_t *out = dst + y * w; - for (int x = 0; x < w; ++x) { - uint8_t a = row[x*4 + 3]; /* alpha */ - if (a < 128) { /* mostly transparent */ - out[x] = 255; - } else { - uint8_t r = row[x*4+0]; - uint8_t g = row[x*4+1]; - uint8_t b = row[x*4+2]; - out[x] = rgba_to_gray(r, g, b); - } - } - } - - quirc_end(qr); - - int count = quirc_count(qr); - JSValue result = JS_NewArray(js); - - for (int i = 0; i < count; i++) { - struct quirc_code code; - struct quirc_data qdata; - - quirc_extract(qr, i, &code); - int err = quirc_decode(&code, &qdata); - if (err == QUIRC_SUCCESS) { - JSValue item = js_new_blob_stoned_copy(js, qdata.payload, qdata.payload_len); - JS_SetPropertyUint32(js, result, i, item); - } else { - printf("QR error: %s\n", quirc_strerror(err)); - } - } - - quirc_destroy(qr); - return result; -} - -static JSValue js_qr_rgba(JSContext *js, JSValueConst self, int argc, JSValueConst *argv) -{ - if (argc < 1) - return JS_ThrowTypeError(js, "qr.rgba(mods, ...) needs a modules object"); - - JSValue mods = argv[0]; - - uint32_t on = 0xFF000000u; /* black opaque */ - uint32_t off = 0xFFFFFFFFu; /* white opaque */ - if (argc > 1) JS_ToUint32(js, &on, argv[1]); - if (argc > 2) JS_ToUint32(js, &off, argv[2]); - - JSValue js_w = JS_GetPropertyStr(js, mods, "width"); - if (JS_IsNull(js_w)) { - JS_FreeValue(js, js_w); - return JS_ThrowTypeError(js, "mods.width missing"); - } - int32_t m = 0; - JS_ToInt32(js, &m, js_w); - JS_FreeValue(js, js_w); - - if (m <= 0) - return JS_ThrowRangeError(js, "mods.width must be > 0"); - - JSValue js_bits = JS_GetPropertyStr(js, mods, "data"); - size_t len = JS_ArrayLength(js, js_bits); - - if (len < (size_t)m * (size_t)m) { - JS_FreeValue(js, js_bits); - return JS_ThrowRangeError(js, "mods.data too small for width²"); - } - - const int w = m, h = m, pitch = w * 4; - const size_t bytes = (size_t)h * (size_t)pitch; - uint8_t *tmp = js_malloc(js, bytes); - if (!tmp) { JS_FreeValue(js, js_bits); return JS_EXCEPTION; } - - for (int y = 0; y < h; ++y) { - uint32_t *row = (uint32_t *)(tmp + y * pitch); - for (int x = 0; x < w; x++) { - uint32_t idx = y * m + x; - JSValue vbit = JS_GetPropertyUint32(js, js_bits, idx); - int on_bit = JS_ToBool(js, vbit); - JS_FreeValue(js, vbit); - row[x] = on_bit ? on : off; - } - } - - JSValue ab = js_new_blob_stoned_copy(js, tmp, bytes); /* GC owns copy */ - js_free(js, tmp); - JS_FreeValue(js, js_bits); /* done with src */ - - JSValue obj = JS_NewObject(js); - JS_SetPropertyStr(js, obj, "width", JS_NewInt32(js, w)); - JS_SetPropertyStr(js, obj, "height", JS_NewInt32(js, h)); - JS_SetPropertyStr(js, obj, "pitch", JS_NewInt32(js, pitch)); - JS_SetPropertyStr(js, obj, "buffer", ab); - JS_SetPropertyStr(js, obj, "format", JS_NewString(js, "rgba32")); - return obj; -} - -// Exported functions for the module -static const JSCFunctionListEntry js_qr_funcs[] = { - JS_CFUNC_DEF("encode", 2, js_qr_encode), // Updated to expect 2 args - JS_CFUNC_DEF("decode", 4, js_qr_decode), - JS_CFUNC_DEF("rgba", 3, js_qr_rgba), -}; - -// Helper to return the default export object -JSValue js_qr_use(JSContext *js) { - JSValue exports = JS_NewObject(js); - JS_SetPropertyFunctionList(js, exports, js_qr_funcs, sizeof(js_qr_funcs) / sizeof(JSCFunctionListEntry)); - return exports; -} diff --git a/source/qjs_qr.h b/source/qjs_qr.h deleted file mode 100644 index e8acffac..00000000 --- a/source/qjs_qr.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef QJS_QR_H -#define QJS_QR_H - -#include "cell.h" - -JSValue js_qr_use(JSContext*); - -#endif diff --git a/source/qop.h b/source/qop.h index f715e0cf..7b18d1fd 100644 --- a/source/qop.h +++ b/source/qop.h @@ -84,7 +84,7 @@ typedef struct { // Open an archive at path. The supplied qop_desc will be filled with the // information from the file header. Returns the size of the archvie or 0 on -// failure +// failure. int qop_open(const char *path, qop_desc *qop); // Read the index from an opened archive. The supplied buffer will be filled @@ -94,10 +94,10 @@ int qop_open(const char *path, qop_desc *qop); // Returns the number of files in the archive or 0 on error. int qop_read_index(qop_desc *qop, void *buffer); -// Close the archive +// Close the archive. void qop_close(qop_desc *qop); -// Find a file with the supplied path. Returns NULL if the file is not found +// Find a file with the supplied path. Returns NULL if the file is not found. qop_file *qop_find(qop_desc *qop, const char *path); // Copy the path of the file into dest. The dest buffer must be at least @@ -107,7 +107,7 @@ int qop_read_path(qop_desc *qop, qop_file *file, char *dest); // Read the whole file into dest. The dest buffer must be at least file->size // bytes long. -// Returns the number of bytes read +// Returns the number of bytes read. int qop_read(qop_desc *qop, qop_file *file, unsigned char *dest); // Read part of a file into dest. The dest buffer must be at least len bytes @@ -279,4 +279,4 @@ int qop_read_ex(qop_desc *qop, qop_file *file, unsigned char *dest, unsigned int } -#endif /* QOP_IMPLEMENTATION */ +#endif /* QOP_IMPLEMENTATION */ \ No newline at end of file