summaryrefslogtreecommitdiff
path: root/src/pdf_bridge.c
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-09 10:41:33 -0300
committerGabriel Schneider <[email protected]>2026-08-10 09:17:07 -0300
commit9085cb5bfdd0b78ff3a62c0c71fc231dd7b5052a (patch)
tree91fce278abc85e4f7491de8b5f02184c8a2d5a56 /src/pdf_bridge.c
parent2b1fac6fecbf7d7cc08f9dad24687b05e9968c9a (diff)
downloadpardes-9085cb5bfdd0b78ff3a62c0c71fc231dd7b5052a.tar.gz
pardes-9085cb5bfdd0b78ff3a62c0c71fc231dd7b5052a.zip
replace ArrayLists with bounded storage
Diffstat (limited to 'src/pdf_bridge.c')
-rw-r--r--src/pdf_bridge.c112
1 files changed, 107 insertions, 5 deletions
diff --git a/src/pdf_bridge.c b/src/pdf_bridge.c
index e0969018..25870f20 100644
--- a/src/pdf_bridge.c
+++ b/src/pdf_bridge.c
@@ -5,12 +5,17 @@
#include <math.h>
#include <limits.h>
#include <stdint.h>
+#include <stdatomic.h>
#include <stdlib.h>
#include <string.h>
#define PARDES_PDF_INITIAL_RESULT_QUADS 64
struct pardes_pdf_document {
+ pardes_pdf_allocator allocator;
+ fz_alloc_context mupdf_allocator;
+ int uses_allocator;
+
fz_context *ctx;
fz_document *doc;
int page_count;
@@ -26,6 +31,97 @@ struct pardes_pdf_document {
int display_list_candidate_page_number;
};
+static pardes_pdf_allocator pardes_pdf_global_allocator;
+static int pardes_pdf_allocator_installed;
+static _Atomic size_t pardes_pdf_active_documents;
+static atomic_flag pardes_pdf_allocator_lock = ATOMIC_FLAG_INIT;
+
+static void
+pardes_pdf_lock_allocator(void)
+{
+ while (atomic_flag_test_and_set_explicit(
+ &pardes_pdf_allocator_lock, memory_order_acquire))
+ ;
+}
+
+static void
+pardes_pdf_unlock_allocator(void)
+{
+ atomic_flag_clear_explicit(
+ &pardes_pdf_allocator_lock, memory_order_release);
+}
+
+
+int
+pardes_pdf_set_allocator(const pardes_pdf_allocator *allocator)
+{
+ int status = PARDES_PDF_OK;
+
+ if (allocator != NULL &&
+ (allocator->alloc == NULL || allocator->realloc == NULL ||
+ allocator->free == NULL))
+ return PARDES_PDF_ERROR;
+
+ pardes_pdf_lock_allocator();
+ if (atomic_load(&pardes_pdf_active_documents) != 0) {
+ status = PARDES_PDF_ERROR;
+ } else if (allocator == NULL) {
+ memset(&pardes_pdf_global_allocator, 0,
+ sizeof(pardes_pdf_global_allocator));
+ pardes_pdf_allocator_installed = 0;
+ } else {
+ pardes_pdf_global_allocator = *allocator;
+ pardes_pdf_allocator_installed = 1;
+ }
+ pardes_pdf_unlock_allocator();
+ return status;
+}
+
+static pardes_pdf_document *
+pardes_pdf_allocate_document(void)
+{
+ pardes_pdf_document *document;
+ pardes_pdf_allocator allocator;
+ int uses_allocator;
+
+ pardes_pdf_lock_allocator();
+ uses_allocator = pardes_pdf_allocator_installed;
+ allocator = pardes_pdf_global_allocator;
+ atomic_fetch_add(&pardes_pdf_active_documents, 1);
+ pardes_pdf_unlock_allocator();
+
+ if (uses_allocator) {
+ document = (pardes_pdf_document *)allocator.alloc(
+ allocator.user, sizeof(*document));
+ } else {
+ document = (pardes_pdf_document *)calloc(1, sizeof(*document));
+ }
+ if (document == NULL) {
+ atomic_fetch_sub(&pardes_pdf_active_documents, 1);
+ return NULL;
+ }
+ if (!uses_allocator)
+ return document;
+
+ memset(document, 0, sizeof(*document));
+ document->allocator = allocator;
+ document->uses_allocator = 1;
+ document->mupdf_allocator.user = allocator.user;
+ document->mupdf_allocator.malloc = allocator.alloc;
+ document->mupdf_allocator.realloc = allocator.realloc;
+ document->mupdf_allocator.free = allocator.free;
+ return document;
+}
+
+static void
+pardes_pdf_free_document(pardes_pdf_document *document)
+{
+ if (document->uses_allocator)
+ document->allocator.free(document->allocator.user, document);
+ else
+ free(document);
+}
+
static void
pardes_pdf_drop_cached_page(pardes_pdf_document *document)
{
@@ -230,15 +326,19 @@ pardes_pdf_open(const char *path, int *page_count)
if (path == NULL || page_count == NULL)
return NULL;
- state = (pardes_pdf_document *)calloc(1, sizeof(*state));
+ state = pardes_pdf_allocate_document();
if (state == NULL)
return NULL;
state->cached_page_number = -1;
state->display_list_candidate_page_number = -1;
- ctx = fz_new_context(NULL, NULL, PARDES_PDF_STORE_LIMIT_BYTES);
+ ctx = fz_new_context(
+ state->uses_allocator ? &state->mupdf_allocator : NULL,
+ NULL,
+ PARDES_PDF_STORE_LIMIT_BYTES);
if (ctx == NULL) {
- free(state);
+ pardes_pdf_free_document(state);
+ atomic_fetch_sub(&pardes_pdf_active_documents, 1);
return NULL;
}
@@ -256,7 +356,8 @@ pardes_pdf_open(const char *path, int *page_count)
fz_report_error(ctx);
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
- free(state);
+ pardes_pdf_free_document(state);
+ atomic_fetch_sub(&pardes_pdf_active_documents, 1);
return NULL;
}
@@ -275,7 +376,8 @@ pardes_pdf_close(pardes_pdf_document *document)
pardes_pdf_drop_cached_page(document);
fz_drop_document(document->ctx, document->doc);
fz_drop_context(document->ctx);
- free(document);
+ pardes_pdf_free_document(document);
+ atomic_fetch_sub(&pardes_pdf_active_documents, 1);
}
int