summaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-09-27 02:15:04 +0200
committerTor Andersson <tor@ghostscript.com>2004-09-27 02:15:04 +0200
commit6ddde92a3a45e970b05770633dc6a337d5d013c5 (patch)
tree1dec4612d7469839478e72d16d30a0da5755243c /base
downloadmupdf-6ddde92a3a45e970b05770633dc6a337d5d013c5.tar.xz
Initial import
Diffstat (limited to 'base')
-rw-r--r--base/arc4.c95
-rw-r--r--base/error.c50
-rw-r--r--base/hash.c263
-rw-r--r--base/matrix.c70
-rw-r--r--base/md5.c269
-rw-r--r--base/memory.c81
-rw-r--r--base/rect.c46
7 files changed, 874 insertions, 0 deletions
diff --git a/base/arc4.c b/base/arc4.c
new file mode 100644
index 00000000..86c9afd8
--- /dev/null
+++ b/base/arc4.c
@@ -0,0 +1,95 @@
+/* This code illustrates a sample implementation
+ * of the Arcfour algorithm
+ * Copyright (c) April 29, 1997 Kalle Kaukonen.
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that this copyright
+ * notice and disclaimer are retained.
+ *
+ * THIS SOFTWARE IS PROVIDED BY KALLE KAUKONEN AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KALLE
+ * KAUKONEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <fitz.h>
+
+void
+fz_arc4init(fz_arc4 *arc4, unsigned char *key, unsigned keylen)
+{
+ unsigned int t, u;
+ unsigned int keyindex;
+ unsigned int stateindex;
+ unsigned char *state;
+ unsigned int counter;
+
+ state = arc4->state;
+
+ arc4->x = 0;
+ arc4->y = 0;
+
+ for (counter = 0; counter < 256; counter++) {
+ state[counter] = counter;
+ }
+
+ keyindex = 0;
+ stateindex = 0;
+
+ for (counter = 0; counter < 256; counter++) {
+ t = state[counter];
+ stateindex = (stateindex + key[keyindex] + t) & 0xff;
+ u = state[stateindex];
+
+ state[stateindex] = t;
+ state[counter] = u;
+
+ if (++keyindex >= keylen) {
+ keyindex = 0;
+ }
+ }
+}
+
+unsigned char
+fz_arc4next(fz_arc4 *arc4)
+{
+ unsigned int x;
+ unsigned int y;
+ unsigned int sx, sy;
+ unsigned char *state;
+
+ state = arc4->state;
+
+ x = (arc4->x + 1) & 0xff;
+ sx = state[x];
+ y = (sx + arc4->y) & 0xff;
+ sy = state[y];
+
+ arc4->x = x;
+ arc4->y = y;
+
+ state[y] = sx;
+ state[x] = sy;
+
+ return state[(sx + sy) & 0xff];
+}
+
+void
+fz_arc4encrypt(fz_arc4 *arc4, unsigned char *dest, unsigned char *src, unsigned len)
+{
+ unsigned int i;
+ for (i = 0; i < len; i++) {
+ unsigned char x;
+ x = fz_arc4next(arc4);
+ dest[i] = src[i] ^ x;
+ }
+}
+
diff --git a/base/error.c b/base/error.c
new file mode 100644
index 00000000..bbba9ac3
--- /dev/null
+++ b/base/error.c
@@ -0,0 +1,50 @@
+#include <fitz.h>
+
+void
+fz_warn(char *fmt, ...)
+{
+ va_list ap;
+ fprintf(stderr, "warning: ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+fz_error *
+fz_throw0(const char *func, const char *file, int line, char *fmt, ...)
+{
+ va_list ap;
+ fz_error *eo;
+
+ eo = fz_malloc(sizeof(fz_error));
+ if (!eo) return fz_outofmem;
+
+ strlcpy(eo->func, func, sizeof eo->func);
+ strlcpy(eo->file, file, sizeof eo->file);
+ eo->line = line;
+
+ va_start(ap, fmt);
+ vsnprintf(eo->msg, sizeof eo->msg, fmt, ap);
+ eo->msg[sizeof(eo->msg) - 1] = '\0';
+ va_end(ap);
+
+ return eo;
+}
+
+void
+fz_freeerror(fz_error *eo)
+{
+ if (!eo->frozen)
+ fz_free(eo);
+}
+
+void
+fz_abort(fz_error *eo)
+{
+ fflush(stdout);
+ fprintf(stderr, "%s:%d: %s(): %s\n", eo->file, eo->line, eo->func, eo->msg);
+ fflush(stderr);
+ abort();
+}
+
diff --git a/base/hash.c b/base/hash.c
new file mode 100644
index 00000000..4b85b6b3
--- /dev/null
+++ b/base/hash.c
@@ -0,0 +1,263 @@
+/* Linear probe hash table.
+ * 2004 (C) Tor Andersson.
+ * BSD license.
+ *
+ * Simple hashtable with open adressing linear probe.
+ * Unlike text book examples, removing entries works
+ * correctly in this implementation so it wont start
+ * exhibiting bad behaviour if entries are inserted
+ * and removed frequently.
+ */
+
+#include <fitz.h>
+
+enum { MAXKEYLEN = 16 };
+
+typedef struct fz_hashentry_s fz_hashentry;
+
+struct fz_hashentry_s
+{
+ unsigned char key[MAXKEYLEN];
+ void *val;
+};
+
+struct fz_hashtable_s
+{
+ unsigned keylen;
+ unsigned size;
+ unsigned load;
+ fz_hashentry *ents;
+};
+
+static unsigned hash(unsigned char *s, int len)
+{
+ unsigned hash = 0;
+ unsigned i;
+ for (i = 0; i < len; i++)
+ {
+ hash += s[i];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+ return hash;
+}
+
+fz_error *
+fz_newhash(fz_hashtable **tablep, int initialsize, int keylen)
+{
+ fz_hashtable *table;
+
+ assert(keylen <= MAXKEYLEN);
+
+ table = *tablep = fz_malloc(sizeof(fz_hashtable));
+ if (!table)
+ return fz_outofmem;
+
+ table->keylen = keylen;
+ table->size = initialsize;
+ table->load = 0;
+
+ table->ents = fz_malloc(sizeof(fz_hashentry) * table->size);
+ if (!table->ents)
+ {
+ fz_free(table);
+ *tablep = nil;
+ return fz_outofmem;
+ }
+
+ memset(table->ents, 0, sizeof(fz_hashentry) * table->size);
+
+ return nil;
+}
+
+int
+fz_hashlen(fz_hashtable *table)
+{
+ return table->size;
+}
+
+void *
+fz_gethashkey(fz_hashtable *table, int idx)
+{
+ return table->ents[idx].key;
+}
+
+void *
+fz_gethashval(fz_hashtable *table, int idx)
+{
+ return table->ents[idx].val;
+}
+
+void
+fz_freehash(fz_hashtable *table)
+{
+ fz_free(table->ents);
+ fz_free(table);
+}
+
+fz_error *
+fz_resizehash(fz_hashtable *table, int newsize)
+{
+ fz_error *error;
+ fz_hashentry *newents;
+ fz_hashentry *oldents;
+ unsigned oldload;
+ unsigned oldsize;
+ unsigned i;
+
+ oldsize = table->size;
+ oldload = table->load;
+ oldents = table->ents;
+
+ if (newsize < oldload * 8 / 10)
+ return fz_throw("rangecheck: resize hash too small");
+
+ newents = fz_realloc(table->ents, sizeof(fz_hashentry) * newsize);
+ if (!newents)
+ return fz_outofmem;
+
+ table->size = newsize;
+ table->load = 0;
+ table->ents = newents;
+ memset(table->ents, 0, sizeof(fz_hashentry) * table->size);
+
+ for (i = 0; i < oldsize; i++)
+ {
+ if (oldents[i].val)
+ {
+ error = fz_hashinsert(table, oldents[i].key, oldents[i].val);
+ if (error)
+ {
+ table->size = oldsize;
+ table->load = oldload;
+ table->ents = oldents;
+ fz_free(newents);
+ return error;
+ }
+ }
+ }
+
+ fz_free(oldents);
+ return nil;
+}
+
+void *
+fz_hashfind(fz_hashtable *table, void *key)
+{
+ fz_hashentry *ents = table->ents;
+ unsigned size = table->size;
+ unsigned pos = hash(key, table->keylen) % size;
+
+ while (1)
+ {
+ if (!ents[pos].val)
+ return nil;
+
+ if (memcmp(key, &ents[pos].key, table->keylen) == 0)
+ return ents[pos].val;
+
+ pos = (pos + 1) % size;
+ }
+}
+
+fz_error *
+fz_hashinsert(fz_hashtable *table, void *key, void *val)
+{
+ fz_error *error;
+ fz_hashentry *ents = table->ents;
+ unsigned size = table->size;
+ unsigned pos = hash(key, table->keylen) % size;
+
+ if (table->load > table->size * 8 / 10)
+ {
+ error = fz_resizehash(table, table->size * 2);
+ if (error)
+ return error;
+ }
+
+ while (1)
+ {
+ if (!ents[pos].val)
+ {
+ memcpy(ents[pos].key, key, table->keylen);
+ ents[pos].val = val;
+ table->load ++;
+ return nil;
+ }
+
+ if (memcmp(key, &ents[pos].key, table->keylen) == 0)
+ return fz_throw("rangecheck: overwrite hash slot");
+
+ pos = (pos + 1) % size;
+ }
+
+ return nil;
+}
+
+fz_error *
+fz_hashremove(fz_hashtable *table, void *key)
+{
+ fz_hashentry *ents = table->ents;
+ unsigned size = table->size;
+ unsigned pos = hash(key, table->keylen) % size;
+ unsigned hole, look, code;
+
+ while (1)
+ {
+ if (!ents[pos].val)
+ return fz_throw("rangecheck: remove inexistant hash entry");
+
+ if (memcmp(key, &ents[pos].key, table->keylen) == 0)
+ {
+ ents[pos].val = nil;
+
+ hole = pos;
+ look = (hole + 1) % size;
+
+ while (ents[look].val)
+ {
+ code = hash(ents[look].key, table->keylen) % size;
+ if ((code <= hole && hole < look) ||
+ (look < code && code <= hole) ||
+ (hole < look && look < code))
+ {
+ ents[hole] = ents[look];
+ ents[look].val = nil;
+ hole = look;
+ }
+
+ look = (look + 1) % size;
+ }
+
+ table->load --;
+ return nil;
+ }
+
+ pos = (pos + 1) % size;
+ }
+}
+
+void
+fz_debughash(fz_hashtable *table)
+{
+ int i, k;
+
+ printf("cache load %d / %d\n", table->load, table->size);
+
+ for (i = 0; i < table->size; i++)
+ {
+ if (!table->ents[i].val)
+ printf("table % 4d: empty\n", i);
+ else
+ {
+ printf("table % 4d: key=", i);
+ for (k = 0; k < MAXKEYLEN; k++)
+ printf("%02x", ((char*)table->ents[i].key)[k]);
+ printf(" val=$%p\n", table->ents[i].val);
+ }
+ }
+}
+
diff --git a/base/matrix.c b/base/matrix.c
new file mode 100644
index 00000000..70193427
--- /dev/null
+++ b/base/matrix.c
@@ -0,0 +1,70 @@
+#include <fitz.h>
+
+fz_matrix
+fz_concat(fz_matrix one, fz_matrix two)
+{
+ fz_matrix dst;
+ dst.a = one.a * two.a + one.b * two.c;
+ dst.b = one.a * two.b + one.b * two.d;
+ dst.c = one.c * two.a + one.d * two.c;
+ dst.d = one.c * two.b + one.d * two.d;
+ dst.e = one.e * two.a + one.f * two.c + two.e;
+ dst.f = one.e * two.b + one.f * two.d + two.f;
+ return dst;
+}
+
+fz_matrix
+fz_identity(void)
+{
+ return (fz_matrix) { 1, 0, 0, 1, 0, 0 };
+}
+
+fz_matrix
+fz_scale(float sx, float sy)
+{
+ return (fz_matrix) { sx, 0, 0, sy, 0, 0 };
+}
+
+fz_matrix
+fz_rotate(float theta)
+{
+ float s = sin(theta * M_PI / 180.0);
+ float c = cos(theta * M_PI / 180.0);
+ return (fz_matrix) { c, s, -s, c, 0 ,0 };
+}
+
+fz_matrix
+fz_translate(float tx, float ty)
+{
+ return (fz_matrix) { 1, 0, 0, 1, tx, ty };
+}
+
+fz_matrix
+fz_invertmatrix(fz_matrix src)
+{
+ fz_matrix dst;
+ float rdet = 1.0 / (src.a * src.d - src.b * src.c);
+ dst.a = src.d * rdet;
+ dst.b = -src.b * rdet;
+ dst.c = -src.c * rdet;
+ dst.d = src.a * rdet;
+ dst.e = -src.e * dst.a - src.f * dst.c;
+ dst.f = -src.e * dst.b - src.f * dst.d;
+ return dst;
+}
+
+int
+fz_isrectilinear(fz_matrix m)
+{
+ return (fabs(m.b) < FLT_EPSILON && fabs(m.c) < FLT_EPSILON) ||
+ (fabs(m.a) < FLT_EPSILON && fabs(m.d) < FLT_EPSILON);
+}
+
+fz_point
+fz_transformpoint(fz_matrix m, fz_point p)
+{
+ float x = p.x * m.a + p.y * m.c + m.e;
+ float y = p.x * m.b + p.y * m.d + m.f;
+ return (fz_point) { x, y };
+}
+
diff --git a/base/md5.c b/base/md5.c
new file mode 100644
index 00000000..648532a5
--- /dev/null
+++ b/base/md5.c
@@ -0,0 +1,269 @@
+/*
+MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+
+Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991.
+All rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+*/
+
+#include <fitz.h>
+
+/* Constants for MD5Transform routine */
+enum
+{
+ S11 = 7, S12 = 12, S13 = 17, S14 = 22,
+ S21 = 5, S22 = 9, S23 = 14, S24 = 20,
+ S31 = 4, S32 = 11, S33 = 16, S34 = 23,
+ S41 = 6, S42 = 10, S43 = 15, S44 = 21,
+};
+
+static void encode(unsigned char *, unsigned long *, unsigned);
+static void decode(unsigned long *, unsigned char *, unsigned);
+static void transform(unsigned long state[4], unsigned char block[64]);
+
+static unsigned char padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE rotates x left n bits */
+#define ROTATE(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (unsigned long)(ac); \
+ (a) = ROTATE ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (unsigned long)(ac); \
+ (a) = ROTATE ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (unsigned long)(ac); \
+ (a) = ROTATE ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (unsigned long)(ac); \
+ (a) = ROTATE ((a), (s)); \
+ (a) += (b); \
+ }
+
+static void encode(unsigned char *output, unsigned long *input, unsigned len)
+{
+ unsigned i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+static void decode(unsigned long *output, unsigned char *input, unsigned len)
+{
+ unsigned i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[i] = ((unsigned long)input[j]) |
+ (((unsigned long)input[j+1]) << 8) |
+ (((unsigned long)input[j+2]) << 16) |
+ (((unsigned long)input[j+3]) << 24);
+ }
+}
+
+static void transform(unsigned long state[4], unsigned char block[64])
+{
+ unsigned long a = state[0];
+ unsigned long b = state[1];
+ unsigned long c = state[2];
+ unsigned long d = state[3];
+ unsigned long x[16];
+
+ decode(x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information */
+ memset(x, 0, sizeof (x));
+}
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context. */
+void fz_md5init(fz_md5 *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest operation,
+ * processing another message block, and updating the context.
+ */
+void fz_md5update(fz_md5 *context, unsigned char *input, unsigned inlen)
+{
+ unsigned i, index, partlen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ context->count[0] += (unsigned long) inlen << 3;
+ if (context->count[0] < (unsigned long) inlen << 3)
+ context->count[1] ++;
+ context->count[1] += (unsigned long) inlen >> 29;
+
+ partlen = 64 - index;
+
+ /* Transform as many times as possible. */
+ if (inlen >= partlen) {
+ memcpy(context->buffer + index, input, partlen);
+ transform(context->state, context->buffer);
+
+ for (i = partlen; i + 63 < inlen; i += 64)
+ transform(context->state, input + i);
+
+ index = 0;
+ }
+ else {
+ i = 0;
+ }
+
+ /* Buffer remaining input */
+ memcpy(context->buffer + index, input + i, inlen - i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+void fz_md5final(fz_md5 *context, unsigned char digest[16])
+{
+ unsigned char bits[8];
+ unsigned index, padlen;
+
+ /* Save number of bits */
+ encode(bits, context->count, 8);
+
+ /* Pad out to 56 mod 64 */
+ index = (unsigned)((context->count[0] >> 3) & 0x3f);
+ padlen = index < 56 ? 56 - index : 120 - index;
+ fz_md5update(context, padding, padlen);
+
+ /* Append length (before padding) */
+ fz_md5update(context, bits, 8);
+
+ /* Store state in digest */
+ encode(digest, context->state, 16);
+
+ /* Zeroize sensitive information */
+ memset(context, 0, sizeof(fz_md5));
+}
+
diff --git a/base/memory.c b/base/memory.c
new file mode 100644
index 00000000..88102d00
--- /dev/null
+++ b/base/memory.c
@@ -0,0 +1,81 @@
+#include <fitz.h>
+
+/* Make this thread local storage if you wish. */
+
+static void *stdmalloc(fz_memorycontext *mem, int n)
+{
+#if 0
+ void *p = malloc(n);
+ if (!p)
+ fprintf(stderr, "failed to malloc %d bytes\n", n);
+ return p;
+#else
+ return malloc(n);
+#endif
+}
+
+static void *stdrealloc(fz_memorycontext *mem, void *p, int n)
+{
+#if 0
+ void *np = realloc(p, n);
+ if (np == nil)
+ fprintf(stderr, "realloc failed %d nytes", n);
+ else if (np == p)
+ fprintf(stderr, "realloc kept %d\n", n);
+ else
+ fprintf(stderr, "realloc moved %d\n", n);
+ return np;
+#else
+ return realloc(p, n);
+#endif
+}
+
+static void stdfree(fz_memorycontext *mem, void *p)
+{
+ free(p);
+}
+
+static fz_memorycontext defmem = { stdmalloc, stdrealloc, stdfree };
+static fz_memorycontext *curmem = &defmem;
+
+fz_error fz_koutofmem = {
+ .msg = {"out of memory"},
+ .func = {"<malloc>"},
+ .file = {"memory.c"},
+ .line = 0,
+ .frozen = 1
+};
+
+fz_memorycontext *
+fz_currentmemorycontext()
+{
+ return curmem;
+}
+
+void
+fz_setmemorycontext(fz_memorycontext *mem)
+{
+ curmem = mem;
+}
+
+void *
+fz_malloc(int n)
+{
+ fz_memorycontext *mem = fz_currentmemorycontext();
+ return mem->malloc(mem, n);
+}
+
+void *
+fz_realloc(void *p, int n)
+{
+ fz_memorycontext *mem = fz_currentmemorycontext();
+ return mem->realloc(mem, p, n);
+}
+
+void
+fz_free(void *p)
+{
+ fz_memorycontext *mem = fz_currentmemorycontext();
+ mem->free(mem, p);
+}
+
diff --git a/base/rect.c b/base/rect.c
new file mode 100644
index 00000000..cb15d434
--- /dev/null
+++ b/base/rect.c
@@ -0,0 +1,46 @@
+#include <fitz.h>
+
+fz_rect
+fz_intersectrects(fz_rect a, fz_rect b)
+{
+ fz_rect r;
+ r.min.x = MAX(a.min.x, b.min.x);
+ r.min.y = MAX(a.min.y, b.min.y);
+ r.max.x = MIN(a.max.x, b.max.x);
+ r.max.y = MIN(a.max.y, b.max.y);
+ return r;
+}
+
+fz_rect
+fz_mergerects(fz_rect a, fz_rect b)
+{
+ fz_rect r;
+ r.min.x = MIN(a.min.x, b.min.x);
+ r.min.y = MIN(a.min.y, b.min.y);
+ r.max.x = MAX(a.max.x, b.max.x);
+ r.max.y = MAX(a.max.y, b.max.y);
+ return r;
+}
+
+fz_irect
+fz_intersectirects(fz_irect a, fz_irect b)
+{
+ fz_irect r;
+ r.min.x = MAX(a.min.x, b.min.x);
+ r.min.y = MAX(a.min.y, b.min.y);
+ r.max.x = MIN(a.max.x, b.max.x);
+ r.max.y = MIN(a.max.y, b.max.y);
+ return r;
+}
+
+fz_irect
+fz_mergeirects(fz_irect a, fz_irect b)
+{
+ fz_irect r;
+ r.min.x = MIN(a.min.x, b.min.x);
+ r.min.y = MIN(a.min.y, b.min.y);
+ r.max.x = MAX(a.max.x, b.max.x);
+ r.max.y = MAX(a.max.y, b.max.y);
+ return r;
+}
+