[Fontconfig] please sort fonts.cache entries

Egmont Koblinger egmont at uhulinux.hu
Tue Mar 7 08:04:50 PST 2006


Hi,

> I'll try to do it tomorrow.

Sorry, I am a bit late due to technical issues.

I attach the patch that sorts directory entries before scanning them. I send
two versions, for 2.3.2 and for 2.3.94. The older one is easier to test
since fonts.cache-1 is more human-readable.

Scandir() would have been an easier choice but that is not really portable
according to its manpage. So I rather chose to manually store the results of
readdir() and sort them using qsort. They are stored in a "char**" called
dirlist where this array is first initialized to contain 8 "char*"s (this
number is quite arbitrary) and doubled each time this limit is exceeded.
dirlistalloc is the allocated size of this array, dirlistlen is the number
of elements already in use.

Of course I tested the patch and it seems to be okay, however that doesn't
guarantee for sure that it is perfect, so please verify it. The only bug I
see is that if a malloc fails and hence the function bails out, then the
result of some earlier malloc's may remain unfreed. I hope it's acceptable
since the whole utility will soon exit then.



thx,

Egmont
-------------- next part --------------
diff -Naur fontconfig-2.3.2.orig/src/fcdir.c fontconfig-2.3.2/src/fcdir.c
--- fontconfig-2.3.2.orig/src/fcdir.c	2005-02-10 21:20:02.000000000 +0100
+++ fontconfig-2.3.2/src/fcdir.c	2006-03-07 16:41:05.000000000 +0100
@@ -169,6 +169,16 @@
 }
 
 /*
+ * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
+ */
+
+static int
+cmpstringp(const void *p1, const void *p2)
+{
+    return strcmp(* (char **) p1, * (char **) p2);
+}
+
+/*
  * Scan 'dir', adding font files to 'set' and
  * subdirectories to 'dirs'
  */
@@ -184,9 +194,12 @@
 {
     DIR			*d;
     struct dirent	*e;
+    FcChar8		**dirlist;
+    int			dirlistlen, dirlistalloc;
     FcChar8		*file;
     FcChar8		*base;
     FcBool		ret = FcTrue;
+    int			i;
 
     if (config && !FcConfigAcceptFilename (config, dir))
 	return FcTrue;
@@ -232,14 +245,40 @@
 	    return FcTrue;
 	return FcFalse;
     }
-    while (ret && (e = readdir (d)))
+    dirlistlen = 0;
+    dirlistalloc = 8;
+    dirlist = malloc(dirlistalloc * sizeof(FcChar8 *));
+    if (!dirlist)
+       return FcFalse;
+    while ((e = readdir (d)))
     {
 	if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
 	{
-	    strcpy ((char *) base, (char *) e->d_name);
-	    ret = FcFileScanConfig (set, dirs, cache, blanks, file, force, config);
+	    if (dirlistlen == dirlistalloc)
+	    {
+		dirlistalloc *= 2;
+		dirlist = realloc(dirlist, dirlistalloc * sizeof(FcChar8 *));
+		if (!dirlist)
+		    return FcFalse;
+	    }
+	    dirlist[dirlistlen] = malloc(strlen (e->d_name) + 1);
+	    if (!dirlist[dirlistlen])
+		return FcFalse;
+	    strcpy(dirlist[dirlistlen], e->d_name);
+	    dirlistlen++;
 	}
     }
+    qsort(dirlist, dirlistlen, sizeof(FcChar8 *), cmpstringp);
+    i = 0;
+    while (ret && i < dirlistlen)
+    {
+	strcpy ((char *) base, (char *) dirlist[i]);
+	ret = FcFileScanConfig (set, dirs, cache, blanks, file, force, config);
+	i++;
+    }
+    for (i = 0; i < dirlistlen; i++)
+	free(dirlist[i]);
+    free (dirlist);
     free (file);
     closedir (d);
     /*
-------------- next part --------------
diff -Naur fontconfig-2.3.94.orig/src/fcdir.c fontconfig-2.3.94/src/fcdir.c
--- fontconfig-2.3.94.orig/src/fcdir.c	2006-02-21 16:45:51.000000000 +0100
+++ fontconfig-2.3.94/src/fcdir.c	2006-03-07 16:29:30.000000000 +0100
@@ -101,6 +101,16 @@
 }
 
 /*
+ * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
+ */
+
+static int
+cmpstringp(const void *p1, const void *p2)
+{
+    return strcmp(* (char **) p1, * (char **) p2);
+}
+
+/*
  * Scan 'dir', adding font files to 'set' and
  * subdirectories to 'dirs'
  */
@@ -116,6 +126,8 @@
 {
     DIR			*d;
     struct dirent	*e;
+    FcChar8		**dirlist;
+    int			dirlistlen, dirlistalloc;
     FcChar8		*file;
     const FcChar8	*d_can = 0;
     FcChar8		*base;
@@ -174,14 +186,40 @@
 	return FcFalse;
     }
 
-    while (ret && (e = readdir (d)))
+    dirlistlen = 0;
+    dirlistalloc = 8;
+    dirlist = malloc(dirlistalloc * sizeof(FcChar8 *));
+    if (!dirlist)
+       return FcFalse;
+    while ((e = readdir (d)))
     {
 	if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
 	{
-	    strcpy ((char *) base, (char *) e->d_name);
-	    ret = FcFileScanConfig (tmpSet, dirs, cache, blanks, file, force, config);
+	    if (dirlistlen == dirlistalloc)
+	    {
+		dirlistalloc *= 2;
+		dirlist = realloc(dirlist, dirlistalloc * sizeof(FcChar8 *));
+		if (!dirlist)
+		    return FcFalse;
+	    }
+	    dirlist[dirlistlen] = malloc(strlen (e->d_name) + 1);
+	    if (!dirlist[dirlistlen])
+		return FcFalse;
+	    strcpy(dirlist[dirlistlen], e->d_name);
+	    dirlistlen++;
 	}
     }
+    qsort(dirlist, dirlistlen, sizeof(FcChar8 *), cmpstringp);
+    i = 0;
+    while (ret && i < dirlistlen)
+    {
+	strcpy ((char *) base, (char *) dirlist[i]);
+	ret = FcFileScanConfig (tmpSet, dirs, cache, blanks, file, force, config);
+	i++;
+    }
+    for (i = 0; i < dirlistlen; i++)
+	free(dirlist[i]);
+    free (dirlist);
     free (file);
     closedir (d);
     /*


More information about the Fontconfig mailing list