1/*
2 * Copyright (c) 2005, 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#ifndef _XLOCALE_PRIVATE_H_
25#define _XLOCALE_PRIVATE_H_
26
27#include <sys/cdefs.h>
28#define __DARWIN_XLOCALE_PRIVATE
29#include <xlocale.h>
30#undef __DARWIN_XLOCALE_PRIVATE
31#include <stdlib.h>
32#include <locale.h>
33#include <libkern/OSAtomic.h>
34#include <pthread.h>
35#include <pthread_spinlock.h>
36#include <limits.h>
37#include "setlocale.h"
38#include "collate.h"
39#include "runetype.h"
40#include "lmessages.h"
41#include "lmonetary.h"
42#include "lnumeric.h"
43#include "timelocal.h"
44
45#undef MB_CUR_MAX
46#define MB_CUR_MAX	(__current_locale()->__lc_ctype->__mb_cur_max)
47#undef MB_CUR_MAX_L
48#define MB_CUR_MAX_L(x)	((x)->__lc_ctype->__mb_cur_max)
49
50typedef void (*__free_extra_t)(void *);
51
52#define XPERMANENT	((__free_extra_t)-1)
53#define XMAGIC		0x786c6f63616c6530LL	/* 'xlocale0' */
54
55#define	__STRUCT_COMMON	\
56	int32_t __refcount; \
57	__free_extra_t __free_extra;
58
59struct __xlocale_st_collate {
60	__STRUCT_COMMON
61	char __encoding[ENCODING_LEN + 1];
62	struct __collate_st_info __info;
63	struct __collate_st_subst *__substitute_table[COLL_WEIGHTS_MAX];
64	struct __collate_st_chain_pri *__chain_pri_table;
65	struct __collate_st_large_char_pri *__large_char_pri_table;
66	struct __collate_st_char_pri __char_pri_table[UCHAR_MAX + 1];
67};
68struct __xlocale_st_runelocale {
69	__STRUCT_COMMON
70	char __ctype_encoding[ENCODING_LEN + 1];
71	int __mb_cur_max;
72	int __mb_sb_limit;
73	size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict,
74	    size_t, __darwin_mbstate_t * __restrict, struct _xlocale *);
75	int (*__mbsinit)(const __darwin_mbstate_t *, struct _xlocale *);
76	size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
77	    size_t, size_t, __darwin_mbstate_t * __restrict, struct _xlocale *);
78	size_t (*__wcrtomb)(char * __restrict, wchar_t,
79	    __darwin_mbstate_t * __restrict, struct _xlocale *);
80	size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
81	    size_t, size_t, __darwin_mbstate_t * __restrict, struct _xlocale *);
82	int __datasize;
83	_RuneLocale _CurrentRuneLocale;
84};
85struct __xlocale_st_ldpart {
86	__STRUCT_COMMON
87	char *_locale_buf;
88};
89/*
90 * the next four structures must have the first three fields of the same
91 * as the _xlocale_st_ldpart structure above.
92 */
93struct __xlocale_st_messages {
94	__STRUCT_COMMON
95	char *_messages_locale_buf;
96	struct lc_messages_T _messages_locale;
97};
98struct __xlocale_st_monetary {
99	__STRUCT_COMMON
100	char *_monetary_locale_buf;
101	struct lc_monetary_T _monetary_locale;
102};
103struct __xlocale_st_numeric {
104	__STRUCT_COMMON
105	char *_numeric_locale_buf;
106	struct lc_numeric_T _numeric_locale;
107};
108struct __xlocale_st_time {
109	__STRUCT_COMMON
110	char *_time_locale_buf;
111	struct lc_time_T _time_locale;
112};
113
114/* the extended locale structure */
115    /* values for __numeric_fp_cvt */
116#define	LC_NUMERIC_FP_UNINITIALIZED	0
117#define	LC_NUMERIC_FP_SAME_LOCALE	1
118#define	LC_NUMERIC_FP_USE_LOCALE	2
119
120struct _xlocale {
121/* The item(s) before __magic are not copied when duplicating locale_t's */
122	__STRUCT_COMMON	/* only used for locale_t's in __lc_numeric_loc */
123	/* 10 independent mbstate_t buffers! */
124	__darwin_mbstate_t __mbs_mblen;
125	__darwin_mbstate_t __mbs_mbrlen;
126	__darwin_mbstate_t __mbs_mbrtowc;
127	__darwin_mbstate_t __mbs_mbsnrtowcs;
128	__darwin_mbstate_t __mbs_mbsrtowcs;
129	__darwin_mbstate_t __mbs_mbtowc;
130	__darwin_mbstate_t __mbs_wcrtomb;
131	__darwin_mbstate_t __mbs_wcsnrtombs;
132	__darwin_mbstate_t __mbs_wcsrtombs;
133	__darwin_mbstate_t __mbs_wctomb;
134	pthread_lock_t __lock;
135/* magic (Here up to the end is copied when duplicating locale_t's) */
136	int64_t __magic;
137/* flags */
138	unsigned char __collate_load_error;
139	unsigned char __collate_substitute_nontrivial;
140	unsigned char _messages_using_locale;
141	unsigned char _monetary_using_locale;
142	unsigned char _numeric_using_locale;
143	unsigned char _time_using_locale;
144	unsigned char __mlocale_changed;
145	unsigned char __nlocale_changed;
146	unsigned char __numeric_fp_cvt;
147/* collate */
148	struct __xlocale_st_collate *__lc_collate;
149/* ctype */
150	struct __xlocale_st_runelocale *__lc_ctype;
151/* messages */
152	struct __xlocale_st_messages *__lc_messages;
153/* monetary */
154	struct __xlocale_st_monetary *__lc_monetary;
155/* numeric */
156	struct __xlocale_st_numeric *__lc_numeric;
157	struct _xlocale *__lc_numeric_loc;
158/* time */
159	struct __xlocale_st_time *__lc_time;
160/* localeconv */
161	struct lconv __lc_localeconv;
162};
163
164#define DEFAULT_CURRENT_LOCALE(x)	\
165				if ((x) == NULL) { \
166					(x) = __current_locale(); \
167				} else if ((x) == LC_GLOBAL_LOCALE) { \
168					(x) = &__global_locale; \
169				}
170
171#define NORMALIZE_LOCALE(x)	if ((x) == NULL) { \
172					(x) = _c_locale; \
173				} else if ((x) == LC_GLOBAL_LOCALE) { \
174					(x) = &__global_locale; \
175				}
176
177#define XL_LOCK(x)	LOCK((x)->__lock);
178#define	XL_RELEASE(x)	if ((x) && (x)->__free_extra != XPERMANENT && OSAtomicDecrement32Barrier(&(x)->__refcount) == 0) { \
179				if ((x)->__free_extra) \
180					(*(x)->__free_extra)((x)); \
181				free((x)); \
182			}
183#define	XL_RETAIN(x)	if ((x) && (x)->__free_extra != XPERMANENT) { OSAtomicIncrement32Barrier(&(x)->__refcount); }
184#define XL_UNLOCK(x)	UNLOCK((x)->__lock);
185
186__private_extern__ struct __xlocale_st_runelocale _DefaultRuneXLocale;
187__private_extern__ struct _xlocale	__global_locale;
188__private_extern__ pthread_key_t	__locale_key;
189
190__BEGIN_DECLS
191
192void	__ldpart_free_extra(struct __xlocale_st_ldpart *);
193locale_t __numeric_ctype(locale_t);
194void	__xlocale_init(void);
195
196static inline __attribute__((always_inline)) locale_t
197__current_locale(void)
198{
199	locale_t __locale = (locale_t)pthread_getspecific(__locale_key);
200	return (__locale ? __locale : &__global_locale);
201}
202
203static inline __attribute__((always_inline)) locale_t
204__locale_ptr(locale_t __loc)
205{
206	NORMALIZE_LOCALE(__loc);
207	return __loc;
208}
209
210__END_DECLS
211
212#endif /* _XLOCALE_PRIVATE_H_ */
213