diff options
author | Roland McGrath <roland@gnu.org> | 2002-08-31 20:08:18 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2002-08-31 20:08:18 +0000 |
commit | a0fc81e1710a9cb9b9ccfceaf2afcca2a310cb4d (patch) | |
tree | af29d38e9663142b5602064c03aef7a78ee74a2c /locale/duplocale.c | |
parent | 6f8f03151697ae59158443f271acc941bc0e8e29 (diff) | |
download | glibc-a0fc81e1710a9cb9b9ccfceaf2afcca2a310cb4d.tar.gz glibc-a0fc81e1710a9cb9b9ccfceaf2afcca2a310cb4d.tar.xz glibc-a0fc81e1710a9cb9b9ccfceaf2afcca2a310cb4d.zip |
* locale/newlocale.c (__newlocale): Don't use strdup for names.
Instead, make the single allocation of the structure larger to hold the name strings. * locale/duplocale.c (__duplocale): Don't strdup names individually. Instead, calculate size for a single allocation and copy into it. * locale/freelocale.c (__freelocale): Don't free names individually.
Diffstat (limited to 'locale/duplocale.c')
-rw-r--r-- | locale/duplocale.c | 51 |
1 files changed, 22 insertions, 29 deletions
diff --git a/locale/duplocale.c b/locale/duplocale.c index 867232e5a9..2fa29d14d6 100644 --- a/locale/duplocale.c +++ b/locale/duplocale.c @@ -35,54 +35,47 @@ __duplocale (__locale_t dataset) { __locale_t result; int cnt; + size_t names_len = 0; - /* We modify global data. */ - __libc_lock_lock (__libc_setlocale_lock); + /* Calculate the total space we need to store all the names. */ + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL && dataset->__names[cnt] != _nl_C_name) + names_len += strlen (dataset->__names[cnt]) + 1; /* Get memory. */ - result = (__locale_t) malloc (sizeof (struct __locale_struct)); - - if (result != NULL) - /* Duplicate the names in a separate loop first so we can - bail out if strdup fails and not have touched usage_counts. */ - for (cnt = 0; cnt < __LC_LAST; ++cnt) - if (cnt != LC_ALL) - { - if (dataset->__names[cnt] == _nl_C_name) - result->__names[cnt] = _nl_C_name; - else - { - result->__names[cnt] = __strdup (dataset->__names[cnt]); - if (result->__names[cnt] == NULL) - { - while (cnt-- > 0) - if (result->__names[cnt] != _nl_C_name) - free ((char *) result->__names[cnt]); - free (result); - result = NULL; - break; - } - } - } + result = malloc (sizeof (struct __locale_struct) + names_len); if (result != NULL) { + char *namep = (char *) (result + 1); + + /* We modify global data (the usage counts). */ + __libc_lock_lock (__libc_setlocale_lock); + for (cnt = 0; cnt < __LC_LAST; ++cnt) if (cnt != LC_ALL) { result->__locales[cnt] = dataset->__locales[cnt]; if (result->__locales[cnt]->usage_count < MAX_USAGE_COUNT) ++result->__locales[cnt]->usage_count; + + if (dataset->__names[cnt] == _nl_C_name) + result->__names[cnt] = _nl_C_name; + else + { + result->__names[cnt] = namep; + namep = __stpcpy (namep, dataset->__names[cnt]) + 1; + } } /* Update the special members. */ result->__ctype_b = dataset->__ctype_b; result->__ctype_tolower = dataset->__ctype_tolower; result->__ctype_toupper = dataset->__ctype_toupper; - } - /* It's done. */ - __libc_lock_unlock (__libc_setlocale_lock); + /* It's done. */ + __libc_lock_unlock (__libc_setlocale_lock); + } return result; } |