	Cache for small images

	The algorithm for deciding whether a document should be cached
	if very simple: the document must be of type image and it
	must be smaller than 4K.

	All kinds of improvements are possible: cache other types as
	well, add a cache replacement algorithm, speed up the cache
	look-up, etc.

	Bert Bos [[<bert@let.rug.nl>]], Nov 1994

<<*>>=
static char copyright[] = "Copyright NBBI, Den Haag, 1994";
#include "config.h"
#include <Xm/Xm.h>
#include "w3a.h"
#include "str.h"
#include "url.h"
#include "w3alib.h"

#define CACHETABLESIZE 250
#define MAXDOCSIZE 4096

struct {
    W3ADocumentInfo *info;
    char *buf;
    size_t buflen;
    Bool complete;
} table[CACHETABLESIZE];

int nrcached = 0;


/* in_cache -- check if this document is in the cache, return where it is */
EXPORT Bool in_cache(W3ADocumentInfo *doc, const char **where, size_t *howmuch)
{
    int i;

    for (i = 0; i < nrcached; i++)
	if (eq(doc->url, table[i].info->url) && table[i].complete) {
	    copy_doc(doc, *table[i].info);
	    *where = table[i].buf;
	    *howmuch = table[i].buflen;
	    return TRUE;
	}
    return FALSE;
}


/* new_cache_id -- return a cache index, or -1 if not caching */
EXPORT int new_cache_id(const W3ADocumentInfo doc)
{
    if (nrcached < CACHETABLESIZE
	&& 0 <= doc.size && doc.size <= MAXDOCSIZE
	&& fnmatch("image/*", doc.mime_type, 0) == 0) {
	table[nrcached].info = new_doc();
	copy_doc(table[nrcached].info, doc);
	table[nrcached].buf = NULL;
	table[nrcached].buflen = 0;
	table[nrcached].complete = FALSE;
	return nrcached++;
    } else {
	return -1;
    }
}


/* store_in_cache -- add the data to the cache */
EXPORT void store_in_cache(int id, const char *buf, size_t nbytes)
{
    assert(0 <= id && id < nrcached && nrcached <= CACHETABLESIZE);
    renewarray(table[id].buf, table[id].buflen + nbytes);
    memcpy(table[id].buf + table[id].buflen, buf, nbytes);
    table[id].buflen += nbytes;
    if (nbytes == 0) table[id].complete = TRUE;
}
