2 * MSVCRT string functions
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define _ISOC99_SOURCE
26 #include "wine/port.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
37 /*********************************************************************
41 char* CDECL
_strdup(const char* str
)
45 char * ret
= MSVCRT_malloc(strlen(str
)+1);
46 if (ret
) strcpy( ret
, str
);
52 /*********************************************************************
55 char* CDECL
MSVCRT__strnset(char* str
, int value
, MSVCRT_size_t len
)
63 /*********************************************************************
66 char* CDECL
_strrev(char* str
)
72 for (p1
= str
, p2
= str
+ strlen(str
) - 1; p2
> p1
; ++p1
, --p2
)
82 /*********************************************************************
85 char* CDECL
_strset(char* str
, int value
)
94 /*********************************************************************
97 char * CDECL
MSVCRT_strtok( char *str
, const char *delim
)
99 thread_data_t
*data
= msvcrt_get_thread_data();
103 if (!(str
= data
->strtok_next
)) return NULL
;
105 while (*str
&& strchr( delim
, *str
)) str
++;
106 if (!*str
) return NULL
;
108 while (*str
&& !strchr( delim
, *str
)) str
++;
109 if (*str
) *str
++ = 0;
110 data
->strtok_next
= str
;
114 /*********************************************************************
115 * strtok_s (MSVCRT.@)
117 char * CDECL
MSVCRT_strtok_s(char *str
, const char *delim
, char **ctx
)
119 if(!delim
|| !ctx
|| (!str
&& !*ctx
)) {
120 MSVCRT__invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
121 *MSVCRT__errno() = MSVCRT_EINVAL
;
128 while(*str
&& strchr(delim
, *str
))
134 while(**ctx
&& !strchr(delim
, **ctx
))
142 /*********************************************************************
145 void CDECL
MSVCRT__swab(char* src
, char* dst
, int len
)
149 len
= (unsigned)len
>> 1;
161 /*********************************************************************
162 * strtod_l (MSVCRT.@)
164 double CDECL
MSVCRT_strtod_l( const char *str
, char **end
, MSVCRT__locale_t locale
)
166 unsigned __int64 d
=0, hlp
;
172 MSVCRT__invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
173 *MSVCRT__errno() = MSVCRT_EINVAL
;
178 locale
= get_locale();
180 /* FIXME: use *_l functions */
192 hlp
= d
*10+*(p
++)-'0';
193 if(d
>MSVCRT_UI64_MAX
/10 || hlp
<d
) {
204 if(*p
== *locale
->locinfo
->lconv
->decimal_point
)
208 hlp
= d
*10+*(p
++)-'0';
209 if(d
>MSVCRT_UI64_MAX
/10 || hlp
<d
)
224 if(*p
=='e' || *p
=='E' || *p
=='d' || *p
=='D') {
236 if(e
>INT_MAX
/10 || (e
=e
*10+*p
-'0')<0)
242 if(exp
<0 && e
<0 && exp
+e
>=0) exp
= INT_MIN
;
243 else if(exp
>0 && e
>0 && exp
+e
<0) exp
= INT_MAX
;
246 if(*p
=='-' || *p
=='+')
253 ret
= (double)sign
*d
*pow(10, exp
);
255 ret
= (double)sign
*d
/pow(10, -exp
);
257 if((d
&& ret
==0.0) || isinf(ret
))
258 *MSVCRT__errno() = MSVCRT_ERANGE
;
266 /*********************************************************************
269 double CDECL
MSVCRT_strtod( const char *str
, char **end
)
271 return MSVCRT_strtod_l( str
, end
, NULL
);
274 /*********************************************************************
277 double CDECL
MSVCRT_atof( const char *str
)
279 return MSVCRT_strtod_l(str
, NULL
, NULL
);
282 /*********************************************************************
285 double CDECL
MSVCRT__atof_l( const char *str
, MSVCRT__locale_t locale
)
287 return MSVCRT_strtod_l(str
, NULL
, locale
);
290 /*********************************************************************
293 int CDECL
MSVCRT_strcoll( const char* str1
, const char* str2
)
295 /* FIXME: handle Windows locale */
296 return strcoll( str1
, str2
);
299 /*********************************************************************
300 * strcpy_s (MSVCRT.@)
302 int CDECL
MSVCRT_strcpy_s( char* dst
, MSVCRT_size_t elem
, const char* src
)
305 if(!elem
) return MSVCRT_EINVAL
;
306 if(!dst
) return MSVCRT_EINVAL
;
310 return MSVCRT_EINVAL
;
313 for(i
= 0; i
< elem
; i
++)
315 if((dst
[i
] = src
[i
]) == '\0') return 0;
318 return MSVCRT_ERANGE
;
321 /*********************************************************************
322 * strcat_s (MSVCRT.@)
324 int CDECL
MSVCRT_strcat_s( char* dst
, MSVCRT_size_t elem
, const char* src
)
327 if(!dst
) return MSVCRT_EINVAL
;
328 if(elem
== 0) return MSVCRT_EINVAL
;
332 return MSVCRT_EINVAL
;
335 for(i
= 0; i
< elem
; i
++)
339 for(j
= 0; (j
+ i
) < elem
; j
++)
341 if((dst
[j
+ i
] = src
[j
]) == '\0') return 0;
345 /* Set the first element to 0, not the first element after the skipped part */
347 return MSVCRT_ERANGE
;
350 /*********************************************************************
353 MSVCRT_size_t CDECL
MSVCRT_strxfrm( char *dest
, const char *src
, MSVCRT_size_t len
)
355 /* FIXME: handle Windows locale */
356 return strxfrm( dest
, src
, len
);
359 /*********************************************************************
360 * _stricoll (MSVCRT.@)
362 int CDECL
MSVCRT__stricoll( const char* str1
, const char* str2
)
364 /* FIXME: handle collates */
365 TRACE("str1 %s str2 %s\n", debugstr_a(str1
), debugstr_a(str2
));
366 return lstrcmpiA( str1
, str2
);
369 /********************************************************************
370 * _atoldbl (MSVCRT.@)
372 int CDECL
MSVCRT__atoldbl(MSVCRT__LDOUBLE
*value
, const char *str
)
374 /* FIXME needs error checking for huge/small values */
376 TRACE("str %s value %p\n",str
,value
);
377 value
->x
= strtold(str
,0);
379 FIXME("stub, str %s value %p\n",str
,value
);
384 /********************************************************************
385 * __STRINGTOLD (MSVCRT.@)
387 int CDECL
__STRINGTOLD( MSVCRT__LDOUBLE
*value
, char **endptr
, const char *str
, int flags
)
390 FIXME("%p %p %s %x partial stub\n", value
, endptr
, str
, flags
);
391 value
->x
= strtold(str
,endptr
);
393 FIXME("%p %p %s %x stub\n", value
, endptr
, str
, flags
);
398 /******************************************************************
401 MSVCRT_long CDECL
MSVCRT_strtol(const char* nptr
, char** end
, int base
)
403 /* wrapper to forward libc error code to msvcrt's error codes */
407 ret
= strtol(nptr
, end
, base
);
410 case ERANGE
: *MSVCRT__errno() = MSVCRT_ERANGE
; break;
411 case EINVAL
: *MSVCRT__errno() = MSVCRT_EINVAL
; break;
413 /* cope with the fact that we may use 64bit long integers on libc
414 * while msvcrt always uses 32bit long integers
416 if (ret
> MSVCRT_LONG_MAX
)
418 ret
= MSVCRT_LONG_MAX
;
419 *MSVCRT__errno() = MSVCRT_ERANGE
;
421 else if (ret
< -MSVCRT_LONG_MAX
- 1)
423 ret
= -MSVCRT_LONG_MAX
- 1;
424 *MSVCRT__errno() = MSVCRT_ERANGE
;
432 /******************************************************************
435 MSVCRT_ulong CDECL
MSVCRT_strtoul(const char* nptr
, char** end
, int base
)
437 /* wrapper to forward libc error code to msvcrt's error codes */
441 ret
= strtoul(nptr
, end
, base
);
444 case ERANGE
: *MSVCRT__errno() = MSVCRT_ERANGE
; break;
445 case EINVAL
: *MSVCRT__errno() = MSVCRT_EINVAL
; break;
447 /* cope with the fact that we may use 64bit long integers on libc
448 * while msvcrt always uses 32bit long integers
450 if (ret
> MSVCRT_ULONG_MAX
)
452 ret
= MSVCRT_ULONG_MAX
;
453 *MSVCRT__errno() = MSVCRT_ERANGE
;
461 /******************************************************************
464 MSVCRT_size_t CDECL
MSVCRT_strnlen(const char *s
, MSVCRT_size_t maxlen
)
468 for(i
=0; i
<maxlen
; i
++)
474 /*********************************************************************
475 * _strtoi64_l (MSVCRT.@)
477 * FIXME: locale parameter is ignored
479 __int64 CDECL
MSVCRT_strtoi64_l(const char *nptr
, char **endptr
, int base
, MSVCRT__locale_t locale
)
481 BOOL negative
= FALSE
;
484 TRACE("(%s %p %d %p)\n", nptr
, endptr
, base
, locale
);
486 if(!nptr
|| base
<0 || base
>36 || base
==1) {
487 MSVCRT__invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
491 while(isspace(*nptr
)) nptr
++;
496 } else if(*nptr
== '+')
499 if((base
==0 || base
==16) && *nptr
=='0' && tolower(*(nptr
+1))=='x') {
512 char cur
= tolower(*nptr
);
520 if(cur
<'a' || cur
>='a'+base
-10)
530 if(!negative
&& (ret
>MSVCRT_I64_MAX
/base
|| ret
*base
>MSVCRT_I64_MAX
-v
)) {
531 ret
= MSVCRT_I64_MAX
;
532 *MSVCRT__errno() = MSVCRT_ERANGE
;
533 } else if(negative
&& (ret
<MSVCRT_I64_MIN
/base
|| ret
*base
<MSVCRT_I64_MIN
-v
)) {
534 ret
= MSVCRT_I64_MIN
;
535 *MSVCRT__errno() = MSVCRT_ERANGE
;
541 *endptr
= (char*)nptr
;
546 /*********************************************************************
547 * _strtoi64 (MSVCRT.@)
549 __int64 CDECL
MSVCRT_strtoi64(const char *nptr
, char **endptr
, int base
)
551 return MSVCRT_strtoi64_l(nptr
, endptr
, base
, NULL
);
554 /*********************************************************************
555 * _strtoui64_l (MSVCRT.@)
557 * FIXME: locale parameter is ignored
559 unsigned __int64 CDECL
MSVCRT_strtoui64_l(const char *nptr
, char **endptr
, int base
, MSVCRT__locale_t locale
)
561 BOOL negative
= FALSE
;
562 unsigned __int64 ret
= 0;
564 TRACE("(%s %p %d %p)\n", nptr
, endptr
, base
, locale
);
566 if(!nptr
|| base
<0 || base
>36 || base
==1) {
567 MSVCRT__invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
571 while(isspace(*nptr
)) nptr
++;
576 } else if(*nptr
== '+')
579 if((base
==0 || base
==16) && *nptr
=='0' && tolower(*(nptr
+1))=='x') {
592 char cur
= tolower(*nptr
);
600 if(cur
<'a' || cur
>='a'+base
-10)
607 if(ret
>MSVCRT_UI64_MAX
/base
|| ret
*base
>MSVCRT_UI64_MAX
-v
) {
608 ret
= MSVCRT_UI64_MAX
;
609 *MSVCRT__errno() = MSVCRT_ERANGE
;
615 *endptr
= (char*)nptr
;
617 return negative
? -ret
: ret
;
620 /*********************************************************************
621 * _strtoui64 (MSVCRT.@)
623 unsigned __int64 CDECL
MSVCRT_strtoui64(const char *nptr
, char **endptr
, int base
)
625 return MSVCRT_strtoui64_l(nptr
, endptr
, base
, NULL
);
628 /*********************************************************************
629 * _ui64toa_s (MSVCRT.@)
631 int CDECL
MSVCRT__ui64toa_s(unsigned __int64 value
, char *str
,
632 MSVCRT_size_t size
, int radix
)
634 char buffer
[65], *pos
;
637 if(!str
|| radix
<2 || radix
>36) {
638 MSVCRT__invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
639 *MSVCRT__errno() = MSVCRT_EINVAL
;
640 return MSVCRT_EINVAL
;
653 *--pos
= 'a'+digit
-10;
656 if(buffer
-pos
+65 > size
) {
657 MSVCRT__invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
658 *MSVCRT__errno() = MSVCRT_EINVAL
;
659 return MSVCRT_EINVAL
;
662 memcpy(str
, pos
, buffer
-pos
+65);