#ifndef MUPDF_FITZ_STORE_H1#define MUPDF_FITZ_STORE_H23#include "mupdf/fitz/system.h"4#include "mupdf/fitz/context.h"56/*7Resource store89MuPDF stores decoded "objects" into a store for potential reuse.10If the size of the store gets too big, objects stored within it can11be evicted and freed to recover space. When MuPDF comes to decode12such an object, it will check to see if a version of this object is13already in the store - if it is, it will simply reuse it. If not, it14will decode it and place it into the store.1516All objects that can be placed into the store are derived from the17fz_storable type (i.e. this should be the first component of the18objects structure). This allows for consistent (thread safe)19reference counting, and includes a function that will be called to20free the object as soon as the reference count reaches zero.2122Most objects offer fz_keep_XXXX/fz_drop_XXXX functions derived23from fz_keep_storable/fz_drop_storable. Creation of such objects24includes a call to FZ_INIT_STORABLE to set up the fz_storable header.25*/2627typedef struct fz_storable_s fz_storable;2829typedef void (fz_store_drop_fn)(fz_context *, fz_storable *);3031struct fz_storable_s {32int refs;33fz_store_drop_fn *drop;34};3536#define FZ_INIT_STORABLE(S_,RC,DROP) \37do { fz_storable *S = &(S_)->storable; S->refs = (RC); \38S->drop = (DROP); \39} while (0)4041void *fz_keep_storable(fz_context *, fz_storable *);42void fz_drop_storable(fz_context *, fz_storable *);4344/*45The store can be seen as a dictionary that maps keys to fz_storable46values. In order to allow keys of different types to be stored, we47have a structure full of functions for each key 'type'; this48fz_store_type pointer is stored with each key, and tells the store49how to perform certain operations (like taking/dropping a reference,50comparing two keys, outputting details for debugging etc).5152The store uses a hash table internally for speed where possible. In53order for this to work, we need a mechanism for turning a generic54'key' into 'a hashable string'. For this purpose the type structure55contains a make_hash_key function pointer that maps from a void *56to an fz_store_hash structure. If make_hash_key function returns 0,57then the key is determined not to be hashable, and the value is58not stored in the hash table.59*/60typedef struct fz_store_hash_s fz_store_hash;6162struct fz_store_hash_s63{64fz_store_drop_fn *drop;65union66{67struct68{69int i0;70int i1;71void *ptr;72} i;73struct74{75void *ptr;76int i;77} pi;78struct79{80int id;81float m[4];82} im;83} u;84};8586typedef struct fz_store_type_s fz_store_type;8788struct fz_store_type_s89{90int (*make_hash_key)(fz_context *ctx, fz_store_hash *, void *);91void *(*keep_key)(fz_context *,void *);92void (*drop_key)(fz_context *,void *);93int (*cmp_key)(fz_context *ctx, void *, void *);94#ifndef NDEBUG95void (*debug)(fz_context *ctx, FILE *, void *);96#endif97};9899/*100fz_store_new_context: Create a new store inside the context101102max: The maximum size (in bytes) that the store is allowed to grow103to. FZ_STORE_UNLIMITED means no limit.104*/105void fz_new_store_context(fz_context *ctx, unsigned int max);106107/*108fz_drop_store_context: Drop a reference to the store.109*/110void fz_drop_store_context(fz_context *ctx);111112/*113fz_keep_store_context: Take a reference to the store.114*/115fz_store *fz_keep_store_context(fz_context *ctx);116117/*118fz_store_item: Add an item to the store.119120Add an item into the store, returning NULL for success. If an item121with the same key is found in the store, then our item will not be122inserted, and the function will return a pointer to that value123instead. This function takes its own reference to val, as required124(i.e. the caller maintains ownership of its own reference).125126key: The key to use to index the item.127128val: The value to store.129130itemsize: The size in bytes of the value (as counted towards the131store size).132133type: Functions used to manipulate the key.134*/135void *fz_store_item(fz_context *ctx, void *key, void *val, unsigned int itemsize, fz_store_type *type);136137/*138fz_find_item: Find an item within the store.139140drop: The function used to free the value (to ensure we get a value141of the correct type).142143key: The key to use to index the item.144145type: Functions used to manipulate the key.146147Returns NULL for not found, otherwise returns a pointer to the value148indexed by key to which a reference has been taken.149*/150void *fz_find_item(fz_context *ctx, fz_store_drop_fn *drop, void *key, fz_store_type *type);151152/*153fz_remove_item: Remove an item from the store.154155If an item indexed by the given key exists in the store, remove it.156157drop: The function used to free the value (to ensure we get a value158of the correct type).159160key: The key to use to find the item to remove.161162type: Functions used to manipulate the key.163*/164void fz_remove_item(fz_context *ctx, fz_store_drop_fn *drop, void *key, fz_store_type *type);165166/*167fz_empty_store: Evict everything from the store.168*/169void fz_empty_store(fz_context *ctx);170171/*172fz_store_scavenge: Internal function used as part of the scavenging173allocator; when we fail to allocate memory, before returning a174failure to the caller, we try to scavenge space within the store by175evicting at least 'size' bytes. The allocator then retries.176177size: The number of bytes we are trying to have free.178179phase: What phase of the scavenge we are in. Updated on exit.180181Returns non zero if we managed to free any memory.182*/183int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase);184185/*186fz_shrink_store: Evict items from the store until the total size of187the objects in the store is reduced to a given percentage of its188current size.189190percent: %age of current size to reduce the store to.191192Returns non zero if we managed to free enough memory, zero otherwise.193*/194int fz_shrink_store(fz_context *ctx, unsigned int percent);195196/*197fz_print_store: Dump the contents of the store for debugging.198*/199#ifndef NDEBUG200void fz_print_store(fz_context *ctx, FILE *out);201void fz_print_store_locked(fz_context *ctx, FILE *out);202#endif203204#endif205206207