github.com/afumu/libc@v0.0.6/musl/src/locale/newlocale.c (about)

     1  #include <stdlib.h>
     2  #include <string.h>
     3  #include <pthread.h>
     4  #include "locale_impl.h"
     5  
     6  static pthread_once_t default_locale_once;
     7  static struct __locale_struct default_locale, default_ctype_locale;
     8  
     9  static void default_locale_init(void)
    10  {
    11  	for (int i=0; i<LC_ALL; i++)
    12  		default_locale.cat[i] = __get_locale(i, "");
    13  	default_ctype_locale.cat[LC_CTYPE] = default_locale.cat[LC_CTYPE];
    14  }
    15  
    16  int __loc_is_allocated(locale_t loc)
    17  {
    18  	return loc && loc != C_LOCALE && loc != UTF8_LOCALE
    19  		&& loc != &default_locale && loc != &default_ctype_locale;
    20  }
    21  
    22  locale_t __newlocale(int mask, const char *name, locale_t loc)
    23  {
    24  	struct __locale_struct tmp;
    25  
    26  	for (int i=0; i<LC_ALL; i++) {
    27  		tmp.cat[i] = (!(mask & (1<<i)) && loc) ? loc->cat[i] :
    28  			__get_locale(i, (mask & (1<<i)) ? name : "");
    29  		if (tmp.cat[i] == LOC_MAP_FAILED)
    30  			return 0;
    31  	}
    32  
    33  	/* For locales with allocated storage, modify in-place. */
    34  	if (__loc_is_allocated(loc)) {
    35  		*loc = tmp;
    36  		return loc;
    37  	}
    38  
    39  	/* Otherwise, first see if we can use one of the builtin locales.
    40  	 * This makes the common usage case for newlocale, getting a C locale
    41  	 * with predictable behavior, very fast, and more importantly, fail-safe. */
    42  	if (!memcmp(&tmp, C_LOCALE, sizeof tmp)) return C_LOCALE;
    43  	if (!memcmp(&tmp, UTF8_LOCALE, sizeof tmp)) return UTF8_LOCALE;
    44  
    45  	/* And provide builtins for the initial default locale, and a
    46  	 * variant of the C locale honoring the default locale's encoding. */
    47  	pthread_once(&default_locale_once, default_locale_init);
    48  	if (!memcmp(&tmp, &default_locale, sizeof tmp)) return &default_locale;
    49  	if (!memcmp(&tmp, &default_ctype_locale, sizeof tmp))
    50  		return &default_ctype_locale;
    51  
    52  	/* If no builtin locale matched, attempt to allocate and copy. */
    53  	if ((loc = malloc(sizeof *loc))) *loc = tmp;
    54  
    55  	return loc;
    56  }
    57  
    58  weak_alias(__newlocale, newlocale);