Pillow
338 строк · 7.3 Кб
1/*
2* The Python Imaging Library
3* $Id$
4*
5* hash tables used by the image quantizer
6*
7* history:
8* 98-09-10 tjs Contributed
9* 98-12-29 fl Added to PIL 1.0b1
10*
11* Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
12*
13* Copyright (c) 1998 by Toby J Sargeant
14* Copyright (c) 1998 by Secret Labs AB
15*
16* See the README file for information on usage and redistribution.
17*/
18
19#include <stdio.h>20#include <stdlib.h>21#include <string.h>22#include <math.h>23
24#include "QuantHash.h"25
26typedef struct _HashNode {27struct _HashNode *next;28HashKey_t key;29HashVal_t value;30} HashNode;31
32struct _HashTable {33HashNode **table;34uint32_t length;35uint32_t count;36HashFunc hashFunc;37HashCmpFunc cmpFunc;38void *userData;39};40
41#define MIN_LENGTH 1142#define RESIZE_FACTOR 343
44static int45_hashtable_insert_node(HashTable *, HashNode *, int, int, CollisionFunc);46
47HashTable *48hashtable_new(HashFunc hf, HashCmpFunc cf) {49HashTable *h;50h = malloc(sizeof(HashTable));51if (!h) {52return NULL;53}54h->hashFunc = hf;55h->cmpFunc = cf;56h->length = MIN_LENGTH;57h->count = 0;58h->userData = NULL;59h->table = malloc(sizeof(HashNode *) * h->length);60if (!h->table) {61free(h);62return NULL;63}64memset(h->table, 0, sizeof(HashNode *) * h->length);65return h;66}
67
68static uint32_t69_findPrime(uint32_t start, int dir) {70static int unit[] = {0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0};71uint32_t t;72while (start > 1) {73if (!unit[start & 0x0f]) {74start += dir;75continue;76}77for (t = 2; t < sqrt((double)start); t++) {78if (!start % t) {79break;80}81}82if (t >= sqrt((double)start)) {83break;84}85start += dir;86}87return start;88}
89
90static void91_hashtable_rehash(HashTable *h, CollisionFunc cf, uint32_t newSize) {92HashNode **oldTable = h->table;93uint32_t i;94HashNode *n, *nn;95uint32_t oldSize;96oldSize = h->length;97h->table = malloc(sizeof(HashNode *) * newSize);98if (!h->table) {99h->table = oldTable;100return;101}102h->length = newSize;103h->count = 0;104memset(h->table, 0, sizeof(HashNode *) * h->length);105for (i = 0; i < oldSize; i++) {106for (n = oldTable[i]; n; n = nn) {107nn = n->next;108_hashtable_insert_node(h, n, 0, 0, cf);109}110}111free(oldTable);112}
113
114static void115_hashtable_resize(HashTable *h) {116uint32_t newSize;117uint32_t oldSize;118oldSize = h->length;119newSize = oldSize;120if (h->count * RESIZE_FACTOR < h->length) {121newSize = _findPrime(h->length / 2 - 1, -1);122} else if (h->length * RESIZE_FACTOR < h->count) {123newSize = _findPrime(h->length * 2 + 1, +1);124}125if (newSize < MIN_LENGTH) {126newSize = oldSize;127}128if (newSize != oldSize) {129_hashtable_rehash(h, NULL, newSize);130}131}
132
133static int134_hashtable_insert_node(135HashTable *h, HashNode *node, int resize, int update, CollisionFunc cf136) {137uint32_t hash = h->hashFunc(h, node->key) % h->length;138HashNode **n, *nv;139int i;140
141for (n = &(h->table[hash]); *n; n = &((*n)->next)) {142nv = *n;143i = h->cmpFunc(h, nv->key, node->key);144if (!i) {145if (cf) {146nv->key = node->key;147cf(h, &(nv->key), &(nv->value), node->key, node->value);148free(node);149return 1;150} else {151nv->key = node->key;152nv->value = node->value;153free(node);154return 1;155}156} else if (i > 0) {157break;158}159}160if (!update) {161node->next = *n;162*n = node;163h->count++;164if (resize) {165_hashtable_resize(h);166}167return 1;168} else {169return 0;170}171}
172
173static int174_hashtable_insert(HashTable *h, HashKey_t key, HashVal_t val, int resize, int update) {175HashNode **n, *nv;176HashNode *t;177int i;178uint32_t hash = h->hashFunc(h, key) % h->length;179
180for (n = &(h->table[hash]); *n; n = &((*n)->next)) {181nv = *n;182i = h->cmpFunc(h, nv->key, key);183if (!i) {184nv->value = val;185return 1;186} else if (i > 0) {187break;188}189}190if (!update) {191t = malloc(sizeof(HashNode));192if (!t) {193return 0;194}195t->next = *n;196*n = t;197t->key = key;198t->value = val;199h->count++;200if (resize) {201_hashtable_resize(h);202}203return 1;204} else {205return 0;206}207}
208
209int
210hashtable_insert_or_update_computed(211HashTable *h, HashKey_t key, ComputeFunc newFunc, ComputeFunc existsFunc212) {213HashNode **n, *nv;214HashNode *t;215int i;216uint32_t hash = h->hashFunc(h, key) % h->length;217
218for (n = &(h->table[hash]); *n; n = &((*n)->next)) {219nv = *n;220i = h->cmpFunc(h, nv->key, key);221if (!i) {222if (existsFunc) {223existsFunc(h, nv->key, &(nv->value));224} else {225return 0;226}227return 1;228} else if (i > 0) {229break;230}231}232t = malloc(sizeof(HashNode));233if (!t) {234return 0;235}236t->key = key;237t->next = *n;238*n = t;239if (newFunc) {240newFunc(h, t->key, &(t->value));241} else {242free(t);243return 0;244}245h->count++;246_hashtable_resize(h);247return 1;248}
249
250int
251hashtable_insert(HashTable *h, HashKey_t key, HashVal_t val) {252return _hashtable_insert(h, key, val, 1, 0);253}
254
255void
256hashtable_foreach_update(HashTable *h, IteratorUpdateFunc i, void *u) {257HashNode *n;258uint32_t x;259
260if (h->table) {261for (x = 0; x < h->length; x++) {262for (n = h->table[x]; n; n = n->next) {263i(h, n->key, &(n->value), u);264}265}266}267}
268
269void
270hashtable_foreach(HashTable *h, IteratorFunc i, void *u) {271HashNode *n;272uint32_t x;273
274if (h->table) {275for (x = 0; x < h->length; x++) {276for (n = h->table[x]; n; n = n->next) {277i(h, n->key, n->value, u);278}279}280}281}
282
283void
284hashtable_free(HashTable *h) {285HashNode *n, *nn;286uint32_t i;287
288if (h->table) {289for (i = 0; i < h->length; i++) {290for (n = h->table[i]; n; n = nn) {291nn = n->next;292free(n);293}294}295free(h->table);296}297free(h);298}
299
300void
301hashtable_rehash_compute(HashTable *h, CollisionFunc cf) {302_hashtable_rehash(h, cf, h->length);303}
304
305int
306hashtable_lookup(const HashTable *h, const HashKey_t key, HashVal_t *valp) {307uint32_t hash = h->hashFunc(h, key) % h->length;308HashNode *n;309int i;310
311for (n = h->table[hash]; n; n = n->next) {312i = h->cmpFunc(h, n->key, key);313if (!i) {314*valp = n->value;315return 1;316} else if (i > 0) {317break;318}319}320return 0;321}
322
323uint32_t
324hashtable_get_count(const HashTable *h) {325return h->count;326}
327
328void *329hashtable_get_user_data(const HashTable *h) {330return h->userData;331}
332
333void *334hashtable_set_user_data(HashTable *h, void *data) {335void *r = h->userData;336h->userData = data;337return r;338}
339