Commit 5a2f39e8ed1708c9a75b1462e4a037751bd95d8a

David Turner 2002-06-08T01:06:31

adding template cache lookup routine

diff --git a/src/cache/ftccache.i b/src/cache/ftccache.i
new file mode 100644
index 0000000..ca7f748
--- /dev/null
+++ b/src/cache/ftccache.i
@@ -0,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