Browse Source

simplify newlocale and allow failure for explicit locale names

unify the code paths for allocated and non-allocated locale objects,
always using a tmp object. this is necessary to avoid clobbering the
base locale object too soon if we allow for the possibility that
looking up an explicitly requested locale name may fail, and makes the
code simpler and cleaner anyway.

eliminate the complex and fragile logic for checking whether one of
the non-allocated locale objects can be used for the result, and
instead just memcmp against each of them.
master
Rich Felker 8 years ago
parent
commit
74e704006a
  1. 37
      src/locale/newlocale.c

37
src/locale/newlocale.c

@ -9,37 +9,28 @@ int __loc_is_allocated(locale_t loc)
locale_t __newlocale(int mask, const char *name, locale_t loc) locale_t __newlocale(int mask, const char *name, locale_t loc)
{ {
int i, j;
struct __locale_struct tmp; struct __locale_struct tmp;
const struct __locale_map *lm;
for (int i=0; i<LC_ALL; i++) {
tmp.cat[i] = (!(mask & (1<<i)) && loc) ? loc->cat[i] :
__get_locale(i, (mask & (1<<i)) ? name : "");
if (tmp.cat[i] == LOC_MAP_FAILED)
return 0;
}
/* For locales with allocated storage, modify in-place. */ /* For locales with allocated storage, modify in-place. */
if (__loc_is_allocated(loc)) { if (__loc_is_allocated(loc)) {
for (i=0; i<LC_ALL; i++) *loc = tmp;
if (mask & (1<<i))
loc->cat[i] = __get_locale(i, name);
return loc; return loc;
} }
/* Otherwise, build a temporary locale object, which will only /* Otherwise, first see if we can use one of the builtin locales.
* be instantiated in allocated storage if it does not match * This makes the common usage case for newlocale, getting a C locale
* one of the built-in static locales. This makes the common * with predictable behavior, very fast, and more importantly, fail-safe. */
* usage case for newlocale, getting a C locale with predictable if (!memcmp(&tmp, C_LOCALE, sizeof tmp)) return C_LOCALE;
* behavior, very fast, and more importantly, fail-safe. */ if (!memcmp(&tmp, UTF8_LOCALE, sizeof tmp)) return UTF8_LOCALE;
for (j=i=0; i<LC_ALL; i++) {
if (loc && !(mask & (1<<i)))
lm = loc->cat[i];
else
lm = __get_locale(i, mask & (1<<i) ? name : "");
if (lm) j++;
tmp.cat[i] = lm;
}
if (!j)
return C_LOCALE;
if (j==1 && tmp.cat[LC_CTYPE]==&__c_dot_utf8)
return UTF8_LOCALE;
/* If no builtin locale matched, attempt to allocate and copy. */
if ((loc = malloc(sizeof *loc))) *loc = tmp; if ((loc = malloc(sizeof *loc))) *loc = tmp;
return loc; return loc;

Loading…
Cancel
Save