diff -ru fontconfig-2.1.pristine/fc-lang/fc-lang.c fontconfig-2.1.working/fc-lang/fc-lang.c --- fontconfig-2.1.pristine/fc-lang/fc-lang.c 2002-08-22 02:36:43.000000000 -0500 +++ fontconfig-2.1.working/fc-lang/fc-lang.c 2003-01-10 23:11:48.000000000 -0600 @@ -309,10 +309,26 @@ /* * Dump sets */ + + /* + * accumulate start indices for the fast indexing + */ + int setHashStart[26] = {},setHashEnd[26] = {}; + FcChar8 firstchar = '\0'; + printf ("static const FcLangCharSet fcLangCharSets[] = {\n"); for (i = 0; sets[i]; i++) { int j = duplicate[i]; + char c; + if(names[i][0] > firstchar) { + for(c = firstchar;c < names[i][0] && c <= 'z';c++) + setHashEnd[c - 'a'] = i - 1; + for(c = firstchar+1;c <= names[i][0] && c <= 'z';c++) + setHashStart[c - 'a'] = i; + + firstchar = names[i][0]; + } if (j < 0) j = i; printf (" { (FcChar8 *) \"%s\",\n" @@ -323,6 +339,21 @@ sets[j]->num, names[j], names[j]); } printf ("};\n\n"); + + if('a' <= firstchar <= 'z') + setHashEnd[firstchar - 'a'] = i - 1; + + /* + * Dump sets start/finish for the fastpath + */ + printf ("static const FcLangCharSetRange fcLangCharSetRages[] = {\n"); + for (i = 0; i < 26; i++) + { + printf (" { %d, %d }, /* %c */\n", + setHashStart[i],setHashEnd[i],'a'+i); + } + printf ("};\n\n"); + while (fgets (line, sizeof (line), stdin)) fputs (line, stdout); diff -ru fontconfig-2.1.pristine/fc-lang/fclang.h fontconfig-2.1.working/fc-lang/fclang.h --- fontconfig-2.1.pristine/fc-lang/fclang.h 2002-10-21 12:03:47.000000000 -0500 +++ fontconfig-2.1.working/fc-lang/fclang.h 2003-01-10 23:11:48.000000000 -0600 @@ -3996,3 +3996,32 @@ { FC_REF_CONSTANT, 1, (FcCharLeaf **) leaves_fj, (FcChar16 *) numbers_fj } }, }; +static const FcLangCharSetRange fcLangCharSetRages[] = { + { 0, 8 }, /* a */ + { 9, 21 }, /* b */ + { 22, 31 }, /* c */ + { 32, 34 }, /* d */ + { 35, 40 }, /* e */ + { 41, 48 }, /* f */ + { 49, 55 }, /* g */ + { 56, 63 }, /* h */ + { 64, 72 }, /* i */ + { 73, 73 }, /* j */ + { 74, 88 }, /* k */ + { 89, 94 }, /* l */ + { 95, 104 }, /* m */ + { 105, 110 }, /* n */ + { 111, 114 }, /* o */ + { 115, 116 }, /* p */ + { 117, 116 }, /* q */ + { 117, 119 }, /* r */ + { 120, 139 }, /* s */ + { 140, 153 }, /* t */ + { 154, 157 }, /* u */ + { 158, 161 }, /* v */ + { 162, 164 }, /* w */ + { 165, 165 }, /* x */ + { 166, 168 }, /* y */ + { 169, 174 }, /* z */ +}; + Only in fontconfig-2.1.working/src: .fclang.c.swp diff -ru fontconfig-2.1.pristine/src/fclang.c fontconfig-2.1.working/src/fclang.c --- fontconfig-2.1.pristine/src/fclang.c 2002-08-26 18:34:31.000000000 -0500 +++ fontconfig-2.1.working/src/fclang.c 2003-01-10 23:12:56.000000000 -0600 @@ -29,6 +29,11 @@ FcCharSet charset; } FcLangCharSet; +typedef struct { + int begin; + int end; +} FcLangCharSetRange; + #include "../fc-lang/fclang.h" #define NUM_LANG_CHAR_SET (sizeof (fcLangCharSets) / sizeof (fcLangCharSets[0])) @@ -228,14 +233,53 @@ { int low, high, mid; int cmp; + FcChar8 firstChar; /* first two chars, then we just let it go to a case insensitive compare */ + firstChar=FcToLower(lang[0]); + + if(firstChar < 'a') + { + low = 0; + high = fcLangCharSetRages[0].begin; + } + else if(firstChar > 'z') + { + low = fcLangCharSetRages[25].begin; + high = NUM_LANG_CHAR_SET - 1; + } + else + { + low = fcLangCharSetRages[firstChar - 'a'].begin; + high = fcLangCharSetRages[firstChar - 'a'].end; + if(low > high) /* no matches */ + return -low; /* next entry after where it would be */ + } - low = 0; - high = NUM_LANG_CHAR_SET - 1; while (low <= high) { mid = (high + low) >> 1; - cmp = FcStrCmpIgnoreCase (fcLangCharSets[mid].lang, lang); - if (cmp == 0) + if(fcLangCharSets[mid].lang[0] != firstChar) + cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang, lang); + else + { /* fast path for resolving 2-letter languages (by far the most common) after + * finding the first char (probably already true because of the hash table) */ + FcChar8 secondChar = FcToLower(lang[1]); + if (fcLangCharSets[mid].lang[1] > secondChar) // check second chars + { + high = mid - 1; + continue; + } + else if (fcLangCharSets[mid].lang[1] < secondChar) + { + low = mid + 1; + continue; + } + else if (fcLangCharSets[mid].lang[2] == '\0' && lang[2] == '\0') + return mid; + + else /* identical through the first two charcters, but at least one string didn't end there */ + cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang+2, lang+2); + } + if (cmp == 0) return mid; if (cmp < 0) low = mid + 1; @@ -407,32 +451,28 @@ FcLangSet * FcNameParseLangSet (const FcChar8 *string) { - FcChar8 lang[32]; - const FcChar8 *end, *next; + FcChar8 lang[32],c; + int i; FcLangSet *ls; ls = FcLangSetCreate (); if (!ls) goto bail0; - while (string && *string) + for(;;) { - end = (FcChar8 *) strchr ((char *) string, '|'); - if (!end) + for(i = 0; i < 31;i++) { - end = string + strlen ((char *) string); - next = end; + c = *string++; + if(c == '\0' || c == '|') + break; /* end of this code */ + lang[i] = c; } - else - next = end + 1; - if (end - string < sizeof (lang) - 1) - { - strncpy ((char *) lang, (char *) string, end - string); - lang[end-string] = '\0'; - if (!FcLangSetAdd (ls, lang)) - goto bail1; - } - string = next; + lang[i] = '\0'; + if (!FcLangSetAdd (ls, lang)) + goto bail1; + if(c == '\0') + break; } return ls; bail1: