adding template cache lookup routine
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
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