Hash :
8c90c22d
Author :
Date :
2002-06-08T06:47:18
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
/***************************************************************************/
/* */
/* ftccache.i */
/* */
/* FreeType template for generic cache. */
/* */
/* Copyright 2002 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#ifndef GEN_CACHE_FAMILY_COMPARE
#error "GEN_CACHE_FAMILY_COMPARE not defined in template instantiation"
#endif
#ifndef GEN_CACHE_NODE_COMPARE
#error "GEN_CACHE_NODE_COMPARE not defined in template instantiation"
#endif
static FT_Error
GEN_CACHE_LOOKUP( FTC_Cache cache,
FTC_Query query,
FTC_Node *anode )
{
FT_LruNode lru;
query->hash = 0;
query->family = NULL;
/* XXX: we break encapsulation for the sake of speed! */
{
/* first of all, find the relevant family */
FT_LruList list = cache->families;
FT_LruNode fam, *pfam;
pfam = &list->nodes;
for (;;)
{
fam = *pfam;
if ( fam == NULL )
goto Normal;
if ( GEN_CACHE_FAMILY_COMPARE( fam, query, list->data ) )
break;
pfam = &fam->next;
}
FT_ASSERT( fam != NULL );
/* move to top of list when needed */
if ( fam != list->nodes )
{
*pfam = fam->next;
fam->next = list->nodes;
list->nodes = fam;
}
lru = fam;
}
{
FTC_Family family = (FTC_Family) lru;
FT_UFast hash = query->hash;
FTC_Node node, *pnode, *bucket;
#ifdef FTC_CACHE_USE_LINEAR_HASHING
FT_UInt index;
index = hash & cache->mask;
if ( index < cache->p )
index = hash & ( cache->mask * 2 + 1 );
bucket = cache->buckets + index;
#else
bucket = cache->buckets + ( hash % cache->size );
#endif
#ifdef FT_DEBUG_LEVEL_ERROR
if ( query->family != family ||
family->fam_index >= cache->manager->families.size )
{
FT_ERROR((
"ftc_cache_lookup: invalid query (bad 'family' field)\n" ));
return FTC_Err_Invalid_Argument;
}
#endif
pnode = bucket;
for ( ;; )
{
node = *pnode;
if ( node == NULL )
goto Normal;
if ( node->hash == hash &&
(FT_UInt)node->fam_index == family->fam_index &&
GEN_CACHE_NODE_COMPARE( node, query, cache ) )
{
/* we place the following out of the loop to make it */
/* as small as possible... */
goto Found;
}
pnode = &node->link;
}
Normal:
return ftc_cache_lookup( cache, query, anode );
Found:
/* move to head of bucket list */
if ( pnode != bucket )
{
*pnode = node->link;
node->link = *bucket;
*bucket = node;
}
/* move to head of MRU list */
if ( node != cache->manager->nodes_list )
{
/* XXX: again, this is an inlined version of ftc_node_mru_up */
FTC_Manager manager = cache->manager;
FTC_Node first = manager->nodes_list;
FTC_Node prev = node->mru_prev;
FTC_Node next = node->mru_next;
FTC_Node last;
prev->mru_next = next;
next->mru_prev = prev;
last = first->mru_prev;
node->mru_next = first;
node->mru_prev = last;
first->mru_prev = node;
last->mru_next = node;
manager->nodes_list = node;
}
*anode = node;
return 0;
}
}
#undef GEN_CACHE_NODE_COMPARE
#undef GEN_CACHE_FAMILY_COMPARE
#undef GEN_CACHE_LOOKUP
/* END */