2 * PROJECT: ReactOS CRT library
3 * LICENSE: LGPL - See COPYING in the top level directory
4 * FILE: lib/sdk/crt/string/wcs.c
5 * PURPOSE: wcs* CRT functions
6 * PROGRAMMERS: Wine team
7 * Ported to ReactOS by Aleksey Bragin (aleksey@reactos.org)
11 * msvcrt.dll wide-char functions
13 * Copyright 1999 Alexandre Julliard
14 * Copyright 2000 Jon Griffiths
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include <internal/wine/msvcrt.h>
37 #include "wine/unicode.h"
38 //#include "wine/debug.h"
41 //WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
51 #pragma function(_wcsset)
55 /*********************************************************************
58 wchar_t* CDECL
_wcsdup( const wchar_t* str
)
63 int size
= (strlenW(str
) + 1) * sizeof(wchar_t);
65 if (ret
) memcpy( ret
, str
, size
);
69 /*********************************************************************
70 * _wcsicoll (MSVCRT.@)
72 INT CDECL
_wcsicoll( const wchar_t* str1
, const wchar_t* str2
)
74 /* FIXME: handle collates */
75 return strcmpiW( str1
, str2
);
79 /*********************************************************************
82 wchar_t* CDECL
_wcsnset( wchar_t* str
, wchar_t c
, size_t n
)
85 while ((n
-- > 0) && *str
) *str
++ = c
;
89 /*********************************************************************
92 wchar_t* CDECL
_wcsrev( wchar_t* str
)
95 wchar_t* end
= str
+ strlenW(str
) - 1;
106 /*********************************************************************
109 wchar_t* CDECL
_wcsset( wchar_t* str
, wchar_t c
)
112 while (*str
) *str
++ = c
;
116 /******************************************************************
117 * _wcsupr_s (MSVCRT.@)
120 INT CDECL
_wcsupr_s( wchar_t* str
, size_t n
)
126 if (str
) *str
= '\0';
134 *ptr
= toupperW(*ptr
);
138 /* MSDN claims that the function should return and set errno to
139 * ERANGE, which doesn't seem to be true based on the tests. */
145 /*********************************************************************
148 double CDECL
wcstod(const wchar_t* lpszStr
, wchar_t** end
)
150 const wchar_t* str
= lpszStr
;
152 double ret
= 0, divisor
= 10.0;
154 TRACE("(%s,%p) semi-stub\n", debugstr_w(lpszStr
), end
);
157 * - Should set errno on failure
158 * - Should fail on overflow
159 * - Need to check which input formats are allowed
161 while (isspaceW(*str
))
170 while (isdigitW(*str
))
172 ret
= ret
* 10.0 + (*str
- '0');
177 while (isdigitW(*str
))
179 ret
= ret
+ (*str
- '0') / divisor
;
184 if (*str
== 'E' || *str
== 'e' || *str
== 'D' || *str
== 'd')
186 int negativeExponent
= 0;
190 negativeExponent
= 1;
193 while (isdigitW(*str
))
195 exponent
= exponent
* 10 + (*str
- '0');
200 if (negativeExponent
)
201 ret
= ret
/ pow(10.0, exponent
);
203 ret
= ret
* pow(10.0, exponent
);
211 *end
= (wchar_t*)str
;
213 TRACE("returning %g\n", ret
);
218 /*********************************************************************
221 int CDECL
wcscoll( const wchar_t* str1
, const wchar_t* str2
)
223 /* FIXME: handle collates */
224 return strcmpW( str1
, str2
);
227 /*********************************************************************
230 wchar_t* CDECL
wcspbrk( const wchar_t* str
, const wchar_t* accept
)
235 for (p
= accept
; *p
; p
++) if (*p
== *str
) return (wchar_t*)str
;
242 /*********************************************************************
245 wchar_t * CDECL
wcstok( wchar_t *str
, const wchar_t *delim
)
247 MSVCRT_thread_data
*data
= msvcrt_get_thread_data();
251 if (!(str
= data
->wcstok_next
)) return NULL
;
253 while (*str
&& strchrW( delim
, *str
)) str
++;
254 if (!*str
) return NULL
;
256 while (*str
&& !strchrW( delim
, *str
)) str
++;
257 if (*str
) *str
++ = 0;
258 data
->wcstok_next
= str
;
262 /*********************************************************************
265 INT CDECL
wctomb(char *mbchar
, wchar_t wchar
)
267 BOOL bUsedDefaultChar
;
268 char chMultiByte
[MB_LEN_MAX
];
271 /* At least one parameter needs to be given, the length of a null character cannot be queried (verified by tests under WinXP SP2) */
272 if(!mbchar
&& !wchar
)
275 /* Use WideCharToMultiByte for doing the conversion using the codepage currently set with setlocale() */
276 nBytes
= WideCharToMultiByte(MSVCRT___lc_codepage
, 0, &wchar
, 1, chMultiByte
, MB_LEN_MAX
, NULL
, &bUsedDefaultChar
);
278 /* Only copy the character if an 'mbchar' pointer was given.
280 The "C" locale is emulated with codepage 1252 here. This codepage has a default character "?", but the "C" locale doesn't have one.
281 Therefore don't copy the character in this case. */
282 if(mbchar
&& !(MSVCRT_current_lc_all
[0] == 'C' && !MSVCRT_current_lc_all
[1] && bUsedDefaultChar
))
283 memcpy(mbchar
, chMultiByte
, nBytes
);
285 /* If the default character was used, set errno to EILSEQ and return -1. */
292 /* Otherwise return the number of bytes this character occupies. */
296 size_t CDECL
wcstombs(char *mbstr
, const wchar_t *wcstr
, size_t count
)
298 BOOL bUsedDefaultChar
;
302 /* Does the caller query for output buffer size? */
307 /* If we currently use the "C" locale, the length of the input string is returned (verified by tests under WinXP SP2) */
308 if(MSVCRT_current_lc_all
[0] == 'C' && !MSVCRT_current_lc_all
[1])
309 return wcslen(wcstr
);
311 /* Otherwise check the length each character needs and build a final return value out of this */
312 count
= wcslen(wcstr
);
315 while((int)(--count
) >= 0 && *wcstr
)
317 /* Get the length of this character */
318 nResult
= wctomb(NULL
, *wcstr
++);
320 /* If this character is not convertible in the current locale, the end result will be -1 */
327 /* Return the final length */
331 /* Convert the string then */
332 bUsedDefaultChar
= FALSE
;
336 char chMultiByte
[MB_LEN_MAX
];
339 /* Are we at the terminating null character? */
342 /* Set the null character, but don't increment the pointer as the returned length never includes the terminating null character */
347 /* Convert this character into the temporary chMultiByte variable */
348 ZeroMemory(chMultiByte
, MB_LEN_MAX
);
349 nResult
= wctomb(chMultiByte
, *wcstr
++);
351 /* Check if this was an invalid character */
353 bUsedDefaultChar
= TRUE
;
355 /* If we got no character, stop the conversion process here */
359 /* Determine whether this is a double-byte or a single-byte character */
365 /* Decrease 'count' by the character length and check if the buffer can still hold the full character */
371 /* It can, so copy it and move the pointer forward */
372 memcpy(p
, chMultiByte
, uLength
);
379 /* Return the length in bytes of the copied characters (without the terminating null character) */
384 /*********************************************************************
385 * wcscpy_s (MSVCRT.@)
387 INT CDECL
wcscpy_s( wchar_t* wcDest
, size_t numElement
, const wchar_t *wcSrc
)
391 if(!wcDest
|| !numElement
)
401 size
= strlenW(wcSrc
) + 1;
403 if(size
> numElement
)
408 memcpy( wcDest
, wcSrc
, size
*sizeof(WCHAR
) );
413 /******************************************************************
414 * wcsncpy_s (MSVCRT.@)
416 INT CDECL
wcsncpy_s( wchar_t* wcDest
, size_t numElement
, const wchar_t *wcSrc
,
421 if (!wcDest
|| !numElement
)
431 size
= min(strlenW(wcSrc
), count
);
433 if (size
>= numElement
)
438 memcpy( wcDest
, wcSrc
, size
*sizeof(WCHAR
) );