* PERFORMANCE OF THIS SOFTWARE.
*/
-#include <stdlib.h>
-#include <sys/mman.h>
#include "fcint.h"
+#include <stdlib.h>
/* #define CHECK */
-/* #define CHATTY */
-
-static FcCharSet * charsets = 0;
-static FcChar16 * numbers = 0;
-static int charset_ptr, charset_count;
-static int charset_numbers_ptr, charset_numbers_count;
-static FcCharLeaf * leaves = 0;
-static int charset_leaf_ptr, charset_leaf_count;
-static int * leaf_idx = 0;
-static int charset_leaf_idx_ptr, charset_leaf_idx_count;
-
-void
-FcCharSetClearStatic()
-{
- charsets = 0;
- numbers = 0;
- charset_ptr = 0; charset_count = 0;
- leaves = 0;
- charset_leaf_ptr = 0; charset_leaf_count = 0;
- leaf_idx = 0;
- charset_leaf_idx_ptr = 0; charset_leaf_idx_count = 0;
-}
-
FcCharSet *
FcCharSetCreate (void)
{
FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
fcs->ref = 1;
fcs->num = 0;
- fcs->storage = FcStorageDynamic;
- fcs->u.dyn.leaves = 0;
- fcs->u.dyn.numbers = 0;
+ fcs->leaves_offset = 0;
+ fcs->numbers_offset = 0;
return fcs;
}
-FcCharSet *
-FcCharSetNew (void);
-
FcCharSet *
FcCharSetNew (void)
{
return FcCharSetCreate ();
}
-void
-FcCharSetPtrDestroy (FcCharSetPtr fcs)
-{
- FcCharSetDestroy (FcCharSetPtrU(fcs));
- if (fcs.storage == FcStorageDynamic &&
- FcCharSetPtrU(fcs)->ref != FC_REF_CONSTANT)
- {
- free (fcs.u.dyn);
- FcMemFree (FC_MEM_CHARSET, sizeof(FcCharSet));
- }
-}
-
void
FcCharSetDestroy (FcCharSet *fcs)
{
int i;
+
if (fcs->ref == FC_REF_CONSTANT)
+ {
+ FcCacheObjectDereference (fcs);
return;
+ }
if (--fcs->ref > 0)
return;
- if (fcs->storage == FcStorageDynamic)
+ for (i = 0; i < fcs->num; i++)
{
- for (i = 0; i < fcs->num; i++)
- {
- FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
- free (fcs->u.dyn.leaves[i]);
- }
- if (fcs->u.dyn.leaves)
- {
- FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
- free (fcs->u.dyn.leaves);
- }
- if (fcs->u.dyn.numbers)
- {
- FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
- free (fcs->u.dyn.numbers);
- }
+ FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
+ free (FcCharSetLeaf (fcs, i));
+ }
+ if (fcs->num)
+ {
+ FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (intptr_t));
+ free (FcCharSetLeaves (fcs));
+ }
+ if (fcs->num)
+ {
+ FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
+ free (FcCharSetNumbers (fcs));
}
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (fcs);
static int
FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
{
- FcChar16 *numbers = FcCharSetGetNumbers(fcs);
+ FcChar16 *numbers = FcCharSetNumbers(fcs);
FcChar16 page;
int low = 0;
int high = fcs->num - 1;
{
int pos = FcCharSetFindLeafPos (fcs, ucs4);
if (pos >= 0)
- return FcCharSetGetLeaf(fcs, pos);
+ return FcCharSetLeaf(fcs, pos);
return 0;
}
FcCharLeaf *leaf,
int pos)
{
- FcCharLeaf **leaves;
- FcChar16 *numbers;
+ intptr_t *leaves = FcCharSetLeaves (fcs);
+ FcChar16 *numbers = FcCharSetNumbers (fcs);
ucs4 >>= 8;
if (ucs4 >= 0x10000)
return FcFalse;
- if (fcs->storage == FcStorageStatic)
+ if (!fcs->num)
+ leaves = malloc (sizeof (*leaves));
+ else
{
- int i;
-
- leaves = malloc ((fcs->num + 1) * sizeof (FcCharLeaf *));
- if (!leaves)
- return FcFalse;
- FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcCharLeaf *));
- numbers = malloc ((fcs->num + 1) * sizeof (FcChar16));
- if (!numbers)
- return FcFalse;
- FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcChar16));
+ intptr_t *new_leaves = realloc (leaves, (fcs->num + 1) *
+ sizeof (*leaves));
+ intptr_t distance = (intptr_t) new_leaves - (intptr_t) leaves;
+
+ if (new_leaves && distance)
+ {
+ int i;
- for (i = 0; i < fcs->num; i++)
- leaves[i] = FcCharSetGetLeaf(fcs, i);
- memcpy (numbers, FcCharSetGetNumbers(fcs),
- fcs->num * sizeof (FcChar16));
- fcs->storage = FcStorageDynamic;
+ for (i = 0; i < fcs->num; i++)
+ new_leaves[i] -= distance;
+ }
+ leaves = new_leaves;
}
+ if (!leaves)
+ return FcFalse;
+
+ if (fcs->num)
+ FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (intptr_t));
+ FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (intptr_t));
+ fcs->leaves_offset = FcPtrToOffset (fcs, leaves);
+
+ if (!fcs->num)
+ numbers = malloc (sizeof (FcChar16));
else
- {
- if (!fcs->u.dyn.leaves)
- leaves = malloc (sizeof (FcCharLeaf *));
- else
- leaves = realloc (fcs->u.dyn.leaves, (fcs->num + 1) * sizeof (FcCharLeaf *));
- if (!leaves)
- return FcFalse;
- if (fcs->num)
- FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
- FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcCharLeaf *));
- fcs->u.dyn.leaves = leaves;
- if (!fcs->u.dyn.numbers)
- numbers = malloc (sizeof (FcChar16));
- else
- numbers = realloc (fcs->u.dyn.numbers, (fcs->num + 1) * sizeof (FcChar16));
- if (!numbers)
- return FcFalse;
- if (fcs->num)
- FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
- FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcChar16));
- fcs->u.dyn.numbers = numbers;
- }
+ numbers = realloc (numbers, (fcs->num + 1) * sizeof (FcChar16));
+ if (!numbers)
+ return FcFalse;
+
+ if (fcs->num)
+ FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
+ FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcChar16));
+ fcs->numbers_offset = FcPtrToOffset (fcs, numbers);
- memmove (fcs->u.dyn.leaves + pos + 1, fcs->u.dyn.leaves + pos,
- (fcs->num - pos) * sizeof (FcCharLeaf *));
- memmove (fcs->u.dyn.numbers + pos + 1, fcs->u.dyn.numbers + pos,
- (fcs->num - pos) * sizeof (FcChar16));
- fcs->u.dyn.numbers[pos] = (FcChar16) ucs4;
- fcs->u.dyn.leaves[pos] = leaf;
+ memmove (leaves + pos + 1, leaves + pos,
+ (fcs->num - pos) * sizeof (*leaves));
+ memmove (numbers + pos + 1, numbers + pos,
+ (fcs->num - pos) * sizeof (*numbers));
+ numbers[pos] = (FcChar16) ucs4;
+ leaves[pos] = FcPtrToOffset (leaves, leaf);
fcs->num++;
return FcTrue;
}
pos = FcCharSetFindLeafPos (fcs, ucs4);
if (pos >= 0)
- return FcCharSetGetLeaf(fcs, pos);
+ return FcCharSetLeaf(fcs, pos);
leaf = calloc (1, sizeof (FcCharLeaf));
if (!leaf)
if (pos >= 0)
{
FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
- if (fcs->storage == FcStorageDynamic)
- {
- free (fcs->u.dyn.leaves[pos]);
- fcs->u.dyn.leaves[pos] = leaf;
- }
- else
- {
- leaves[leaf_idx[fcs->u.stat.leafidx_offset]+pos] = *leaf;
- }
+ free (FcCharSetLeaf (fcs, pos));
+ FcCharSetLeaves(fcs)[pos] = FcPtrToOffset (FcCharSetLeaves(fcs),
+ leaf);
return FcTrue;
}
pos = -pos - 1;
iter->leaf = 0;
return;
}
- iter->ucs4 = (FcChar32) FcCharSetGetNumbers(fcs)[pos] << 8;
+ iter->ucs4 = (FcChar32) FcCharSetNumbers(fcs)[pos] << 8;
}
- iter->leaf = FcCharSetGetLeaf(fcs, pos);
+ iter->leaf = FcCharSetLeaf(fcs, pos);
iter->pos = pos;
-#ifdef CHATTY
- printf ("set %08x: %08x\n", iter->ucs4, (FcChar32) iter->leaf);
-#endif
}
static void
}
else
{
- iter->ucs4 = (FcChar32) FcCharSetGetNumbers(fcs)[pos] << 8;
- iter->leaf = FcCharSetGetLeaf(fcs, pos);
+ iter->ucs4 = (FcChar32) FcCharSetNumbers(fcs)[pos] << 8;
+ iter->leaf = FcCharSetLeaf(fcs, pos);
iter->pos = pos;
}
}
-#ifdef CHATTY
-static void
-FcCharSetDump (const FcCharSet *fcs)
-{
- int pos;
-
- printf ("fcs %08x:\n", (FcChar32) fcs);
- for (pos = 0; pos < fcs->num; pos++)
- {
- FcCharLeaf *leaf = fcs->leaves[pos];
- FcChar32 ucs4 = (FcChar32) fcs->numbers[pos] << 8;
-
- printf (" %08x: %08x\n", ucs4, (FcChar32) leaf);
- }
-}
-#endif
static void
FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
{
-#ifdef CHATTY
- FcCharSetDump (fcs);
-#endif
iter->ucs4 = 0;
+ iter->pos = 0;
FcCharSetIterSet (fcs, iter);
}
{
if (src->ref != FC_REF_CONSTANT)
src->ref++;
- return src;
-}
-
-FcCharSetPtr
-FcCharSetCopyPtr (FcCharSetPtr src)
-{
- if (FcCharSetPtrU(src)->ref != FC_REF_CONSTANT)
- FcCharSetPtrU(src)->ref++;
+ else
+ FcCacheObjectReference (src);
return src;
}
int i = 256/32;
if (ai.ucs4 == bi.ucs4)
{
- FcChar32 *bm = bi.leaf->map;;
+ FcChar32 *bm = bi.leaf->map;
while (i--)
count += FcCharSetPopCount (*am++ & ~*bm++);
}
ai = 0;
while (ai < a->num && bi < b->num)
{
- an = FcCharSetGetNumbers(a)[ai];
- bn = FcCharSetGetNumbers(b)[bi];
+ an = FcCharSetNumbers(a)[ai];
+ bn = FcCharSetNumbers(b)[bi];
/*
* Check matching pages
*/
if (an == bn)
{
- FcChar32 *am = FcCharSetGetLeaf(a, ai)->map;
- FcChar32 *bm = FcCharSetGetLeaf(b, bi)->map;
+ FcChar32 *am = FcCharSetLeaf(a, ai)->map;
+ FcChar32 *bm = FcCharSetLeaf(b, bi)->map;
if (am != bm)
{
while (low <= high)
{
int mid = (low + high) >> 1;
- bn = FcCharSetGetNumbers(b)[mid];
+ bn = FcCharSetNumbers(b)[mid];
if (bn == an)
{
high = mid;
high = mid - 1;
}
bi = high;
- while (bi < b->num && FcCharSetGetNumbers(b)[bi] < an)
+ while (bi < b->num && FcCharSetNumbers(b)[bi] < an)
bi++;
}
}
/*
* old coverage API, rather hard to use correctly
*/
-FcChar32
-FcCharSetCoverage (const FcCharSet *a, FcChar32 page, FcChar32 *result);
FcChar32
FcCharSetCoverage (const FcCharSet *a, FcChar32 page, FcChar32 *result)
return FcTrue;
}
+FcCharSet *
+FcNameParseCharSet (FcChar8 *string)
+{
+ FcCharSet *c;
+ FcChar32 ucs4;
+ FcCharLeaf *leaf;
+ FcCharLeaf temp;
+ FcChar32 bits;
+ int i;
+
+ c = FcCharSetCreate ();
+ if (!c)
+ goto bail0;
+ while (*string)
+ {
+ string = FcCharSetParseValue (string, &ucs4);
+ if (!string)
+ goto bail1;
+ bits = 0;
+ for (i = 0; i < 256/32; i++)
+ {
+ string = FcCharSetParseValue (string, &temp.map[i]);
+ if (!string)
+ goto bail1;
+ bits |= temp.map[i];
+ }
+ if (bits)
+ {
+ leaf = malloc (sizeof (FcCharLeaf));
+ if (!leaf)
+ goto bail1;
+ *leaf = temp;
+ if (!FcCharSetInsertLeaf (c, ucs4, leaf))
+ goto bail1;
+ }
+ }
+ return c;
+bail1:
+ if (c->num)
+ {
+ FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
+ free (FcCharSetLeaves (c));
+ }
+ if (c->num)
+ {
+ FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
+ free (FcCharSetNumbers (c));
+ }
+ FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
+ free (c);
+bail0:
+ return NULL;
+}
+
+FcBool
+FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
+{
+ FcCharSetIter ci;
+ int i;
+#ifdef CHECK
+ int len = buf->len;
+#endif
+
+ for (FcCharSetIterStart (c, &ci);
+ ci.leaf;
+ FcCharSetIterNext (c, &ci))
+ {
+ if (!FcCharSetUnparseValue (buf, ci.ucs4))
+ return FcFalse;
+ for (i = 0; i < 256/32; i++)
+ if (!FcCharSetUnparseValue (buf, ci.leaf->map[i]))
+ return FcFalse;
+ }
+#ifdef CHECK
+ {
+ FcCharSet *check;
+ FcChar32 missing;
+ FcCharSetIter ci, checki;
+
+ /* null terminate for parser */
+ FcStrBufChar (buf, '\0');
+ /* step back over null for life after test */
+ buf->len--;
+ check = FcNameParseCharSet (buf->buf + len);
+ FcCharSetIterStart (c, &ci);
+ FcCharSetIterStart (check, &checki);
+ while (ci.leaf || checki.leaf)
+ {
+ if (ci.ucs4 < checki.ucs4)
+ {
+ printf ("Missing leaf node at 0x%x\n", ci.ucs4);
+ FcCharSetIterNext (c, &ci);
+ }
+ else if (checki.ucs4 < ci.ucs4)
+ {
+ printf ("Extra leaf node at 0x%x\n", checki.ucs4);
+ FcCharSetIterNext (check, &checki);
+ }
+ else
+ {
+ int i = 256/32;
+ FcChar32 *cm = ci.leaf->map;
+ FcChar32 *checkm = checki.leaf->map;
+
+ for (i = 0; i < 256; i += 32)
+ {
+ if (*cm != *checkm)
+ printf ("Mismatching sets at 0x%08x: 0x%08x != 0x%08x\n",
+ ci.ucs4 + i, *cm, *checkm);
+ cm++;
+ checkm++;
+ }
+ FcCharSetIterNext (c, &ci);
+ FcCharSetIterNext (check, &checki);
+ }
+ }
+ if ((missing = FcCharSetSubtractCount (c, check)))
+ printf ("%d missing in reparsed result\n", missing);
+ if ((missing = FcCharSetSubtractCount (check, c)))
+ printf ("%d extra in reparsed result\n", missing);
+ FcCharSetDestroy (check);
+ }
+#endif
+
+ return FcTrue;
+}
+
typedef struct _FcCharLeafEnt FcCharLeafEnt;
struct _FcCharLeafEnt {
};
#define FC_CHAR_LEAF_BLOCK (4096 / sizeof (FcCharLeafEnt))
-static FcCharLeafEnt **FcCharLeafBlocks;
-static int FcCharLeafBlockCount;
+#define FC_CHAR_LEAF_HASH_SIZE 257
+
+typedef struct _FcCharSetEnt FcCharSetEnt;
+
+struct _FcCharSetEnt {
+ FcCharSetEnt *next;
+ FcChar32 hash;
+ FcCharSet set;
+};
+
+typedef struct _FcCharSetOrigEnt FcCharSetOrigEnt;
+
+struct _FcCharSetOrigEnt {
+ FcCharSetOrigEnt *next;
+ const FcCharSet *orig;
+ const FcCharSet *frozen;
+};
+
+#define FC_CHAR_SET_HASH_SIZE 67
+
+struct _FcCharSetFreezer {
+ FcCharLeafEnt *leaf_hash_table[FC_CHAR_LEAF_HASH_SIZE];
+ FcCharLeafEnt **leaf_blocks;
+ int leaf_block_count;
+ FcCharSetEnt *set_hash_table[FC_CHAR_SET_HASH_SIZE];
+ FcCharSetOrigEnt *orig_hash_table[FC_CHAR_SET_HASH_SIZE];
+ FcCharLeafEnt *current_block;
+ int leaf_remain;
+ int leaves_seen;
+ int charsets_seen;
+ int leaves_allocated;
+ int charsets_allocated;
+};
static FcCharLeafEnt *
-FcCharLeafEntCreate (void)
+FcCharLeafEntCreate (FcCharSetFreezer *freezer)
{
- static FcCharLeafEnt *block;
- static int remain;
-
- if (!remain)
+ if (!freezer->leaf_remain)
{
FcCharLeafEnt **newBlocks;
- FcCharLeafBlockCount++;
- newBlocks = realloc (FcCharLeafBlocks, FcCharLeafBlockCount * sizeof (FcCharLeafEnt *));
+ freezer->leaf_block_count++;
+ newBlocks = realloc (freezer->leaf_blocks, freezer->leaf_block_count * sizeof (FcCharLeafEnt *));
if (!newBlocks)
return 0;
- FcCharLeafBlocks = newBlocks;
- block = FcCharLeafBlocks[FcCharLeafBlockCount-1] = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
- if (!block)
+ freezer->leaf_blocks = newBlocks;
+ freezer->current_block = freezer->leaf_blocks[freezer->leaf_block_count-1] = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
+ if (!freezer->current_block)
return 0;
FcMemAlloc (FC_MEM_CHARLEAF, FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
- remain = FC_CHAR_LEAF_BLOCK;
+ freezer->leaf_remain = FC_CHAR_LEAF_BLOCK;
}
- remain--;
- return block++;
+ freezer->leaf_remain--;
+ freezer->leaves_allocated++;
+ return freezer->current_block++;
}
-#define FC_CHAR_LEAF_HASH_SIZE 257
-
static FcChar32
FcCharLeafHash (FcCharLeaf *leaf)
{
return hash;
}
-static int FcCharLeafTotal;
-static int FcCharLeafUsed;
-
-static FcCharLeafEnt *FcCharLeafHashTable[FC_CHAR_LEAF_HASH_SIZE];
-
static FcCharLeaf *
-FcCharSetFreezeLeaf (FcCharLeaf *leaf)
+FcCharSetFreezeLeaf (FcCharSetFreezer *freezer, FcCharLeaf *leaf)
{
FcChar32 hash = FcCharLeafHash (leaf);
- FcCharLeafEnt **bucket = &FcCharLeafHashTable[hash % FC_CHAR_LEAF_HASH_SIZE];
+ FcCharLeafEnt **bucket = &freezer->leaf_hash_table[hash % FC_CHAR_LEAF_HASH_SIZE];
FcCharLeafEnt *ent;
- FcCharLeafTotal++;
for (ent = *bucket; ent; ent = ent->next)
{
if (ent->hash == hash && !memcmp (&ent->leaf, leaf, sizeof (FcCharLeaf)))
return &ent->leaf;
}
- ent = FcCharLeafEntCreate();
+ ent = FcCharLeafEntCreate(freezer);
if (!ent)
return 0;
- FcCharLeafUsed++;
ent->leaf = *leaf;
ent->hash = hash;
ent->next = *bucket;
return &ent->leaf;
}
-static void
-FcCharSetThawAllLeaf (void)
-{
- int i;
-
- for (i = 0; i < FC_CHAR_LEAF_HASH_SIZE; i++)
- FcCharLeafHashTable[i] = 0;
-
- FcCharLeafTotal = 0;
- FcCharLeafUsed = 0;
-
- for (i = 0; i < FcCharLeafBlockCount; i++)
- free (FcCharLeafBlocks[i]);
-
- free (FcCharLeafBlocks);
- FcCharLeafBlocks = 0;
- FcCharLeafBlockCount = 0;
-}
-
-typedef struct _FcCharSetEnt FcCharSetEnt;
-
-struct _FcCharSetEnt {
- FcCharSetEnt *next;
- FcChar32 hash;
- FcCharSet set;
-};
-
-#define FC_CHAR_SET_HASH_SIZE 67
-
static FcChar32
FcCharSetHash (FcCharSet *fcs)
{
int i;
/* hash in leaves */
- for (i = 0; i < fcs->num * sizeof (FcCharLeaf *) / sizeof (FcChar32); i++)
- hash = ((hash << 1) | (hash >> 31)) ^ (FcChar32)(FcCharSetGetLeaf(fcs, i)->map);
+ for (i = 0; i < fcs->num; i++)
+ hash = ((hash << 1) | (hash >> 31)) ^ FcCharLeafHash (FcCharSetLeaf(fcs,i));
/* hash in numbers */
for (i = 0; i < fcs->num; i++)
- hash = ((hash << 1) | (hash >> 31)) ^ *FcCharSetGetNumbers(fcs);
+ hash = ((hash << 1) | (hash >> 31)) ^ *FcCharSetNumbers(fcs);
return hash;
}
-static int FcCharSetTotal;
-static int FcCharSetUsed;
-static int FcCharSetTotalEnts, FcCharSetUsedEnts;
-
-static FcCharSetEnt *FcCharSetHashTable[FC_CHAR_SET_HASH_SIZE];
+static FcBool
+FcCharSetFreezeOrig (FcCharSetFreezer *freezer, const FcCharSet *orig, const FcCharSet *frozen)
+{
+ FcCharSetOrigEnt **bucket = &freezer->orig_hash_table[((uintptr_t) orig) & FC_CHAR_SET_HASH_SIZE];
+ FcCharSetOrigEnt *ent;
+
+ ent = malloc (sizeof (FcCharSetOrigEnt));
+ if (!ent)
+ return FcFalse;
+ ent->orig = orig;
+ ent->frozen = frozen;
+ ent->next = *bucket;
+ *bucket = ent;
+ return FcTrue;
+}
static FcCharSet *
-FcCharSetFreezeBase (FcCharSet *fcs)
+FcCharSetFreezeBase (FcCharSetFreezer *freezer, FcCharSet *fcs, const FcCharSet *orig)
{
FcChar32 hash = FcCharSetHash (fcs);
- FcCharSetEnt **bucket = &FcCharSetHashTable[hash % FC_CHAR_SET_HASH_SIZE];
+ FcCharSetEnt **bucket = &freezer->set_hash_table[hash % FC_CHAR_SET_HASH_SIZE];
FcCharSetEnt *ent;
int size;
+ int i;
- FcCharSetTotal++;
- FcCharSetTotalEnts += fcs->num;
for (ent = *bucket; ent; ent = ent->next)
{
if (ent->hash == hash &&
ent->set.num == fcs->num &&
- !memcmp (FcCharSetGetNumbers(&ent->set),
- FcCharSetGetNumbers(fcs),
+ !memcmp (FcCharSetNumbers(&ent->set),
+ FcCharSetNumbers(fcs),
fcs->num * sizeof (FcChar16)))
{
FcBool ok = FcTrue;
int i;
for (i = 0; i < fcs->num; i++)
- if (FcCharSetGetLeaf(&ent->set, i) != FcCharSetGetLeaf(fcs, i))
+ if (FcCharSetLeaf(&ent->set, i) != FcCharSetLeaf(fcs, i))
ok = FcFalse;
if (ok)
return &ent->set;
if (!ent)
return 0;
FcMemAlloc (FC_MEM_CHARSET, size);
- FcCharSetUsed++;
- FcCharSetUsedEnts += fcs->num;
+
+ freezer->charsets_allocated++;
ent->set.ref = FC_REF_CONSTANT;
ent->set.num = fcs->num;
- ent->set.storage = fcs->storage;
- if (fcs->storage == FcStorageDynamic)
+ if (fcs->num)
{
- if (fcs->num)
- {
- ent->set.u.dyn.leaves = (FcCharLeaf **) (ent + 1);
- ent->set.u.dyn.numbers = (FcChar16 *) (ent->set.u.dyn.leaves + fcs->num);
- memcpy (ent->set.u.dyn.leaves, fcs->u.dyn.leaves, fcs->num * sizeof (FcCharLeaf *));
- memcpy (ent->set.u.dyn.numbers, fcs->u.dyn.numbers, fcs->num * sizeof (FcChar16));
- }
- else
- {
- ent->set.u.dyn.leaves = 0;
- ent->set.u.dyn.numbers = 0;
- }
+ intptr_t *ent_leaves;
+
+ ent->set.leaves_offset = sizeof (ent->set);
+ ent->set.numbers_offset = (ent->set.leaves_offset +
+ fcs->num * sizeof (intptr_t));
+
+ ent_leaves = FcCharSetLeaves (&ent->set);
+ for (i = 0; i < fcs->num; i++)
+ ent_leaves[i] = FcPtrToOffset (ent_leaves,
+ FcCharSetLeaf (fcs, i));
+ memcpy (FcCharSetNumbers (&ent->set),
+ FcCharSetNumbers (fcs),
+ fcs->num * sizeof (FcChar16));
}
else
{
- ent->set.u.stat.leafidx_offset = fcs->u.stat.leafidx_offset;
- ent->set.u.stat.numbers_offset = fcs->u.stat.numbers_offset;
+ ent->set.leaves_offset = 0;
+ ent->set.numbers_offset = 0;
}
ent->hash = hash;
ent->next = *bucket;
*bucket = ent;
+
return &ent->set;
}
-void
-FcCharSetThawAll (void)
+static const FcCharSet *
+FcCharSetFindFrozen (FcCharSetFreezer *freezer, const FcCharSet *orig)
{
- int i;
- FcCharSetEnt *ent, *next;
-
- for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
- {
- for (ent = FcCharSetHashTable[i]; ent; ent = next)
- {
- next = ent->next;
- free (ent);
- }
- FcCharSetHashTable[i] = 0;
- }
-
- FcCharSetTotal = 0;
- FcCharSetTotalEnts = 0;
- FcCharSetUsed = 0;
- FcCharSetUsedEnts = 0;
-
- FcCharSetThawAllLeaf ();
+ FcCharSetOrigEnt **bucket = &freezer->orig_hash_table[((uintptr_t) orig) & FC_CHAR_SET_HASH_SIZE];
+ FcCharSetOrigEnt *ent;
+
+ for (ent = *bucket; ent; ent = ent->next)
+ if (ent->orig == orig)
+ return ent->frozen;
+ return NULL;
}
-FcCharSet *
-FcCharSetFreeze (FcCharSet *fcs)
+const FcCharSet *
+FcCharSetFreeze (FcCharSetFreezer *freezer, const FcCharSet *fcs)
{
- FcCharSet *b;
- FcCharSet *n = 0;
- FcCharLeaf *l;
- int i;
+ FcCharSet *b;
+ const FcCharSet *n = 0;
+ FcCharLeaf *l;
+ int i;
b = FcCharSetCreate ();
if (!b)
goto bail0;
for (i = 0; i < fcs->num; i++)
{
- l = FcCharSetFreezeLeaf (FcCharSetGetLeaf(fcs, i));
+ l = FcCharSetFreezeLeaf (freezer, FcCharSetLeaf(fcs, i));
if (!l)
goto bail1;
- if (!FcCharSetInsertLeaf (b, FcCharSetGetNumbers(fcs)[i] << 8, l))
+ if (!FcCharSetInsertLeaf (b, FcCharSetNumbers(fcs)[i] << 8, l))
goto bail1;
}
- n = FcCharSetFreezeBase (b);
+ n = FcCharSetFreezeBase (freezer, b, fcs);
+ if (!FcCharSetFreezeOrig (freezer, fcs, n))
+ {
+ n = NULL;
+ goto bail1;
+ }
+ freezer->charsets_seen++;
+ freezer->leaves_seen += fcs->num;
bail1:
- if (b->storage == FcStorageDynamic)
+ if (b->num)
{
- if (b->u.dyn.leaves)
- {
- FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
- free (b->u.dyn.leaves);
- }
- if (b->u.dyn.numbers)
- {
- FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16));
- free (b->u.dyn.numbers);
- }
+ FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
+ free (FcCharSetLeaves (b));
+ }
+ if (b->num)
+ {
+ FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16));
+ free (FcCharSetNumbers (b));
}
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (b);
return n;
}
-FcCharSet *
-FcNameParseCharSet (FcChar8 *string)
+FcCharSetFreezer *
+FcCharSetFreezerCreate (void)
{
- FcCharSet *c, *n = 0;
- FcChar32 ucs4;
- FcCharLeaf *leaf;
- FcCharLeaf temp;
- FcChar32 bits;
- int i;
+ FcCharSetFreezer *freezer;
- c = FcCharSetCreate ();
- if (!c)
- goto bail0;
- while (*string)
- {
- string = FcCharSetParseValue (string, &ucs4);
- if (!string)
- goto bail1;
- bits = 0;
- for (i = 0; i < 256/32; i++)
- {
- string = FcCharSetParseValue (string, &temp.map[i]);
- if (!string)
- goto bail1;
- bits |= temp.map[i];
- }
- if (bits)
- {
- leaf = FcCharSetFreezeLeaf (&temp);
- if (!leaf)
- goto bail1;
- if (!FcCharSetInsertLeaf (c, ucs4, leaf))
- goto bail1;
- }
- }
-#ifdef CHATTY
- printf (" %8s %8s %8s %8s\n", "total", "totalmem", "new", "newmem");
- printf ("Leaves: %8d %8d %8d %8d\n",
- FcCharLeafTotal, sizeof (FcCharLeaf) * FcCharLeafTotal,
- FcCharLeafUsed, sizeof (FcCharLeaf) * FcCharLeafUsed);
- printf ("Charsets: %8d %8d %8d %8d\n",
- FcCharSetTotal, sizeof (FcCharSet) * FcCharSetTotal,
- FcCharSetUsed, sizeof (FcCharSet) * FcCharSetUsed);
- printf ("Tables: %8d %8d %8d %8d\n",
- FcCharSetTotalEnts, FcCharSetTotalEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)),
- FcCharSetUsedEnts, FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
- printf ("Total: %8s %8d %8s %8d\n",
- "",
- sizeof (FcCharLeaf) * FcCharLeafTotal +
- sizeof (FcCharSet) * FcCharSetTotal +
- FcCharSetTotalEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)),
- "",
- sizeof (FcCharLeaf) * FcCharLeafUsed +
- sizeof (FcCharSet) * FcCharSetUsed +
- FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
-#endif
- n = FcCharSetFreezeBase (c);
-bail1:
- if (c->storage == FcStorageDynamic)
- {
- if (c->u.dyn.leaves)
- {
- FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
- free (c->u.dyn.leaves);
- }
- if (c->u.dyn.numbers)
- {
- FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
- free (c->u.dyn.numbers);
- }
- FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
- }
- free (c);
-bail0:
- return n;
+ freezer = calloc (1, sizeof (FcCharSetFreezer));
+ return freezer;
}
-FcBool
-FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
+void
+FcCharSetFreezerDestroy (FcCharSetFreezer *freezer)
{
- FcCharSetIter ci;
- int i;
-#ifdef CHECK
- int len = buf->len;
-#endif
+ int i;
- for (FcCharSetIterStart (c, &ci);
- ci.leaf;
- FcCharSetIterNext (c, &ci))
+ if (FcDebug() & FC_DBG_CACHE)
{
- if (!FcCharSetUnparseValue (buf, ci.ucs4))
- return FcFalse;
- for (i = 0; i < 256/32; i++)
- if (!FcCharSetUnparseValue (buf, ci.leaf->map[i]))
- return FcFalse;
+ printf ("\ncharsets %d -> %d leaves %d -> %d\n",
+ freezer->charsets_seen, freezer->charsets_allocated,
+ freezer->leaves_seen, freezer->leaves_allocated);
}
-#ifdef CHECK
+ for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
{
- FcCharSet *check;
- FcChar32 missing;
- FcCharSetIter ci, checki;
-
- /* null terminate for parser */
- FcStrBufChar (buf, '\0');
- /* step back over null for life after test */
- buf->len--;
- check = FcNameParseCharSet (buf->buf + len);
- FcCharSetIterStart (c, &ci);
- FcCharSetIterStart (check, &checki);
- while (ci.leaf || checki.leaf)
+ FcCharSetEnt *ent, *next;
+ for (ent = freezer->set_hash_table[i]; ent; ent = next)
{
- if (ci.ucs4 < checki.ucs4)
- {
- printf ("Missing leaf node at 0x%x\n", ci.ucs4);
- FcCharSetIterNext (c, &ci);
- }
- else if (checki.ucs4 < ci.ucs4)
- {
- printf ("Extra leaf node at 0x%x\n", checki.ucs4);
- FcCharSetIterNext (check, &checki);
- }
- else
- {
- int i = 256/32;
- FcChar32 *cm = ci.leaf->map;
- FcChar32 *checkm = checki.leaf->map;
-
- for (i = 0; i < 256; i += 32)
- {
- if (*cm != *checkm)
- printf ("Mismatching sets at 0x%08x: 0x%08x != 0x%08x\n",
- ci.ucs4 + i, *cm, *checkm);
- cm++;
- checkm++;
- }
- FcCharSetIterNext (c, &ci);
- FcCharSetIterNext (check, &checki);
- }
+ next = ent->next;
+ free (ent);
}
- if ((missing = FcCharSetSubtractCount (c, check)))
- printf ("%d missing in reparsed result\n", missing);
- if ((missing = FcCharSetSubtractCount (check, c)))
- printf ("%d extra in reparsed result\n", missing);
- FcCharSetDestroy (check);
}
-#endif
-
- return FcTrue;
-}
-
-FcCharSet *
-FcCharSetPtrU (FcCharSetPtr ci)
-{
- switch (ci.storage)
+ for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
{
- case FcStorageDynamic:
- return ci.u.dyn;
- case FcStorageStatic:
- return &charsets[ci.u.stat];
- default:
- return 0;
+ FcCharSetOrigEnt *ent, *next;
+ for (ent = freezer->orig_hash_table[i]; ent; ent = next)
+ {
+ next = ent->next;
+ free (ent);
+ }
}
-}
-FcCharSetPtr
-FcCharSetPtrCreateDynamic(FcCharSet *c)
-{
- FcCharSetPtr new;
+ for (i = 0; i < freezer->leaf_block_count; i++)
+ free (freezer->leaf_blocks[i]);
- new.storage = FcStorageDynamic;
- new.u.dyn = c;
- return new;
+ free (freezer->leaf_blocks);
+ free (freezer);
}
FcBool
-FcCharSetPrepareSerialize(FcCharSet *c)
+FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
{
- /* note the redundancy */
- charset_count++;
- charset_leaf_idx_count++;
- charset_leaf_count += c->num;
- charset_numbers_count += c->num;
- return FcTrue;
-}
-
-FcCharSetPtr
-FcCharSetSerialize(FcCharSet *c)
-{
- int i;
- FcCharSetPtr newp;
- FcCharSet new;
-
- if (!charsets)
- {
- charsets = malloc(sizeof(FcCharSet) * charset_count);
- if (!charsets) goto bail;
- numbers = malloc(sizeof(FcChar16) * charset_numbers_count);
- if (!numbers) goto bail1;
- leaves = malloc(sizeof(FcCharLeaf) * charset_leaf_count);
- if (!leaves) goto bail2;
- leaf_idx = malloc(sizeof(int)*charset_leaf_idx_count);
- if (!leaf_idx) goto bail3;
- }
-
- new.ref = FC_REF_CONSTANT;
- new.storage = FcStorageStatic;
- new.u.stat.leafidx_offset = charset_leaf_idx_ptr;
- new.u.stat.numbers_offset = charset_numbers_ptr;
- new.num = c->num;
-
- newp.storage = FcStorageStatic;
- newp.u.stat = charset_ptr;
- charsets[charset_ptr++] = new;
-
- leaf_idx[charset_leaf_idx_ptr++] = charset_leaf_ptr;
- for (i = 0; i < c->num; i++)
+ intptr_t *leaves;
+ FcChar16 *numbers;
+ int i;
+
+ if (cs->ref != FC_REF_CONSTANT)
{
- memcpy (&leaves[charset_leaf_ptr++],
- c->u.dyn.leaves[i], sizeof(FcCharLeaf));
- numbers[charset_numbers_ptr++] = c->u.dyn.numbers[i];
+ if (!serialize->cs_freezer)
+ {
+ serialize->cs_freezer = FcCharSetFreezerCreate ();
+ if (!serialize->cs_freezer)
+ return FcFalse;
+ }
+ if (FcCharSetFindFrozen (serialize->cs_freezer, cs))
+ return FcTrue;
+
+ cs = FcCharSetFreeze (serialize->cs_freezer, cs);
}
-
- return newp;
-
- bail3:
- free (leaves);
- bail2:
- free (numbers);
- bail1:
- free (charsets);
- bail:
- return FcCharSetPtrCreateDynamic(0);
-}
-
-FcBool
-FcCharSetRead (int fd, FcCache metadata)
-{
- charsets = mmap(NULL,
- metadata.charsets_length * sizeof (FcCharSet),
- PROT_READ,
- MAP_SHARED, fd, metadata.charsets_offset);
- if (charsets == MAP_FAILED)
- goto bail;
- charset_count = charset_ptr = metadata.charsets_length;
-
- leaves = mmap(NULL,
- metadata.charset_num_sum * sizeof (FcCharLeaf),
- PROT_READ,
- MAP_SHARED, fd, metadata.charset_leaf_offset);
- if (leaves == MAP_FAILED)
- goto bail1;
- charset_leaf_count = charset_leaf_ptr = metadata.charset_num_sum;
-
- leaf_idx = mmap(NULL,
- metadata.charsets_length * sizeof (FcCharLeaf*),
- PROT_READ,
- MAP_SHARED, fd, metadata.charset_leafidx_offset);
- if (leaf_idx == MAP_FAILED)
- goto bail2;
- charset_leaf_idx_count = charset_leaf_idx_ptr = metadata.charsets_length;
-
- numbers = mmap(NULL,
- metadata.charset_num_sum * sizeof (FcChar16),
- PROT_READ,
- MAP_SHARED, fd, metadata.charset_numbers_offset);
- if (numbers == MAP_FAILED)
- goto bail3;
- charset_numbers_count = charset_numbers_ptr = metadata.charset_num_sum;
-
+
+ leaves = FcCharSetLeaves (cs);
+ numbers = FcCharSetNumbers (cs);
+
+ if (!FcSerializeAlloc (serialize, cs, sizeof (FcCharSet)))
+ return FcFalse;
+ if (!FcSerializeAlloc (serialize, leaves, cs->num * sizeof (intptr_t)))
+ return FcFalse;
+ if (!FcSerializeAlloc (serialize, numbers, cs->num * sizeof (FcChar16)))
+ return FcFalse;
+ for (i = 0; i < cs->num; i++)
+ if (!FcSerializeAlloc (serialize, FcCharSetLeaf(cs, i),
+ sizeof (FcCharLeaf)))
+ return FcFalse;
return FcTrue;
-
- bail3:
- munmap (leaf_idx, metadata.charsets_length * sizeof (FcCharLeaf*));
- bail2:
- munmap (leaves, metadata.charset_num_sum * sizeof (FcCharLeaf));
- bail1:
- munmap (charsets, metadata.charsets_length * sizeof (FcCharSet));
- bail:
- return FcFalse;
}
-
-FcBool
-FcCharSetWrite (int fd, FcCache *metadata)
+
+FcCharSet *
+FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
{
- metadata->charsets_length = charset_ptr;
- metadata->charsets_offset = FcCacheNextOffset(fd);
-
- if (charset_ptr > 0)
- {
- lseek (fd, metadata->charsets_offset, SEEK_SET);
- if (write (fd, charsets, charset_ptr * sizeof(FcCharSet)) == -1)
- return FcFalse;
- }
-
- metadata->charset_leaf_offset = FcCacheNextOffset(fd);
- metadata->charset_num_sum = charset_leaf_ptr;
- if (charset_leaf_ptr > 0)
- {
- lseek (fd, metadata->charset_leaf_offset, SEEK_SET);
- if (write (fd, leaves, charset_leaf_ptr * sizeof(FcCharLeaf)) == -1)
- return FcFalse;
- }
-
- metadata->charset_leafidx_offset = FcCacheNextOffset(fd);
- if (charset_leaf_idx_ptr > 0)
- {
- lseek (fd, metadata->charset_leafidx_offset, SEEK_SET);
- if (write (fd, leaf_idx, charset_leaf_idx_ptr * sizeof(FcCharLeaf*)) == -1)
- return FcFalse;
- }
-
+ FcCharSet *cs_serialized;
+ intptr_t *leaves, *leaves_serialized;
+ FcChar16 *numbers, *numbers_serialized;
+ FcCharLeaf *leaf, *leaf_serialized;
+ int i;
- metadata->charset_numbers_offset = FcCacheNextOffset(fd);
- if (charset_leaf_ptr > 0)
+ if (cs->ref != FC_REF_CONSTANT && serialize->cs_freezer)
{
- lseek (fd, metadata->charset_numbers_offset, SEEK_SET);
- if (write (fd, numbers, charset_leaf_ptr * sizeof(FcChar16)) == -1)
- return FcFalse;
+ cs = FcCharSetFindFrozen (serialize->cs_freezer, cs);
+ if (!cs)
+ return NULL;
}
+
+ cs_serialized = FcSerializePtr (serialize, cs);
+ if (!cs_serialized)
+ return NULL;
+
+ cs_serialized->ref = FC_REF_CONSTANT;
+ cs_serialized->num = cs->num;
- return FcTrue;
-}
-
-FcCharLeaf *
-FcCharSetGetLeaf(const FcCharSet *c, int i)
-{
- switch (c->storage)
+ if (cs->num)
{
- case FcStorageDynamic:
- return c->u.dyn.leaves[i];
- case FcStorageStatic:
- return &leaves[leaf_idx[c->u.stat.leafidx_offset]+i];
- default:
- return 0;
+ leaves = FcCharSetLeaves (cs);
+ leaves_serialized = FcSerializePtr (serialize, leaves);
+ if (!leaves_serialized)
+ return NULL;
+
+ cs_serialized->leaves_offset = FcPtrToOffset (cs_serialized,
+ leaves_serialized);
+
+ numbers = FcCharSetNumbers (cs);
+ numbers_serialized = FcSerializePtr (serialize, numbers);
+ if (!numbers)
+ return NULL;
+
+ cs_serialized->numbers_offset = FcPtrToOffset (cs_serialized,
+ numbers_serialized);
+
+ for (i = 0; i < cs->num; i++)
+ {
+ leaf = FcCharSetLeaf (cs, i);
+ leaf_serialized = FcSerializePtr (serialize, leaf);
+ if (!leaf_serialized)
+ return NULL;
+ *leaf_serialized = *leaf;
+ leaves_serialized[i] = FcPtrToOffset (leaves_serialized,
+ leaf_serialized);
+ numbers_serialized[i] = numbers[i];
+ }
}
-}
-
-FcChar16 *
-FcCharSetGetNumbers(const FcCharSet *c)
-{
- switch (c->storage)
+ else
{
- case FcStorageDynamic:
- return c->u.dyn.numbers;
- case FcStorageStatic:
- return &numbers[c->u.stat.numbers_offset];
- default:
- return 0;
+ cs_serialized->leaves_offset = 0;
+ cs_serialized->numbers_offset = 0;
}
+
+ return cs_serialized;
}
-
+#define __fccharset__
+#include "fcaliastail.h"
+#undef __fccharset__