Use a binary search to find the range containing a character in

RuneRange arrays. This is much faster when there are hundreds of
ranges (as is the case in UTF-8 locales) and was inspired by a
similar change made by Apple in Darwin.
This commit is contained in:
Tim J. Robbins 2004-05-09 13:04:49 +00:00
parent b17e85fede
commit 45a11576f3
3 changed files with 34 additions and 20 deletions

View File

@ -44,21 +44,25 @@ unsigned long
___runetype(c)
__ct_rune_t c;
{
int x;
size_t lim;
_RuneRange *rr = &_CurrentRuneLocale->runetype_ext;
_RuneEntry *re = rr->ranges;
_RuneEntry *base, *re;
if (c < 0 || c == EOF)
return(0L);
for (x = 0; x < rr->nranges; ++x, ++re) {
if (c < re->min)
return(0L);
if (c <= re->max) {
/* Binary search -- see bsearch.c for explanation. */
base = rr->ranges;
for (lim = rr->nranges; lim != 0; lim >>= 1) {
re = base + (lim >> 1);
if (re->min <= c && c <= re->max) {
if (re->types)
return(re->types[c - re->min]);
else
return(re->map);
} else if (c > re->max) {
base = re + 1;
lim--;
}
}

View File

@ -44,18 +44,23 @@ __ct_rune_t
___tolower(c)
__ct_rune_t c;
{
int x;
size_t lim;
_RuneRange *rr = &_CurrentRuneLocale->maplower_ext;
_RuneEntry *re = rr->ranges;
_RuneEntry *base, *re;
if (c < 0 || c == EOF)
return(c);
for (x = 0; x < rr->nranges; ++x, ++re) {
if (c < re->min)
return(c);
if (c <= re->max)
/* Binary search -- see bsearch.c for explanation. */
base = rr->ranges;
for (lim = rr->nranges; lim != 0; lim >>= 1) {
re = base + (lim >> 1);
if (re->min <= c && c <= re->max)
return (re->map + c - re->min);
else if (c > re->max) {
base = re + 1;
lim--;
}
}
return(c);

View File

@ -44,18 +44,23 @@ __ct_rune_t
___toupper(c)
__ct_rune_t c;
{
int x;
size_t lim;
_RuneRange *rr = &_CurrentRuneLocale->mapupper_ext;
_RuneEntry *re = rr->ranges;
_RuneEntry *base, *re;
if (c < 0 || c == EOF)
return(c);
for (x = 0; x < rr->nranges; ++x, ++re) {
if (c < re->min)
return(c);
if (c <= re->max)
/* Binary search -- see bsearch.c for explanation. */
base = rr->ranges;
for (lim = rr->nranges; lim != 0; lim >>= 1) {
re = base + (lim >> 1);
if (re->min <= c && c <= re->max)
return (re->map + c - re->min);
else if (c > re->max) {
base = re + 1;
lim--;
}
}
return(c);