2 * Copyright (c) 2007 2008
5 * This material is provided "as is", with absolutely no warranty expressed
6 * or implied. Any use is at your own risk.
8 * Permission to use or copy this software for any purpose is hereby granted
9 * without fee, provided the above notices are retained on all copies.
10 * Permission to modify the code and to distribute modified code is granted,
11 * provided the above notices are retained, and a notice that the code was
12 * modified is included with the above copyright notice.
16 #if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
17 # define _STLP_WCSNCPY(D, DS, S, C) wcsncpy_s(D, DS, S, C)
19 # define _STLP_WCSNCPY(D, DS, S, C) wcsncpy(D, S, C)
22 static const wchar_t* __wtrue_name
= L
"true";
23 static const wchar_t* __wfalse_name
= L
"false";
25 typedef struct _Locale_codecvt
{
28 unsigned char cleads
[256 / CHAR_BIT
];
29 unsigned char max_char_size
;
35 _Locale_mask_t
_WLocale_ctype(_Locale_ctype_t
* ltype
, wint_t c
,
36 _Locale_mask_t which_bits
) {
39 buf
[0] = c
; buf
[1] = 0;
40 GetStringTypeW(CT_CTYPE1
, buf
, -1, out
);
41 _STLP_MARK_PARAMETER_AS_UNUSED(ltype
)
42 return (_Locale_mask_t
)(MapCtypeMask(out
[0]) & which_bits
);
45 wint_t _WLocale_tolower(_Locale_ctype_t
* ltype
, wint_t c
) {
49 LCMapStringW(ltype
->lc
.id
, LCMAP_LOWERCASE
, &in_c
, 1, &res
, 1);
53 wint_t _WLocale_toupper(_Locale_ctype_t
* ltype
, wint_t c
) {
57 LCMapStringW(ltype
->lc
.id
, LCMAP_UPPERCASE
, &in_c
, 1, &res
, 1);
61 _Locale_codecvt_t
* _Locale_codecvt_create(const char * name
, _Locale_lcid_t
* lc_hint
, int *__err_code
) {
62 char cp_name
[MAX_CP_LEN
+ 1];
67 _Locale_codecvt_t
*lcodecvt
= (_Locale_codecvt_t
*)malloc(sizeof(_Locale_codecvt_t
));
69 if (!lcodecvt
) { *__err_code
= _STLP_LOC_NO_MEMORY
; return lcodecvt
; }
70 memset(lcodecvt
, 0, sizeof(_Locale_codecvt_t
));
72 if (__GetLCIDFromName(name
, &lcodecvt
->lc
.id
, cp_name
, lc_hint
) == -1)
73 { free(lcodecvt
); *__err_code
= _STLP_LOC_UNKNOWN_NAME
; return NULL
; }
75 lcodecvt
->cp
= atoi(cp_name
);
76 if (!GetCPInfo(lcodecvt
->cp
, &CPInfo
)) { free(lcodecvt
); return NULL
; }
78 if (lcodecvt
->cp
!= CP_UTF7
&& lcodecvt
->cp
!= CP_UTF8
) {
79 lcodecvt
->mbtowc_flags
= MB_PRECOMPOSED
;
80 lcodecvt
->wctomb_flags
= WC_COMPOSITECHECK
| WC_SEPCHARS
;
82 lcodecvt
->max_char_size
= CPInfo
.MaxCharSize
;
84 if (CPInfo
.MaxCharSize
> 1) {
85 for (ptr
= (unsigned char*)CPInfo
.LeadByte
; *ptr
&& *(ptr
+ 1); ptr
+= 2)
86 for (i
= *ptr
; i
<= *(ptr
+ 1); ++i
) lcodecvt
->cleads
[i
/ CHAR_BIT
] |= (0x01 << i
% CHAR_BIT
);
92 char const* _Locale_codecvt_name(const _Locale_codecvt_t
* lcodecvt
, char* buf
) {
93 char cp_buf
[MAX_CP_LEN
+ 1];
94 my_ltoa(lcodecvt
->cp
, cp_buf
);
95 return __GetLocaleName(lcodecvt
->lc
.id
, cp_buf
, buf
);
98 void _Locale_codecvt_destroy(_Locale_codecvt_t
* lcodecvt
) {
99 if (!lcodecvt
) return;
104 int _WLocale_mb_cur_max (_Locale_codecvt_t
* lcodecvt
)
105 { return lcodecvt
->max_char_size
; }
107 int _WLocale_mb_cur_min (_Locale_codecvt_t
*lcodecvt
) {
108 _STLP_MARK_PARAMETER_AS_UNUSED(lcodecvt
)
112 int _WLocale_is_stateless (_Locale_codecvt_t
* lcodecvt
)
113 { return (lcodecvt
->max_char_size
== 1) ? 1 : 0; }
115 static int __isleadbyte(int i
, unsigned char *ctable
) {
116 unsigned char c
= (unsigned char)i
;
117 return (ctable
[c
/ CHAR_BIT
] & (0x01 << c
% CHAR_BIT
));
120 static int __mbtowc(_Locale_codecvt_t
*l
, wchar_t *dst
, const char *from
, unsigned int count
) {
123 if (l
->cp
== CP_UTF7
|| l
->cp
== CP_UTF8
) {
124 result
= MultiByteToWideChar(l
->cp
, l
->mbtowc_flags
, from
, count
, dst
, 1);
126 switch (GetLastError()) {
127 case ERROR_NO_UNICODE_TRANSLATION
:
135 if (count
== 1 && __isleadbyte(*from
, l
->cleads
)) return (size_t)-2;
136 result
= MultiByteToWideChar(l
->cp
, l
->mbtowc_flags
, from
, count
, dst
, 1);
137 if (result
== 0) return -1;
143 size_t _WLocale_mbtowc(_Locale_codecvt_t
*lcodecvt
, wchar_t *to
,
144 const char *from
, size_t n
, mbstate_t *shift_state
) {
146 _STLP_MARK_PARAMETER_AS_UNUSED(shift_state
)
147 if (lcodecvt
->max_char_size
== 1) { /* Single byte encoding. */
148 result
= MultiByteToWideChar(lcodecvt
->cp
, lcodecvt
->mbtowc_flags
, from
, 1, to
, 1);
149 if (result
== 0) return (size_t)-1;
152 else { /* Multi byte encoding. */
154 unsigned int count
= 1;
156 retval
= __mbtowc(lcodecvt
, to
, from
, count
);
158 { if (++count
> ((unsigned int)lcodecvt
->max_char_size
)) return (size_t)-1; }
159 else if (retval
== -1)
160 { return (size_t)-1; }
168 size_t _WLocale_wctomb(_Locale_codecvt_t
*lcodecvt
, char *to
, size_t n
,
169 const wchar_t c
, mbstate_t *shift_state
) {
170 int size
= WideCharToMultiByte(lcodecvt
->cp
, lcodecvt
->wctomb_flags
, &c
, 1, NULL
, 0, NULL
, NULL
);
172 if (!size
) return (size_t)-1;
173 if ((size_t)size
> n
) return (size_t)-2;
176 /* Limiting the output buf size to INT_MAX seems like reasonable to transform a single wchar_t. */
179 WideCharToMultiByte(lcodecvt
->cp
, lcodecvt
->wctomb_flags
, &c
, 1, to
, (int)n
, NULL
, NULL
);
181 _STLP_MARK_PARAMETER_AS_UNUSED(shift_state
)
185 size_t _WLocale_unshift(_Locale_codecvt_t
*lcodecvt
, mbstate_t *st
,
186 char *buf
, size_t n
, char **next
) {
187 /* _WLocale_wctomb do not even touch to st, there is nothing to unshift in this localization implementation. */
188 _STLP_MARK_PARAMETER_AS_UNUSED(lcodecvt
)
189 _STLP_MARK_PARAMETER_AS_UNUSED(st
)
190 _STLP_MARK_PARAMETER_AS_UNUSED(&n
)
196 /* This function takes care of the potential size_t DWORD different size. */
197 static int _WLocale_strcmp_aux(_Locale_collate_t
* lcol
,
198 const wchar_t* s1
, size_t n1
,
199 const wchar_t* s2
, size_t n2
) {
200 int result
= CSTR_EQUAL
;
201 while (n1
> 0 || n2
> 0) {
202 DWORD size1
= trim_size_t_to_DWORD(n1
);
203 DWORD size2
= trim_size_t_to_DWORD(n2
);
204 result
= CompareStringW(lcol
->lc
.id
, 0, s1
, size1
, s2
, size2
);
205 if (result
!= CSTR_EQUAL
)
213 int _WLocale_strcmp(_Locale_collate_t
* lcol
,
214 const wchar_t* s1
, size_t n1
,
215 const wchar_t* s2
, size_t n2
) {
217 result
= _WLocale_strcmp_aux(lcol
, s1
, n1
, s2
, n2
);
218 return (result
== CSTR_EQUAL
) ? 0 : (result
== CSTR_LESS_THAN
) ? -1 : 1;
221 size_t _WLocale_strxfrm(_Locale_collate_t
* lcol
,
222 wchar_t* dst
, size_t dst_size
,
223 const wchar_t* src
, size_t src_size
) {
226 /* see _Locale_strxfrm: */
227 if (src_size
> INT_MAX
) {
229 _STLP_WCSNCPY(dst
, dst_size
, src
, src_size
);
233 if (dst_size
> INT_MAX
) {
236 result
= LCMapStringW(lcol
->lc
.id
, LCMAP_SORTKEY
, src
, (int)src_size
, dst
, (int)dst_size
);
237 if (result
!= 0 && dst
!= 0) {
238 for (i
= result
- 1; i
>= 0; --i
) {
239 dst
[i
] = ((unsigned char*)dst
)[i
];
242 return result
!= 0 ? result
- 1 : 0;
246 wchar_t _WLocale_decimal_point(_Locale_numeric_t
* lnum
) {
248 GetLocaleInfoW(lnum
->lc
.id
, LOCALE_SDECIMAL
, buf
, 4);
252 wchar_t _WLocale_thousands_sep(_Locale_numeric_t
* lnum
) {
254 GetLocaleInfoW(lnum
->lc
.id
, LOCALE_STHOUSAND
, buf
, 4);
258 const wchar_t * _WLocale_true(_Locale_numeric_t
* lnum
, wchar_t* buf
, size_t bufSize
) {
259 _STLP_MARK_PARAMETER_AS_UNUSED(lnum
)
260 _STLP_MARK_PARAMETER_AS_UNUSED(buf
)
261 _STLP_MARK_PARAMETER_AS_UNUSED(&bufSize
)
265 const wchar_t * _WLocale_false(_Locale_numeric_t
* lnum
, wchar_t* buf
, size_t bufSize
) {
266 _STLP_MARK_PARAMETER_AS_UNUSED(lnum
)
267 _STLP_MARK_PARAMETER_AS_UNUSED(buf
)
268 _STLP_MARK_PARAMETER_AS_UNUSED(&bufSize
)
269 return __wfalse_name
;
273 const wchar_t* _WLocale_int_curr_symbol(_Locale_monetary_t
* lmon
, wchar_t* buf
, size_t bufSize
)
274 { GetLocaleInfoW(lmon
->lc
.id
, LOCALE_SINTLSYMBOL
, buf
, (int)bufSize
); return buf
; }
276 const wchar_t* _WLocale_currency_symbol(_Locale_monetary_t
* lmon
, wchar_t* buf
, size_t bufSize
)
277 { GetLocaleInfoW(lmon
->lc
.id
, LOCALE_SCURRENCY
, buf
, (int)bufSize
); return buf
; }
279 wchar_t _WLocale_mon_decimal_point(_Locale_monetary_t
* lmon
)
280 { return lmon
->decimal_point
[0]; }
282 wchar_t _WLocale_mon_thousands_sep(_Locale_monetary_t
* lmon
)
283 { return lmon
->thousands_sep
[0]; }
285 const wchar_t* _WLocale_positive_sign(_Locale_monetary_t
* lmon
, wchar_t* buf
, size_t bufSize
)
286 { GetLocaleInfoW(lmon
->lc
.id
, LOCALE_SPOSITIVESIGN
, buf
, (int)bufSize
); return buf
; }
288 const wchar_t* _WLocale_negative_sign(_Locale_monetary_t
* lmon
, wchar_t* buf
, size_t bufSize
)
289 { GetLocaleInfoW(lmon
->lc
.id
, LOCALE_SNEGATIVESIGN
, buf
, (int)bufSize
); return buf
; }
292 const wchar_t * _WLocale_full_monthname(_Locale_time_t
* ltime
, int month
,
293 wchar_t* buf
, size_t bufSize
)
294 { GetLocaleInfoW(ltime
->lc
.id
, LOCALE_SMONTHNAME1
+ month
, buf
, (int)bufSize
); return buf
; }
296 const wchar_t * _WLocale_abbrev_monthname(_Locale_time_t
* ltime
, int month
,
297 wchar_t* buf
, size_t bufSize
)
298 { GetLocaleInfoW(ltime
->lc
.id
, LOCALE_SABBREVMONTHNAME1
+ month
, buf
, (int)bufSize
); return buf
; }
300 const wchar_t * _WLocale_full_dayofweek(_Locale_time_t
* ltime
, int day
,
301 wchar_t* buf
, size_t bufSize
)
302 { GetLocaleInfoW(ltime
->lc
.id
, LOCALE_SDAYNAME1
+ day
, buf
, (int)bufSize
); return buf
; }
304 const wchar_t * _WLocale_abbrev_dayofweek(_Locale_time_t
* ltime
, int day
,
305 wchar_t* buf
, size_t bufSize
)
306 { GetLocaleInfoW(ltime
->lc
.id
, LOCALE_SABBREVDAYNAME1
+ day
, buf
, (int)bufSize
); return buf
; }
308 const wchar_t* _WLocale_am_str(_Locale_time_t
* ltime
,
309 wchar_t* buf
, size_t bufSize
)
310 { GetLocaleInfoW(ltime
->lc
.id
, LOCALE_S1159
, buf
, (int)bufSize
); return buf
; }
312 const wchar_t* _WLocale_pm_str(_Locale_time_t
* ltime
,
313 wchar_t* buf
, size_t bufSize
)
314 { GetLocaleInfoW(ltime
->lc
.id
, LOCALE_S2359
, buf
, (int)bufSize
); return buf
; }