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
32/* private locale structures */
33
34/*
35 * Because some locale data is rather ahem.. large, we would like to keep
36 * reference counts on it.  We create an abstract header (locdata) structure
37 * which keeps a point to the opaque per-category data, along with a reference
38 * count to it.  To be threadsafe, we will use atomics when holding it or
39 * freeing it.  (This only occurs when locale objects are created or destroyed,
40 * so there should be no performance impact on hot code paths.  If your code
41 * uses locale_t creation/destruction on a hot code path, its broken.  But
42 * even so, the atomic and reference counting will probably *greatly* improve
43 * your life as bootstrapping locale data from files is quite expensive.
44 */
45
46#define	NLOCDATA	4
47struct locdata {
48	char		l_lname[ENCODING_LEN+1];	/* locale name */
49	void		*l_data[NLOCDATA];		/* storage area */
50	void		*l_map;				/* mapped file */
51	size_t		l_map_len;
52	struct locdata	*l_next;			/* link cached list */
53	int		l_cached;			/* nonzero if cached */
54};
55
56
57struct _locale {
58	struct locdata	*locdata[LC_ALL];
59	struct _locale	*next;
60	int		on_list;	/* on linked list */
61	char		locname[(ENCODING_LEN+1)*NLOCDATA + 1];
62
63	/*
64	 * Convenience pointers.
65	 */
66	const struct lc_ctype		*ctype;
67	const struct lc_collate		*collate;
68	const struct lc_messages	*messages;
69	const struct lc_monetary	*monetary;
70	const struct lc_numeric		*numeric;
71	const struct lc_time		*time;
72	const struct _RuneLocale	*runelocale;
73
74	/*
75	 * The loaded value is used for localeconv.  In paticular, when
76	 * when we change the value of one of the above categories, we will
77	 * also need to update the lconv structure.  The loaded bit indicates
78	 * that the lconv structure is "current" for that category.  It's
79	 * sort of an "inverse dirty" bit.
80	 */
81	int		loaded[LC_ALL];
82	struct lconv	lconv;
83};
84
85
86struct locdata *__locdata_alloc(const char *, size_t);
87void __locdata_free(struct locdata *);
88struct locdata *__locdata_get_cache(int, const char *);
89void __locdata_set_cache(int, struct locdata *);
90
91struct locdata *__lc_numeric_load(const char *name);
92struct locdata *__lc_monetary_load(const char *name);
93struct locdata *__lc_messages_load(const char *name);
94struct locdata *__lc_time_load(const char *name);
95struct locdata *__lc_ctype_load(const char *name);
96struct locdata *__lc_collate_load(const char *name);
97
98extern struct locdata	__posix_numeric_locdata;
99extern struct locdata	__posix_monetary_locdata;
100extern struct locdata	__posix_messages_locdata;
101extern struct locdata	__posix_time_locdata;
102extern struct locdata	__posix_ctype_locdata;
103extern struct locdata	__posix_collate_locdata;
104extern locale_t ___global_locale;
105
106#endif	/* _LOCALEIMPL_H_ */
107