]> git.wh0rd.org - fontconfig.git/blobdiff - src/fccharset.c
Include $(top_srcdir), $(top_srcdir)/src before anything else.
[fontconfig.git] / src / fccharset.c
index 8003bccc3a009fcfefd1ea970434c76a4fd10c64..e0a09612859857e4bd557d3ebff890b62f2d8c0f 100644 (file)
  * 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)
 {
@@ -40,8 +67,9 @@ 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;
 }
 
@@ -54,7 +82,6 @@ FcCharSetNew (void)
     return FcCharSetCreate ();
 }
 
-
 void
 FcCharSetDestroy (FcCharSet *fcs)
 {
@@ -63,20 +90,23 @@ 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);
@@ -91,7 +121,7 @@ FcCharSetDestroy (FcCharSet *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;
@@ -120,7 +150,7 @@ FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4)
 {
     int        pos = FcCharSetFindLeafPos (fcs, ucs4);
     if (pos >= 0)
-       return fcs->leaves[pos];
+       return FcCharSetGetLeaf(fcs, pos);
     return 0;
 }
 
@@ -136,33 +166,62 @@ FcCharSetPutLeaf (FcCharSet       *fcs,
     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;
 }
@@ -180,7 +239,7 @@ FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4)
 
     pos = FcCharSetFindLeafPos (fcs, ucs4);
     if (pos >= 0)
-       return fcs->leaves[pos];
+       return FcCharSetGetLeaf(fcs, pos);
     
     leaf = calloc (1, sizeof (FcCharLeaf));
     if (!leaf)
@@ -205,8 +264,16 @@ FcCharSetInsertLeaf (FcCharSet *fcs, FcChar32 ucs4, FcCharLeaf *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;
@@ -257,9 +324,9 @@ FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter)
            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);
@@ -277,8 +344,8 @@ FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter)
     }
     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;
     }
 }
@@ -307,6 +374,7 @@ FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
     FcCharSetDump (fcs);
 #endif
     iter->ucs4 = 0;
+    iter->pos = 0;
     FcCharSetIterSet (fcs, iter);
 }
 
@@ -560,7 +628,7 @@ FcCharSetSubtractCount (const FcCharSet *a, const FcCharSet *b)
            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++);
            }
@@ -594,15 +662,15 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
     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)
            {
@@ -633,7 +701,7 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
            while (low <= high)
            {
                int mid = (low + high) >> 1;
-               bn = b->numbers[mid];
+               bn = FcCharSetGetNumbers(b)[mid];
                if (bn == an)
                {
                    high = mid;
@@ -645,7 +713,7 @@ FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
                    high = mid - 1;
            }
            bi = high;
-           while (bi < b->num && b->numbers[bi] < an)
+           while (bi < b->num && FcCharSetGetNumbers(b)[bi] < an)
                bi++;
        }
     }
@@ -949,16 +1017,14 @@ static FcChar32
 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;
 }
 
@@ -982,12 +1048,18 @@ FcCharSetFreezeBase (FcCharSet *fcs)
     {
        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;
        }
     }
 
@@ -1003,17 +1075,26 @@ FcCharSetFreezeBase (FcCharSet *fcs)
     
     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;
@@ -1059,23 +1140,26 @@ FcCharSetFreeze (FcCharSet *fcs)
        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);
@@ -1141,17 +1225,20 @@ FcNameParseCharSet (FcChar8 *string)
 #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;
@@ -1229,3 +1316,176 @@ FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
     
     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];
+}
+