2 * Wine internal Unicode definitions
4 * Copyright 2000 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #ifndef __WINE_WINE_UNICODE_H
22 #define __WINE_WINE_UNICODE_H
31 #ifdef __WINE_WINE_TEST_H
32 #error This file should not be used in Wine tests
35 #ifdef __WINE_USE_MSVCRT
36 #error This file should not be used with msvcrt headers
43 #ifndef WINE_UNICODE_INLINE
44 #define WINE_UNICODE_INLINE static FORCEINLINE
47 WINE_UNICODE_INLINE WCHAR
tolowerW( WCHAR ch
)
49 return RtlDowncaseUnicodeChar( ch
);
52 WINE_UNICODE_INLINE WCHAR
toupperW( WCHAR ch
)
54 return RtlUpcaseUnicodeChar( ch
);
57 /* the character type contains the C1_* flags in the low 12 bits */
58 /* and the C2_* type in the high 4 bits */
59 WINE_UNICODE_INLINE
unsigned short get_char_typeW( WCHAR ch
)
61 extern const unsigned short wine_wctype_table
[];
62 return wine_wctype_table
[wine_wctype_table
[ch
>> 8] + (ch
& 0xff)];
65 WINE_UNICODE_INLINE
int iscntrlW( WCHAR wc
)
67 return get_char_typeW(wc
) & C1_CNTRL
;
70 WINE_UNICODE_INLINE
int ispunctW( WCHAR wc
)
72 return get_char_typeW(wc
) & C1_PUNCT
;
75 WINE_UNICODE_INLINE
int isspaceW( WCHAR wc
)
77 return get_char_typeW(wc
) & C1_SPACE
;
80 WINE_UNICODE_INLINE
int isdigitW( WCHAR wc
)
82 return get_char_typeW(wc
) & C1_DIGIT
;
85 WINE_UNICODE_INLINE
int isxdigitW( WCHAR wc
)
87 return get_char_typeW(wc
) & C1_XDIGIT
;
90 WINE_UNICODE_INLINE
int islowerW( WCHAR wc
)
92 return get_char_typeW(wc
) & C1_LOWER
;
95 WINE_UNICODE_INLINE
int isupperW( WCHAR wc
)
97 return get_char_typeW(wc
) & C1_UPPER
;
100 WINE_UNICODE_INLINE
int isalnumW( WCHAR wc
)
102 return get_char_typeW(wc
) & (C1_ALPHA
|C1_DIGIT
|C1_LOWER
|C1_UPPER
);
105 WINE_UNICODE_INLINE
int isalphaW( WCHAR wc
)
107 return get_char_typeW(wc
) & (C1_ALPHA
|C1_LOWER
|C1_UPPER
);
110 WINE_UNICODE_INLINE
int isgraphW( WCHAR wc
)
112 return get_char_typeW(wc
) & (C1_ALPHA
|C1_PUNCT
|C1_DIGIT
|C1_LOWER
|C1_UPPER
);
115 WINE_UNICODE_INLINE
int isprintW( WCHAR wc
)
117 return get_char_typeW(wc
) & (C1_ALPHA
|C1_BLANK
|C1_PUNCT
|C1_DIGIT
|C1_LOWER
|C1_UPPER
);
120 /* some useful string manipulation routines */
122 WINE_UNICODE_INLINE
unsigned int strlenW( const WCHAR
*str
)
124 const WCHAR
*s
= str
;
129 WINE_UNICODE_INLINE WCHAR
*strcpyW( WCHAR
*dst
, const WCHAR
*src
)
132 while ((*p
++ = *src
++));
136 /* strncpy doesn't do what you think, don't use it */
137 #define strncpyW(d,s,n) error do_not_use_strncpyW_use_lstrcpynW_or_memcpy_instead
139 WINE_UNICODE_INLINE
int strcmpW( const WCHAR
*str1
, const WCHAR
*str2
)
141 while (*str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
142 return *str1
- *str2
;
145 WINE_UNICODE_INLINE
int strncmpW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
147 if (n
<= 0) return 0;
148 while ((--n
> 0) && *str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
149 return *str1
- *str2
;
152 WINE_UNICODE_INLINE WCHAR
*strcatW( WCHAR
*dst
, const WCHAR
*src
)
154 strcpyW( dst
+ strlenW(dst
), src
);
158 WINE_UNICODE_INLINE WCHAR
*strchrW( const WCHAR
*str
, WCHAR ch
)
160 do { if (*str
== ch
) return (WCHAR
*)(ULONG_PTR
)str
; } while (*str
++);
164 WINE_UNICODE_INLINE WCHAR
*strrchrW( const WCHAR
*str
, WCHAR ch
)
167 do { if (*str
== ch
) ret
= (WCHAR
*)(ULONG_PTR
)str
; } while (*str
++);
171 WINE_UNICODE_INLINE WCHAR
*strpbrkW( const WCHAR
*str
, const WCHAR
*accept
)
173 for ( ; *str
; str
++) if (strchrW( accept
, *str
)) return (WCHAR
*)(ULONG_PTR
)str
;
177 WINE_UNICODE_INLINE
size_t strspnW( const WCHAR
*str
, const WCHAR
*accept
)
180 for (ptr
= str
; *ptr
; ptr
++) if (!strchrW( accept
, *ptr
)) break;
184 WINE_UNICODE_INLINE
size_t strcspnW( const WCHAR
*str
, const WCHAR
*reject
)
187 for (ptr
= str
; *ptr
; ptr
++) if (strchrW( reject
, *ptr
)) break;
191 WINE_UNICODE_INLINE WCHAR
*strlwrW( WCHAR
*str
)
194 for (ret
= str
; *str
; str
++) *str
= tolowerW(*str
);
198 WINE_UNICODE_INLINE WCHAR
*struprW( WCHAR
*str
)
201 for (ret
= str
; *str
; str
++) *str
= toupperW(*str
);
205 WINE_UNICODE_INLINE WCHAR
*memchrW( const WCHAR
*ptr
, WCHAR ch
, size_t n
)
208 for (end
= ptr
+ n
; ptr
< end
; ptr
++) if (*ptr
== ch
) return (WCHAR
*)(ULONG_PTR
)ptr
;
212 WINE_UNICODE_INLINE WCHAR
*memrchrW( const WCHAR
*ptr
, WCHAR ch
, size_t n
)
216 for (end
= ptr
+ n
; ptr
< end
; ptr
++) if (*ptr
== ch
) ret
= (WCHAR
*)(ULONG_PTR
)ptr
;
220 WINE_UNICODE_INLINE
int strcmpiW( const WCHAR
*str1
, const WCHAR
*str2
)
224 int ret
= tolowerW(*str1
) - tolowerW(*str2
);
225 if (ret
|| !*str1
) return ret
;
231 WINE_UNICODE_INLINE
int strncmpiW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
234 for ( ; n
> 0; n
--, str1
++, str2
++)
235 if ((ret
= tolowerW(*str1
) - tolowerW(*str2
)) || !*str1
) break;
239 WINE_UNICODE_INLINE
int memicmpW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
242 for ( ; n
> 0; n
--, str1
++, str2
++)
243 if ((ret
= tolowerW(*str1
) - tolowerW(*str2
))) break;
247 WINE_UNICODE_INLINE WCHAR
*strstrW( const WCHAR
*str
, const WCHAR
*sub
)
251 const WCHAR
*p1
= str
, *p2
= sub
;
252 while (*p1
&& *p2
&& *p1
== *p2
) { p1
++; p2
++; }
253 if (!*p2
) return (WCHAR
*)str
;
259 WINE_UNICODE_INLINE LONG
strtolW( LPCWSTR s
, LPWSTR
*end
, INT base
)
261 BOOL negative
= FALSE
, empty
= TRUE
;
264 if (base
< 0 || base
== 1 || base
> 36) return 0;
265 if (end
) *end
= (WCHAR
*)s
;
266 while (isspaceW(*s
)) s
++;
273 else if (*s
== '+') s
++;
275 if ((base
== 0 || base
== 16) && s
[0] == '0' && (s
[1] == 'x' || s
[1] == 'X'))
280 if (base
== 0) base
= s
[0] != '0' ? 10 : 8;
286 if ('0' <= *s
&& *s
<= '9') v
= *s
- '0';
287 else if ('A' <= *s
&& *s
<= 'Z') v
= *s
- 'A' + 10;
288 else if ('a' <= *s
&& *s
<= 'z') v
= *s
- 'a' + 10;
290 if (v
>= base
) break;
291 if (negative
) v
= -v
;
295 if (!negative
&& (ret
> MAXLONG
/ base
|| ret
* base
> MAXLONG
- v
))
297 else if (negative
&& (ret
< (LONG
)MINLONG
/ base
|| ret
* base
< (LONG
)(MINLONG
- v
)))
300 ret
= ret
* base
+ v
;
303 if (end
&& !empty
) *end
= (WCHAR
*)s
;
307 WINE_UNICODE_INLINE ULONG
strtoulW( LPCWSTR s
, LPWSTR
*end
, INT base
)
309 BOOL negative
= FALSE
, empty
= TRUE
;
312 if (base
< 0 || base
== 1 || base
> 36) return 0;
313 if (end
) *end
= (WCHAR
*)s
;
314 while (isspaceW(*s
)) s
++;
321 else if (*s
== '+') s
++;
323 if ((base
== 0 || base
== 16) && s
[0] == '0' && (s
[1] == 'x' || s
[1] == 'X'))
328 if (base
== 0) base
= s
[0] != '0' ? 10 : 8;
334 if ('0' <= *s
&& *s
<= '9') v
= *s
- '0';
335 else if ('A' <= *s
&& *s
<= 'Z') v
= *s
- 'A' + 10;
336 else if ('a' <= *s
&& *s
<= 'z') v
= *s
- 'a' + 10;
338 if (v
>= base
) break;
342 if (ret
> MAXDWORD
/ base
|| ret
* base
> MAXDWORD
- v
)
345 ret
= ret
* base
+ v
;
348 if (end
&& !empty
) *end
= (WCHAR
*)s
;
349 return negative
? -ret
: ret
;
352 WINE_UNICODE_INLINE
long int atolW( const WCHAR
*str
)
354 return strtolW( str
, (WCHAR
**)0, 10 );
357 WINE_UNICODE_INLINE
int atoiW( const WCHAR
*str
)
359 return (int)atolW( str
);
362 NTSYSAPI
int __cdecl
_vsnwprintf(WCHAR
*,size_t,const WCHAR
*,__ms_va_list
);
364 static inline int WINAPIV
snprintfW( WCHAR
*str
, size_t len
, const WCHAR
*format
, ...)
368 __ms_va_start(valist
, format
);
369 retval
= _vsnwprintf(str
, len
, format
, valist
);
374 static inline int WINAPIV
sprintfW( WCHAR
*str
, const WCHAR
*format
, ...)
378 __ms_va_start(valist
, format
);
379 retval
= _vsnwprintf(str
, MAXLONG
, format
, valist
);
384 #undef WINE_UNICODE_INLINE
390 #endif /* __WINE_WINE_UNICODE_H */