ref: 5a2f39e8ed1708c9a75b1462e4a037751bd95d8a
parent: 4927e37a042368fa7c2657aaa26ed98fb72dfacc
author: David Turner <[email protected]>
date: Fri Jun 7 21:06:31 EDT 2002
adding template cache lookup routine
--- /dev/null
+++ b/src/cache/ftccache.i
@@ -1,0 +1,141 @@
+#ifndef GEN_CACHE_FAMILY_COMPARE
+#error "GEN_CACHE_FAMILY_COMPARE not defined in template instanciation"
+#endif
+
+#ifndef GEN_CACHE_NODE_COMPARE
+#error "GEN_CACHE_NODE_COMPARE not defined in template instanciation"
+#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