1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2014 Garrett D'Amore <garrett@damore.org> 14 */ 15 16 /* 17 * This file implements the 2008 newlocale and friends handling. It is 18 * private to libc. 19 */ 20 #ifndef _LOCALEIMPL_H_ 21 #define _LOCALEIMPL_H_ 22 23 #ifndef _LCONV_C99 24 #define _LCONV_C99 /* so we get all the extensions */ 25 #endif 26 27 #include <sys/types.h> 28 #include <locale.h> 29 #include <xlocale.h> 30 #include "setlocale.h" 31 #include "runetype.h" 32 33 /* private locale structures */ 34 35 /* 36 * Because some locale data is rather ahem.. large, we would like to keep 37 * reference counts on it. We create an abstract header (locdata) structure 38 * which keeps a point to the opaque per-category data, along with a reference 39 * count to it. To be threadsafe, we will use atomics when holding it or 40 * freeing it. (This only occurs when locale objects are created or destroyed, 41 * so there should be no performance impact on hot code paths. If your code 42 * uses locale_t creation/destruction on a hot code path, its broken. But 43 * even so, the atomic and reference counting will probably *greatly* improve 44 * your life as bootstrapping locale data from files is quite expensive. 45 */ 46 47 #define NLOCDATA 4 48 struct locdata { 49 char l_lname[ENCODING_LEN+1]; /* locale name */ 50 void *l_data[NLOCDATA]; /* storage area */ 51 void *l_map; /* mapped file */ 52 size_t l_map_len; 53 struct locdata *l_next; /* link cached list */ 54 int l_cached; /* nonzero if cached */ 55 }; 56 57 58 struct locale { 59 struct locdata *locdata[LC_ALL]; 60 struct locale *next; 61 int on_list; /* on linked list */ 62 char locname[(ENCODING_LEN+1)*NLOCDATA + 1]; 63 64 /* 65 * Convenience pointers. 66 */ 67 const struct lc_ctype *ctype; 68 const struct lc_collate *collate; 69 const struct lc_messages *messages; 70 const struct lc_monetary *monetary; 71 const struct lc_numeric *numeric; 72 const struct lc_time *time; 73 const _RuneLocale *runelocale; 74 75 /* 76 * The loaded value is used for localeconv. In paticular, when 77 * when we change the value of one of the above categories, we will 78 * also need to update the lconv structure. The loaded bit indicates 79 * that the lconv structure is "current" for that category. It's 80 * sort of an "inverse dirty" bit. 81 */ 82 int loaded[LC_ALL]; 83 struct lconv lconv; 84 }; 85 86 87 struct locdata *__locdata_alloc(const char *, size_t); 88 void __locdata_free(struct locdata *); 89 struct locdata *__locdata_get_cache(int, const char *); 90 void __locdata_set_cache(int, struct locdata *); 91 92 struct locdata *__lc_numeric_load(const char *name); 93 struct locdata *__lc_monetary_load(const char *name); 94 struct locdata *__lc_messages_load(const char *name); 95 struct locdata *__lc_time_load(const char *name); 96 struct locdata *__lc_ctype_load(const char *name); 97 struct locdata *__lc_collate_load(const char *name); 98 99 extern struct locdata __posix_numeric_locdata; 100 extern struct locdata __posix_monetary_locdata; 101 extern struct locdata __posix_messages_locdata; 102 extern struct locdata __posix_time_locdata; 103 extern struct locdata __posix_ctype_locdata; 104 extern struct locdata __posix_collate_locdata; 105 extern locale_t ___global_locale; 106 107 #endif /* _LOCALEIMPL_H_ */