]> git.wh0rd.org - fontconfig.git/commitdiff
[charset] Grow internal FcCharset arrays exponentially
authorBehdad Esfahbod <behdad@behdad.org>
Fri, 5 Jun 2009 22:16:38 +0000 (18:16 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 24 Jun 2009 17:52:12 +0000 (13:52 -0400)
src/fccharset.c

index cba21c771f05a86a0a5f29c36759da972ca3583f..cd9b158aca6081c47a89a780f453a6b938513665 100644 (file)
@@ -68,11 +68,9 @@ FcCharSetDestroy (FcCharSet *fcs)
     }
     if (fcs->num)
     {
+        /* the numbers here are estimates */
        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));
     }
@@ -134,6 +132,8 @@ FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4)
     return 0;
 }
 
+#define FC_IS_ZERO_OR_POWER_OF_TWO(x) (!((x) & ((x)-1)))
+
 static FcBool
 FcCharSetPutLeaf (FcCharSet    *fcs, 
                  FcChar32      ucs4,
@@ -143,45 +143,52 @@ FcCharSetPutLeaf (FcCharSet       *fcs,
     intptr_t   *leaves = FcCharSetLeaves (fcs);
     FcChar16   *numbers = FcCharSetNumbers (fcs);
 
-    /* XXX We can't handle Unicode values in Plane 16 */
     ucs4 >>= 8;
+    /* XXX We can't handle Unicode values in Plane 16 */
     if (ucs4 >= 0x10000)
        return FcFalse;
 
-    if (fcs->num == fcs->alloced)
+    if (FC_IS_ZERO_OR_POWER_OF_TWO (fcs->num))
     {
-       intptr_t    *new_leaves = realloc (leaves, (fcs->num + 1) * 
-                                          sizeof (*leaves));
-       intptr_t    distance = (intptr_t) new_leaves - (intptr_t) leaves;
-       
+      if (!fcs->num)
+      {
+        unsigned int alloced = 8;
+       leaves = malloc (alloced * sizeof (*leaves));
+       numbers = malloc (alloced * sizeof (*numbers));
+       FcMemAlloc (FC_MEM_CHARSET, alloced * sizeof (*leaves));
+       FcMemAlloc (FC_MEM_CHARSET, alloced * sizeof (*numbers));
+      }
+      else
+      {
+        unsigned int alloced = fcs->num;
+       intptr_t *new_leaves, distance;
+
+       FcMemFree (FC_MEM_CHARSET, alloced * sizeof (*leaves));
+       FcMemFree (FC_MEM_CHARSET, alloced * sizeof (*numbers));
+
+       alloced *= 2;
+       new_leaves = realloc (leaves, alloced * sizeof (*leaves));
+       numbers = realloc (numbers, alloced * sizeof (*numbers));
+
+       FcMemAlloc (FC_MEM_CHARSET, alloced * sizeof (*leaves));
+       FcMemAlloc (FC_MEM_CHARSET, alloced * sizeof (*numbers));
+
+       distance = (intptr_t) new_leaves - (intptr_t) leaves;
        if (new_leaves && distance)
        {
            int i;
-
            for (i = 0; i < fcs->num; i++)
                new_leaves[i] -= distance;
        }
        leaves = new_leaves;
+      }
+
+      if (!leaves || !numbers)
+         return FcFalse;
+
+      fcs->leaves_offset = FcPtrToOffset (fcs, leaves);
+      fcs->numbers_offset = FcPtrToOffset (fcs, numbers);
     }
-    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
-       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 (leaves + pos + 1, leaves + pos, 
             (fcs->num - pos) * sizeof (*leaves));