PostgreSQL Source Code: src/port/pg_localeconv_r.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include "c.h"
17
18#if !defined(WIN32)
19#include <langinfo.h>
20#include <pthread.h>
21#endif
22
23#include <limits.h>
24
25#ifdef MON_THOUSANDS_SEP
26
27
28
29
30#define TRANSLATE_FROM_LANGINFO
31#endif
32
34{
38#ifdef TRANSLATE_FROM_LANGINFO
39 nl_item item;
40#endif
41};
42
43
44#ifdef TRANSLATE_FROM_LANGINFO
45#define LCONV_M(is_string, category, name, item) \
46 { is_string, category, offsetof(struct lconv, name), item }
47#else
48#define LCONV_M(is_string, category, name, item) \
49 { is_string, category, offsetof(struct lconv, name) }
50#endif
51#define LCONV_S(c, n, i) LCONV_M(true, c, n, i)
52#define LCONV_C(c, n, i) LCONV_M(false, c, n, i)
53
54
55
56
57
58
59
60
61
62
64
67 LCONV_S(LC_NUMERIC, grouping, GROUPING),
68 LCONV_S(LC_MONETARY, int_curr_symbol, INT_CURR_SYMBOL),
69 LCONV_S(LC_MONETARY, currency_symbol, CURRENCY_SYMBOL),
70 LCONV_S(LC_MONETARY, mon_decimal_point, MON_DECIMAL_POINT),
71 LCONV_S(LC_MONETARY, mon_thousands_sep, MON_THOUSANDS_SEP),
72 LCONV_S(LC_MONETARY, mon_grouping, MON_GROUPING),
73 LCONV_S(LC_MONETARY, positive_sign, POSITIVE_SIGN),
74 LCONV_S(LC_MONETARY, negative_sign, NEGATIVE_SIGN),
75
76
77 LCONV_C(LC_MONETARY, int_frac_digits, INT_FRAC_DIGITS),
78 LCONV_C(LC_MONETARY, frac_digits, FRAC_DIGITS),
79 LCONV_C(LC_MONETARY, p_cs_precedes, P_CS_PRECEDES),
80 LCONV_C(LC_MONETARY, p_sep_by_space, P_SEP_BY_SPACE),
81 LCONV_C(LC_MONETARY, n_cs_precedes, N_CS_PRECEDES),
82 LCONV_C(LC_MONETARY, n_sep_by_space, N_SEP_BY_SPACE),
83 LCONV_C(LC_MONETARY, p_sign_posn, P_SIGN_POSN),
84 LCONV_C(LC_MONETARY, n_sign_posn, N_SIGN_POSN),
85};
86
87static inline char **
89{
90 return (char **) ((char *) lconv + table[i].offset);
91}
92
93static inline char *
95{
97}
98
99
100
101
102
103void
105{
109}
110
111#ifdef TRANSLATE_FROM_LANGINFO
112
113
114
115static int
116pg_localeconv_from_langinfo(struct lconv *dst,
119{
121 {
123
125 numeric_locale : monetary_locale;
126
128 {
130
131 string = nl_langinfo_l(table[i].item, locale);
132 if (!(string = strdup(string)))
133 {
135 errno = ENOMEM;
136 return -1;
137 }
139 }
140 else
141 {
144 }
145 }
146
147 return 0;
148}
149#else
150
151
152
153
154static int
156 struct lconv *src,
158{
160 {
162 continue;
163
165 {
167
169 if (!(string = strdup(string)))
170 {
172 errno = ENOMEM;
173 return -1;
174 }
176 }
177 else
178 {
180 }
181 }
182
183 return 0;
184}
185#endif
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230int
233 struct lconv *output)
234{
235#ifdef WIN32
236 wchar_t *save_lc_ctype = NULL;
237 wchar_t *save_lc_monetary = NULL;
238 wchar_t *save_lc_numeric = NULL;
239 int save_config_thread_locale;
240 int result = -1;
241
242
243 save_config_thread_locale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
244
245
246
247
248
249
250
251
252 save_lc_ctype = _wsetlocale(LC_CTYPE, NULL);
253 if (!save_lc_ctype || !(save_lc_ctype = wcsdup(save_lc_ctype)))
254 goto exit;
255 save_lc_monetary = _wsetlocale(LC_MONETARY, NULL);
256 if (!save_lc_monetary || !(save_lc_monetary = wcsdup(save_lc_monetary)))
257 goto exit;
258 save_lc_numeric = _wsetlocale(LC_NUMERIC, NULL);
259 if (!save_lc_numeric || !(save_lc_numeric = wcsdup(save_lc_numeric)))
260 goto exit;
261
263
264
266 goto exit;
268 if (result != 0)
269 goto exit;
270
271
273 goto exit;
275
276exit:
277
278 if (save_lc_ctype)
279 {
280 _wsetlocale(LC_CTYPE, save_lc_ctype);
281 free(save_lc_ctype);
282 }
283 if (save_lc_monetary)
284 {
285 _wsetlocale(LC_MONETARY, save_lc_monetary);
286 free(save_lc_monetary);
287 }
288 if (save_lc_numeric)
289 {
290 _wsetlocale(LC_NUMERIC, save_lc_numeric);
291 free(save_lc_numeric);
292 }
293 _configthreadlocale(save_config_thread_locale);
294
295 return result;
296
297#else
300 int result;
301
302
303
304
305
306
307
308 errno = ENOENT;
309 monetary_locale = newlocale(LC_ALL_MASK, lc_monetary, 0);
310 if (monetary_locale == 0)
311 return -1;
312 numeric_locale = newlocale(LC_ALL_MASK, lc_numeric, 0);
313 if (numeric_locale == 0)
314 {
315 freelocale(monetary_locale);
316 return -1;
317 }
318
320#if defined(TRANSLATE_FROM_LANGINFO)
321
322 result = pg_localeconv_from_langinfo(output,
323 monetary_locale,
324 numeric_locale);
325#elif defined(HAVE_LOCALECONV_L)
326
328 localeconv_l(monetary_locale),
329 LC_MONETARY);
330 if (result == 0)
331 {
332
334 localeconv_l(numeric_locale),
335 LC_NUMERIC);
336 }
337#else
338
339 {
342
344
345 save_locale = uselocale(monetary_locale);
347 localeconv(),
348 LC_MONETARY);
349 if (result == 0)
350 {
351
352 uselocale(numeric_locale);
354 localeconv(),
355 LC_NUMERIC);
356 }
358
359 uselocale(save_locale);
360 }
361#endif
362
363 freelocale(monetary_locale);
364 freelocale(numeric_locale);
365
366 return result;
367#endif
368}
static char * thousands_sep
static char * decimal_point
static char * lc_monetary
static char * lconv_char_member(struct lconv *lconv, int i)
int pg_localeconv_r(const char *lc_monetary, const char *lc_numeric, struct lconv *output)
static int pg_localeconv_copy_members(struct lconv *dst, struct lconv *src, int category)
static char ** lconv_string_member(struct lconv *lconv, int i)
static const struct lconv_member_info table[]
void pg_localeconv_free(struct lconv *lconv)
int pthread_mutex_unlock(pthread_mutex_t *mp)
int pthread_mutex_lock(pthread_mutex_t *mp)
#define PTHREAD_MUTEX_INITIALIZER