* PERFORMANCE OF THIS SOFTWARE.
*/
-#include <stdlib.h>
#include "fcint.h"
+#include <stdlib.h>
/* #define CHECK */
/* #define CHATTY */
+static FcCharSet ** charsets = 0;
+static FcChar16 ** numbers = 0;
+static int charset_bank_count = 0, 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;
+
+extern const FcChar16 langBankNumbers[];
+extern const FcCharLeaf langBankLeaves[];
+extern const int langBankLeafIdx[];
+
+static FcBool
+FcCharSetEnsureBank (int bi);
+
+void
+FcLangCharSetPopulate (void)
+{
+ int bi = FcCacheBankToIndexMTF (FC_BANK_LANGS);
+ FcCharSetEnsureBank (bi);
+ charsets[bi] = 0;
+ numbers[bi] = (FcChar16 *)langBankNumbers;
+ leaves[bi] = (FcCharLeaf *)langBankLeaves;
+ leaf_idx[bi] = (int *)langBankLeafIdx;
+}
+
FcCharSet *
FcCharSetCreate (void)
{
FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
fcs->ref = 1;
fcs->num = 0;
- fcs->leaves = 0;
- fcs->numbers = 0;
+ fcs->bank = FC_BANK_DYNAMIC;
+ fcs->u.dyn.leaves = 0;
+ fcs->u.dyn.numbers = 0;
return fcs;
}
return FcCharSetCreate ();
}
-
void
FcCharSetDestroy (FcCharSet *fcs)
{
return;
if (--fcs->ref > 0)
return;
- for (i = 0; i < fcs->num; i++)
- {
- FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
- free (fcs->leaves[i]);
- }
- if (fcs->leaves)
+ if (fcs->bank == FC_BANK_DYNAMIC)
{
- FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
- free (fcs->leaves);
- }
- if (fcs->numbers)
- {
- FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
- free (fcs->numbers);
+ 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_CHARSET, sizeof (FcCharSet));
free (fcs);
static int
FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
{
- FcChar16 *numbers = fcs->numbers;
+ FcChar16 *numbers = FcCharSetGetNumbers(fcs);
FcChar16 page;
int low = 0;
int high = fcs->num - 1;
{
int pos = FcCharSetFindLeafPos (fcs, ucs4);
if (pos >= 0)
- return fcs->leaves[pos];
+ return FcCharSetGetLeaf(fcs, pos);
return 0;
}
ucs4 >>= 8;
if (ucs4 >= 0x10000)
return FcFalse;
- if (!fcs->leaves)
- leaves = malloc (sizeof (FcCharLeaf *));
- else
- leaves = realloc (fcs->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->leaves = leaves;
- if (!fcs->numbers)
- numbers = malloc (sizeof (FcChar16));
+ if (fcs->bank != FC_BANK_DYNAMIC)
+ {
+ /* convert to dynamic */
+ 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)
+ {
+ free (leaves);
+ return FcFalse;
+ }
+ FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcChar16));
+
+ for (i = 0; i < fcs->num; i++)
+ leaves[i] = FcCharSetGetLeaf(fcs, i);
+ memcpy (numbers, FcCharSetGetNumbers(fcs),
+ fcs->num * sizeof (FcChar16));
+
+ fcs->bank = FC_BANK_DYNAMIC;
+ fcs->u.dyn.leaves = leaves;
+ fcs->u.dyn.numbers = numbers;
+ }
else
- numbers = realloc (fcs->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 = numbers;
+ {
+ 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;
+ }
- memmove (fcs->leaves + pos + 1, fcs->leaves + pos,
+ memmove (fcs->u.dyn.leaves + pos + 1, fcs->u.dyn.leaves + pos,
(fcs->num - pos) * sizeof (FcCharLeaf *));
- memmove (fcs->numbers + pos + 1, fcs->numbers + pos,
+ memmove (fcs->u.dyn.numbers + pos + 1, fcs->u.dyn.numbers + pos,
(fcs->num - pos) * sizeof (FcChar16));
- fcs->numbers[pos] = (FcChar16) ucs4;
- fcs->leaves[pos] = leaf;
+ fcs->u.dyn.numbers[pos] = (FcChar16) ucs4;
+ fcs->u.dyn.leaves[pos] = leaf;
fcs->num++;
return FcTrue;
}
pos = FcCharSetFindLeafPos (fcs, ucs4);
if (pos >= 0)
- return fcs->leaves[pos];
+ return FcCharSetGetLeaf(fcs, pos);
leaf = calloc (1, sizeof (FcCharLeaf));
if (!leaf)
if (pos >= 0)
{
FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
- free (fcs->leaves[pos]);
- fcs->leaves[pos] = leaf;
+ if (fcs->bank == FC_BANK_DYNAMIC)
+ {
+ free (fcs->u.dyn.leaves[pos]);
+ fcs->u.dyn.leaves[pos] = leaf;
+ }
+ else
+ {
+ int bi = FcCacheBankToIndex(fcs->bank);
+ leaves[bi][leaf_idx[fcs->bank][fcs->u.stat.leafidx_offset]+pos] = *leaf;
+ }
return FcTrue;
}
pos = -pos - 1;
iter->leaf = 0;
return;
}
- iter->ucs4 = (FcChar32) fcs->numbers[pos] << 8;
+ iter->ucs4 = (FcChar32) FcCharSetGetNumbers(fcs)[pos] << 8;
}
- iter->leaf = fcs->leaves[pos];
+ iter->leaf = FcCharSetGetLeaf(fcs, pos);
iter->pos = pos;
#ifdef CHATTY
printf ("set %08x: %08x\n", iter->ucs4, (FcChar32) iter->leaf);
}
else
{
- iter->ucs4 = (FcChar32) fcs->numbers[pos] << 8;
- iter->leaf = fcs->leaves[pos];
+ iter->ucs4 = (FcChar32) FcCharSetGetNumbers(fcs)[pos] << 8;
+ iter->leaf = FcCharSetGetLeaf(fcs, pos);
iter->pos = pos;
}
}
FcCharSetDump (fcs);
#endif
iter->ucs4 = 0;
+ iter->pos = 0;
FcCharSetIterSet (fcs, iter);
}
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 = a->numbers[ai];
- bn = b->numbers[bi];
+ an = FcCharSetGetNumbers(a)[ai];
+ bn = FcCharSetGetNumbers(b)[bi];
/*
* Check matching pages
*/
if (an == bn)
{
- FcChar32 *am = a->leaves[ai]->map;
- FcChar32 *bm = b->leaves[bi]->map;
+ FcChar32 *am = FcCharSetGetLeaf(a, ai)->map;
+ FcChar32 *bm = FcCharSetGetLeaf(b, bi)->map;
if (am != bm)
{
while (low <= high)
{
int mid = (low + high) >> 1;
- bn = b->numbers[mid];
+ bn = FcCharSetGetNumbers(b)[mid];
if (bn == an)
{
high = mid;
high = mid - 1;
}
bi = high;
- while (bi < b->num && b->numbers[bi] < an)
+ while (bi < b->num && FcCharSetGetNumbers(b)[bi] < an)
bi++;
}
}
FcCharSetHash (FcCharSet *fcs)
{
FcChar32 hash = 0;
- FcChar32 *p;
int i;
/* hash in leaves */
- p = (FcChar32 *) fcs->leaves;
- for (i = 0; i < fcs->num * sizeof (FcCharLeaf *) / sizeof (FcChar32); i++)
- hash = ((hash << 1) | (hash >> 31)) ^ *p++;
+ for (i = 0; i < fcs->num * (int) (sizeof (FcCharLeaf *) / sizeof (FcChar32)); i++)
+ hash = ((hash << 1) | (hash >> 31)) ^ (FcChar32)(FcCharSetGetLeaf(fcs, i)->map);
/* hash in numbers */
for (i = 0; i < fcs->num; i++)
- hash = ((hash << 1) | (hash >> 31)) ^ fcs->numbers[i];
+ hash = ((hash << 1) | (hash >> 31)) ^ *FcCharSetGetNumbers(fcs);
return hash;
}
{
if (ent->hash == hash &&
ent->set.num == fcs->num &&
- !memcmp (ent->set.leaves, fcs->leaves,
- fcs->num * sizeof (FcCharLeaf *)) &&
- !memcmp (ent->set.numbers, fcs->numbers,
+ !memcmp (FcCharSetGetNumbers(&ent->set),
+ FcCharSetGetNumbers(fcs),
fcs->num * sizeof (FcChar16)))
{
- return &ent->set;
+ FcBool ok = FcTrue;
+ int i;
+
+ for (i = 0; i < fcs->num; i++)
+ if (FcCharSetGetLeaf(&ent->set, i) != FcCharSetGetLeaf(fcs, i))
+ ok = FcFalse;
+ if (ok)
+ return &ent->set;
}
}
ent->set.ref = FC_REF_CONSTANT;
ent->set.num = fcs->num;
- if (fcs->num)
+ ent->set.bank = fcs->bank;
+ if (fcs->bank == FC_BANK_DYNAMIC)
{
- ent->set.leaves = (FcCharLeaf **) (ent + 1);
- ent->set.numbers = (FcChar16 *) (ent->set.leaves + fcs->num);
- memcpy (ent->set.leaves, fcs->leaves, fcs->num * sizeof (FcCharLeaf *));
- memcpy (ent->set.numbers, fcs->numbers, fcs->num * sizeof (FcChar16));
+ 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;
+ }
}
else
{
- ent->set.leaves = 0;
- ent->set.numbers = 0;
+ ent->set.u.stat.leafidx_offset = fcs->u.stat.leafidx_offset;
+ ent->set.u.stat.numbers_offset = fcs->u.stat.numbers_offset;
}
ent->hash = hash;
goto bail0;
for (i = 0; i < fcs->num; i++)
{
- l = FcCharSetFreezeLeaf (fcs->leaves[i]);
+ l = FcCharSetFreezeLeaf (FcCharSetGetLeaf(fcs, i));
if (!l)
goto bail1;
- if (!FcCharSetInsertLeaf (b, fcs->numbers[i] << 8, l))
+ if (!FcCharSetInsertLeaf (b, FcCharSetGetNumbers(fcs)[i] << 8, l))
goto bail1;
}
n = FcCharSetFreezeBase (b);
bail1:
- if (b->leaves)
+ if (b->bank == FC_BANK_DYNAMIC)
{
- FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
- free (b->leaves);
- }
- if (b->numbers)
- {
- FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16));
- free (b->numbers);
+ 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, sizeof (FcCharSet));
free (b);
#endif
n = FcCharSetFreezeBase (c);
bail1:
- if (c->leaves)
- {
- FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
- free (c->leaves);
- }
- if (c->numbers)
+ if (c->bank == FC_BANK_DYNAMIC)
{
- FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
- free (c->numbers);
+ 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));
}
- FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (c);
bail0:
return n;
return FcTrue;
}
+
+void
+FcCharSetNewBank(void)
+{
+ charset_count = 0;
+ charset_numbers_count = 0;
+ charset_leaf_count = 0;
+ charset_leaf_idx_count = 0;
+}
+
+int
+FcCharSetNeededBytes (const FcCharSet *c)
+{
+ /* yes, there's redundancy */
+ charset_count++;
+ charset_leaf_idx_count += c->num;
+ charset_leaf_count += c->num;
+ charset_numbers_count += c->num;
+ return sizeof (FcCharSet) +
+ sizeof (int) * c->num + /* leaf_idx */
+ sizeof (FcCharLeaf) * c->num + /* leaf */
+ sizeof (FcChar16) * c->num; /* number */
+}
+
+int
+FcCharSetNeededBytesAlign (void)
+{
+ return fc_alignof (FcCharSet) + fc_alignof (int) +
+ fc_alignof (FcCharLeaf) + fc_alignof (FcChar16);
+}
+
+static FcBool
+FcCharSetEnsureBank (int bi)
+{
+ if (!charsets || charset_bank_count <= bi)
+ {
+ int new_count = charset_bank_count + 2;
+ FcCharSet ** cs;
+ FcChar16 ** n;
+ FcCharLeaf ** lvs;
+ int ** lvi;
+ int i;
+
+ cs = realloc(charsets, sizeof(FcCharSet*) * new_count);
+ if (!cs) return 0;
+ n = realloc(numbers, sizeof(FcChar16*) * new_count);
+ if (!n) return 0;
+ lvs = realloc(leaves, sizeof(FcCharLeaf*) * new_count);
+ if (!lvs) return 0;
+ lvi = realloc(leaf_idx, sizeof(int*) * new_count);
+ if (!lvi) return 0;
+
+ charsets = cs; numbers = n; leaves = lvs; leaf_idx = lvi;
+ for (i = charset_bank_count; i < new_count; i++)
+ {
+ charsets[i] = 0;
+ numbers[i] = 0;
+ leaves[i] = 0;
+ leaf_idx[i] = 0;
+ }
+ charset_bank_count = new_count;
+ }
+ return FcTrue;
+}
+
+void *
+FcCharSetDistributeBytes (FcCache * metadata, void * block_ptr)
+{
+ int bi = FcCacheBankToIndex(metadata->bank);
+ if (!FcCharSetEnsureBank(bi))
+ return 0;
+
+ block_ptr = ALIGN (block_ptr, FcCharSet);
+ charsets[bi] = (FcCharSet *)block_ptr;
+ block_ptr = (void *)((char *)block_ptr +
+ (sizeof (FcCharSet) * charset_count));
+ block_ptr = ALIGN (block_ptr, FcChar16);
+ numbers[bi] = (FcChar16 *)block_ptr;
+ block_ptr = (void *)((char *)block_ptr +
+ (sizeof(FcChar16) * charset_numbers_count));
+ block_ptr = ALIGN (block_ptr, FcCharLeaf);
+ leaves[bi] = (FcCharLeaf *)block_ptr;
+ block_ptr = (void *)((char *)block_ptr +
+ (sizeof(FcCharLeaf) * charset_leaf_count));
+ block_ptr = ALIGN (block_ptr, int);
+ leaf_idx[bi] = (int *)block_ptr;
+ block_ptr = (void *)((char *)block_ptr +
+ (sizeof(int) * charset_leaf_idx_count));
+
+ metadata->charset_count = charset_count;
+ metadata->charset_numbers_count = charset_numbers_count;
+ metadata->charset_leaf_count = charset_leaf_count;
+ metadata->charset_leaf_idx_count = charset_leaf_idx_count;
+ charset_ptr = 0; charset_leaf_ptr = 0;
+ charset_leaf_idx_ptr = 0; charset_numbers_ptr = 0;
+ return block_ptr;
+}
+
+FcCharSet *
+FcCharSetSerialize(int bank, FcCharSet *c)
+{
+ int i;
+ FcCharSet new;
+ int bi = FcCacheBankToIndex(bank), cp = charset_ptr;
+
+ new.ref = FC_REF_CONSTANT;
+ new.bank = bank;
+ new.u.stat.leafidx_offset = charset_leaf_idx_ptr;
+ new.u.stat.numbers_offset = charset_numbers_ptr;
+ new.num = c->num;
+
+ charsets[bi][charset_ptr++] = new;
+
+ for (i = 0; i < c->num; i++)
+ {
+ leaf_idx[bi][charset_leaf_idx_ptr++] = charset_leaf_ptr;
+ memcpy (&leaves[bi][charset_leaf_ptr++],
+ c->u.dyn.leaves[i], sizeof(FcCharLeaf));
+ numbers[bi][charset_numbers_ptr++] = c->u.dyn.numbers[i];
+ }
+
+ return &charsets[bi][cp];
+}
+
+void *
+FcCharSetUnserialize (FcCache *metadata, void *block_ptr)
+{
+ int bi = FcCacheBankToIndex(metadata->bank);
+ if (!FcCharSetEnsureBank(bi))
+ return 0;
+
+ block_ptr = ALIGN (block_ptr, FcCharSet);
+ charsets[bi] = (FcCharSet *)block_ptr;
+ block_ptr = (void *)((char *)block_ptr +
+ (sizeof (FcCharSet) * metadata->charset_count));
+ block_ptr = ALIGN (block_ptr, FcChar16);
+ numbers[bi] = (FcChar16 *)block_ptr;
+ block_ptr = (void *)((char *)block_ptr +
+ (sizeof(FcChar16) * metadata->charset_numbers_count));
+ block_ptr = ALIGN (block_ptr, FcCharLeaf);
+ leaves[bi] = (FcCharLeaf *)block_ptr;
+ block_ptr = (void *)((char *)block_ptr +
+ (sizeof(FcCharLeaf) * metadata->charset_leaf_count));
+ block_ptr = ALIGN (block_ptr, int);
+ leaf_idx[bi] = (int *)block_ptr;
+ block_ptr = (void *)((char *)block_ptr +
+ (sizeof(int) * metadata->charset_leaf_idx_count));
+
+ return block_ptr;
+}
+
+FcCharLeaf *
+FcCharSetGetLeaf(const FcCharSet *c, int i)
+{
+ int bi;
+ if (c->bank == FC_BANK_DYNAMIC)
+ return c->u.dyn.leaves[i];
+ bi = FcCacheBankToIndex(c->bank);
+
+ return &leaves[bi][leaf_idx[bi][c->u.stat.leafidx_offset+i]];
+}
+
+FcChar16 *
+FcCharSetGetNumbers(const FcCharSet *c)
+{
+ int bi;
+ if (c->bank == FC_BANK_DYNAMIC)
+ return c->u.dyn.numbers;
+ bi = FcCacheBankToIndex(c->bank);
+
+ return &numbers[bi][c->u.stat.numbers_offset];
+}
+