2 * NTDLL string functions
4 * Copyright 2000 Alexandre Julliard
5 * Copyright 2000 Jon Griffiths
6 * Copyright 2003 Thomas Mertes
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "ntdll_misc.h"
37 /* same as wctypes except for TAB, which doesn't have C1_BLANK for some reason... */
38 static const unsigned short ctypes
[257] =
43 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
44 0x0020, 0x0028, 0x0028, 0x0028, 0x0028, 0x0028, 0x0020, 0x0020,
46 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
47 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
49 0x0048, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
50 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
52 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084,
53 0x0084, 0x0084, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
55 0x0010, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0181, 0x0101,
56 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
58 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
59 0x0101, 0x0101, 0x0101, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
61 0x0010, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0182, 0x0102,
62 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
64 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102, 0x0102,
65 0x0102, 0x0102, 0x0102, 0x0010, 0x0010, 0x0010, 0x0010, 0x0020
69 /*********************************************************************
72 void * __cdecl
memchr( const void *ptr
, int c
, size_t n
)
74 const unsigned char *p
= ptr
;
76 for (p
= ptr
; n
; n
--, p
++) if (*p
== (unsigned char)c
) return (void *)(ULONG_PTR
)p
;
81 /*********************************************************************
84 int __cdecl
memcmp( const void *ptr1
, const void *ptr2
, size_t n
)
86 const unsigned char *p1
, *p2
;
88 for (p1
= ptr1
, p2
= ptr2
; n
; n
--, p1
++, p2
++)
90 if (*p1
< *p2
) return -1;
91 if (*p1
> *p2
) return 1;
97 /*********************************************************************
101 * Behaves like memmove.
103 void * __cdecl
memcpy( void *dst
, const void *src
, size_t n
)
105 volatile unsigned char *d
= dst
; /* avoid gcc optimizations */
106 const unsigned char *s
= src
;
108 if ((size_t)dst
- (size_t)src
>= n
)
110 while (n
--) *d
++ = *s
++;
116 while (n
--) *d
-- = *s
--;
122 /*********************************************************************
125 void * __cdecl
memmove( void *dst
, const void *src
, size_t n
)
127 volatile unsigned char *d
= dst
; /* avoid gcc optimizations */
128 const unsigned char *s
= src
;
130 if ((size_t)dst
- (size_t)src
>= n
)
132 while (n
--) *d
++ = *s
++;
138 while (n
--) *d
-- = *s
--;
144 static inline void memset_aligned_32( unsigned char *d
, uint64_t v
, size_t n
)
146 unsigned char *end
= d
+ n
;
149 *(uint64_t *)(d
+ 0) = v
;
150 *(uint64_t *)(d
+ 8) = v
;
151 *(uint64_t *)(d
+ 16) = v
;
152 *(uint64_t *)(d
+ 24) = v
;
157 /*********************************************************************
160 void *__cdecl
memset( void *dst
, int c
, size_t n
)
162 typedef uint64_t DECLSPEC_ALIGN(1) unaligned_ui64
;
163 typedef uint32_t DECLSPEC_ALIGN(1) unaligned_ui32
;
164 typedef uint16_t DECLSPEC_ALIGN(1) unaligned_ui16
;
166 uint64_t v
= 0x101010101010101ull
* (unsigned char)c
;
167 unsigned char *d
= (unsigned char *)dst
;
168 size_t a
= 0x20 - ((uintptr_t)d
& 0x1f);
172 *(unaligned_ui64
*)(d
+ 0) = v
;
173 *(unaligned_ui64
*)(d
+ 8) = v
;
174 *(unaligned_ui64
*)(d
+ n
- 16) = v
;
175 *(unaligned_ui64
*)(d
+ n
- 8) = v
;
176 if (n
<= 32) return dst
;
177 *(unaligned_ui64
*)(d
+ 16) = v
;
178 *(unaligned_ui64
*)(d
+ 24) = v
;
179 *(unaligned_ui64
*)(d
+ n
- 32) = v
;
180 *(unaligned_ui64
*)(d
+ n
- 24) = v
;
181 if (n
<= 64) return dst
;
184 memset_aligned_32( d
+ a
, v
, n
);
189 *(unaligned_ui64
*)d
= v
;
190 *(unaligned_ui64
*)(d
+ n
- 8) = v
;
195 *(unaligned_ui32
*)d
= v
;
196 *(unaligned_ui32
*)(d
+ n
- 4) = v
;
201 *(unaligned_ui16
*)d
= v
;
202 *(unaligned_ui16
*)(d
+ n
- 2) = v
;
214 /*********************************************************************
217 char * __cdecl
strcat( char *dst
, const char *src
)
221 while ((*d
++ = *src
++));
226 /*********************************************************************
229 char * __cdecl
strchr( const char *str
, int c
)
231 do { if (*str
== (char)c
) return (char *)(ULONG_PTR
)str
; } while (*str
++);
236 /*********************************************************************
239 int __cdecl
strcmp( const char *str1
, const char *str2
)
241 while (*str1
&& *str1
== *str2
) { str1
++; str2
++; }
242 if ((unsigned char)*str1
> (unsigned char)*str2
) return 1;
243 if ((unsigned char)*str1
< (unsigned char)*str2
) return -1;
248 /*********************************************************************
251 char * __cdecl
strcpy( char *dst
, const char *src
)
254 while ((*d
++ = *src
++));
259 /*********************************************************************
262 size_t __cdecl
strcspn( const char *str
, const char *reject
)
265 for (ptr
= str
; *ptr
; ptr
++) if (strchr( reject
, *ptr
)) break;
270 /*********************************************************************
273 size_t __cdecl
strlen( const char *str
)
281 /*********************************************************************
284 char * __cdecl
strncat( char *dst
, const char *src
, size_t len
)
288 for ( ; len
&& *src
; d
++, src
++, len
--) *d
= *src
;
294 /*********************************************************************
297 int __cdecl
strncmp( const char *str1
, const char *str2
, size_t len
)
300 while (--len
&& *str1
&& *str1
== *str2
) { str1
++; str2
++; }
301 return (unsigned char)*str1
- (unsigned char)*str2
;
305 /*********************************************************************
309 char * __cdecl
strncpy( char *dst
, const char *src
, size_t len
)
312 for (d
= dst
; len
&& *src
; d
++, src
++, len
--) *d
= *src
;
313 while (len
--) *d
++ = 0;
318 /*********************************************************************
321 size_t __cdecl
strnlen( const char *str
, size_t len
)
324 for (s
= str
; len
&& *s
; s
++, len
--) ;
329 /*********************************************************************
332 char * __cdecl
strpbrk( const char *str
, const char *accept
)
334 for ( ; *str
; str
++) if (strchr( accept
, *str
)) return (char *)(ULONG_PTR
)str
;
339 /*********************************************************************
342 char * __cdecl
strrchr( const char *str
, int c
)
345 do { if (*str
== (char)c
) ret
= (char *)(ULONG_PTR
)str
; } while (*str
++);
350 /*********************************************************************
353 size_t __cdecl
strspn( const char *str
, const char *accept
)
356 for (ptr
= str
; *ptr
; ptr
++) if (!strchr( accept
, *ptr
)) break;
361 /*********************************************************************
364 char * __cdecl
strstr( const char *str
, const char *sub
)
368 const char *p1
= str
, *p2
= sub
;
369 while (*p1
&& *p2
&& *p1
== *p2
) { p1
++; p2
++; }
370 if (!*p2
) return (char *)str
;
377 /*********************************************************************
380 void * __cdecl
_memccpy( void *dst
, const void *src
, int c
, size_t n
)
382 unsigned char *d
= dst
;
383 const unsigned char *s
= src
;
384 while (n
--) if ((*d
++ = *s
++) == (unsigned char)c
) return d
;
389 /*********************************************************************
392 int __cdecl
tolower( int c
)
394 return (char)c
>= 'A' && (char)c
<= 'Z' ? c
- 'A' + 'a' : c
;
398 /*********************************************************************
401 * Compare two blocks of memory as strings, ignoring case.
404 * s1 [I] First string to compare to s2
405 * s2 [I] Second string to compare to s1
406 * len [I] Number of bytes to compare
409 * An integer less than, equal to, or greater than zero indicating that
410 * s1 is less than, equal to or greater than s2 respectively.
413 * Any Nul characters in s1 or s2 are ignored. This function always
414 * compares up to len bytes or the first place where s1 and s2 differ.
416 int __cdecl
_memicmp( const void *str1
, const void *str2
, size_t len
)
418 const unsigned char *s1
= str1
, *s2
= str2
;
422 if ((ret
= tolower(*s1
) - tolower(*s2
))) break;
430 /*********************************************************************
431 * _strnicmp (NTDLL.@)
433 int __cdecl
_strnicmp( LPCSTR str1
, LPCSTR str2
, size_t n
)
439 l1
= (unsigned char)tolower(*str1
);
440 l2
= (unsigned char)tolower(*str2
);
443 if (sizeof(void *) > sizeof(int)) return l1
- l2
;
444 return l1
- l2
> 0 ? 1 : -1;
454 /*********************************************************************
458 int __cdecl
_stricmp( LPCSTR str1
, LPCSTR str2
)
460 return _strnicmp( str1
, str2
, -1 );
464 /*********************************************************************
467 * Convert a string to upper case.
470 * str [I/O] String to convert
473 * str. There is no error return, if str is NULL or invalid, this
474 * function will crash.
476 LPSTR __cdecl
_strupr( LPSTR str
)
479 for ( ; *str
; str
++) *str
= RtlUpperChar(*str
);
484 /*********************************************************************
487 * Convert a string to lowercase
490 * str [I/O] String to convert
493 * str. There is no error return, if str is NULL or invalid, this
494 * function will crash.
496 LPSTR __cdecl
_strlwr( LPSTR str
)
499 for ( ; *str
; str
++) *str
= tolower(*str
);
504 /*********************************************************************
507 int __cdecl
toupper( int c
)
509 char str
[4], *p
= str
;
513 memcpy( str
, &c
, sizeof(c
) );
514 wc
= RtlAnsiCharToUnicodeChar( &p
);
515 if (RtlUpcaseUnicodeToMultiByteN( str
, 2, &len
, &wc
, sizeof(wc
) )) return c
;
516 if (len
== 2) return ((unsigned char)str
[0] << 8) + (unsigned char)str
[1];
517 return (unsigned char)str
[0];
521 /*********************************************************************
524 int __cdecl
isalnum( int c
)
526 return ctypes
[c
+ 1] & (C1_LOWER
| C1_UPPER
| C1_DIGIT
);
530 /*********************************************************************
533 int __cdecl
isalpha( int c
)
535 return ctypes
[c
+ 1] & (C1_LOWER
| C1_UPPER
);
539 /*********************************************************************
542 int __cdecl
iscntrl( int c
)
544 return ctypes
[c
+ 1] & C1_CNTRL
;
548 /*********************************************************************
551 int __cdecl
isdigit( int c
)
553 return ctypes
[c
+ 1] & C1_DIGIT
;
557 /*********************************************************************
560 int __cdecl
isgraph( int c
)
562 return ctypes
[c
+ 1] & (C1_LOWER
| C1_UPPER
| C1_DIGIT
| C1_PUNCT
);
566 /*********************************************************************
569 int __cdecl
islower( int c
)
571 return ctypes
[c
+ 1] & C1_LOWER
;
575 /*********************************************************************
578 int __cdecl
isprint( int c
)
580 return ctypes
[c
+ 1] & (C1_LOWER
| C1_UPPER
| C1_DIGIT
| C1_PUNCT
| C1_BLANK
);
584 /*********************************************************************
587 int __cdecl
ispunct( int c
)
589 return ctypes
[c
+ 1] & C1_PUNCT
;
593 /*********************************************************************
596 int __cdecl
isspace( int c
)
598 return ctypes
[c
+ 1] & C1_SPACE
;
602 /*********************************************************************
605 int __cdecl
isupper( int c
)
607 return ctypes
[c
+ 1] & C1_UPPER
;
611 /*********************************************************************
614 int __cdecl
isxdigit( int c
)
616 return ctypes
[c
+ 1] & C1_XDIGIT
;
620 /*********************************************************************
621 * __isascii (NTDLL.@)
623 int CDECL
__isascii(int c
)
625 return (unsigned)c
< 0x80;
629 /*********************************************************************
630 * __toascii (NTDLL.@)
632 int CDECL
__toascii(int c
)
634 return (unsigned)c
& 0x7f;
638 /*********************************************************************
641 int CDECL
__iscsym(int c
)
643 return (c
< 127 && (isalnum(c
) || c
== '_'));
647 /*********************************************************************
648 * __iscsymf (NTDLL.@)
650 int CDECL
__iscsymf(int c
)
652 return (c
< 127 && (isalpha(c
) || c
== '_'));
656 /*********************************************************************
659 int CDECL
_toupper(int c
)
661 return c
- 0x20; /* sic */
665 /*********************************************************************
668 int CDECL
_tolower(int c
)
670 return c
+ 0x20; /* sic */
674 static int char_to_int( char c
)
676 if ('0' <= c
&& c
<= '9') return c
- '0';
677 if ('A' <= c
&& c
<= 'Z') return c
- 'A' + 10;
678 if ('a' <= c
&& c
<= 'z') return c
- 'a' + 10;
682 /*********************************************************************
685 __msvcrt_long __cdecl
strtol( const char *s
, char **end
, int base
)
687 BOOL negative
= FALSE
, empty
= TRUE
;
690 if (base
< 0 || base
== 1 || base
> 36) return 0;
691 if (end
) *end
= (char *)s
;
692 while (isspace(*s
)) s
++;
699 else if (*s
== '+') s
++;
701 if ((base
== 0 || base
== 16) && !char_to_int( *s
) && (s
[1] == 'x' || s
[1] == 'X'))
706 if (base
== 0) base
= char_to_int( *s
) ? 10 : 8;
710 int v
= char_to_int( *s
);
711 if (v
< 0 || v
>= base
) break;
712 if (negative
) v
= -v
;
716 if (!negative
&& (ret
> MAXLONG
/ base
|| ret
* base
> MAXLONG
- v
))
718 else if (negative
&& (ret
< (LONG
)MINLONG
/ base
|| ret
* base
< (LONG
)(MINLONG
- v
)))
721 ret
= ret
* base
+ v
;
724 if (end
&& !empty
) *end
= (char *)s
;
729 /*********************************************************************
732 __msvcrt_ulong __cdecl
strtoul( const char *s
, char **end
, int base
)
734 BOOL negative
= FALSE
, empty
= TRUE
;
737 if (base
< 0 || base
== 1 || base
> 36) return 0;
738 if (end
) *end
= (char *)s
;
739 while (isspace(*s
)) s
++;
746 else if (*s
== '+') s
++;
748 if ((base
== 0 || base
== 16) && !char_to_int( *s
) && (s
[1] == 'x' || s
[1] == 'X'))
753 if (base
== 0) base
= char_to_int( *s
) ? 10 : 8;
757 int v
= char_to_int( *s
);
758 if (v
< 0 || v
>= base
) break;
762 if (ret
> MAXDWORD
/ base
|| ret
* base
> MAXDWORD
- v
)
765 ret
= ret
* base
+ v
;
768 if (end
&& !empty
) *end
= (char *)s
;
769 return negative
? -ret
: ret
;
773 /*********************************************************************
776 * Convert an unsigned long integer to a string.
782 * - Converts value to a Nul terminated string which is copied to str.
783 * - The maximum length of the copied str is 33 bytes.
784 * - Does not check if radix is in the range of 2 to 36.
785 * - If str is NULL it crashes, as the native function does.
787 char * __cdecl
_ultoa( __msvcrt_ulong value
, char *str
, int radix
)
797 digit
= value
% radix
;
798 value
= value
/ radix
;
800 *--pos
= '0' + digit
;
802 *--pos
= 'a' + digit
- 10;
804 } while (value
!= 0L);
806 memcpy(str
, pos
, &buffer
[32] - pos
+ 1);
811 /*********************************************************************
814 * Convert a long integer to a string.
820 * - Converts value to a Nul terminated string which is copied to str.
821 * - The maximum length of the copied str is 33 bytes. If radix
822 * is 10 and value is negative, the value is converted with sign.
823 * - Does not check if radix is in the range of 2 to 36.
824 * - If str is NULL it crashes, as the native function does.
826 char * __cdecl
_ltoa( __msvcrt_long value
, char *str
, int radix
)
834 if (value
< 0 && radix
== 10) {
849 *--pos
= '0' + digit
;
851 *--pos
= 'a' + digit
- 10;
859 memcpy(str
, pos
, &buffer
[32] - pos
+ 1);
864 /*********************************************************************
867 * Converts an integer to a string.
873 * - Converts value to a '\0' terminated string which is copied to str.
874 * - The maximum length of the copied str is 33 bytes. If radix
875 * is 10 and value is negative, the value is converted with sign.
876 * - Does not check if radix is in the range of 2 to 36.
877 * - If str is NULL it crashes, as the native function does.
879 char * __cdecl
_itoa(
880 int value
, /* [I] Value to be converted */
881 char *str
, /* [O] Destination for the converted value */
882 int radix
) /* [I] Number base for conversion */
884 return _ltoa(value
, str
, radix
);
888 /*********************************************************************
891 * Converts a large unsigned integer to a string.
897 * - Converts value to a '\0' terminated string which is copied to str.
898 * - The maximum length of the copied str is 65 bytes.
899 * - Does not check if radix is in the range of 2 to 36.
900 * - If str is NULL it crashes, as the native function does.
902 char * __cdecl
_ui64toa(
903 ULONGLONG value
, /* [I] Value to be converted */
904 char *str
, /* [O] Destination for the converted value */
905 int radix
) /* [I] Number base for conversion */
915 digit
= value
% radix
;
916 value
= value
/ radix
;
918 *--pos
= '0' + digit
;
920 *--pos
= 'a' + digit
- 10;
922 } while (value
!= 0L);
924 memcpy(str
, pos
, &buffer
[64] - pos
+ 1);
929 /*********************************************************************
932 * Converts a large integer to a string.
938 * - Converts value to a Nul terminated string which is copied to str.
939 * - The maximum length of the copied str is 65 bytes. If radix
940 * is 10 and value is negative, the value is converted with sign.
941 * - Does not check if radix is in the range of 2 to 36.
942 * - If str is NULL it crashes, as the native function does.
945 * - The native DLL converts negative values (for base 10) wrong:
946 *| -1 is converted to -18446744073709551615
947 *| -2 is converted to -18446744073709551614
948 *| -9223372036854775807 is converted to -9223372036854775809
949 *| -9223372036854775808 is converted to -9223372036854775808
950 * The native msvcrt _i64toa function and our ntdll _i64toa function
951 * do not have this bug.
953 char * __cdecl
_i64toa(
954 LONGLONG value
, /* [I] Value to be converted */
955 char *str
, /* [O] Destination for the converted value */
956 int radix
) /* [I] Number base for conversion */
964 if (value
< 0 && radix
== 10) {
979 *--pos
= '0' + digit
;
981 *--pos
= 'a' + digit
- 10;
989 memcpy(str
, pos
, &buffer
[64] - pos
+ 1);
994 /*********************************************************************
997 * Convert a string to a large integer.
1000 * str [I] String to be converted
1003 * Success: The integer value represented by str.
1004 * Failure: 0. Note that this cannot be distinguished from a successful
1005 * return, if the string contains "0".
1008 * - Accepts: {whitespace} [+|-] {digits}
1009 * - No check is made for value overflow, only the lower 64 bits are assigned.
1010 * - If str is NULL it crashes, as the native function does.
1012 LONGLONG __cdecl
_atoi64( const char *str
)
1014 ULONGLONG RunningTotal
= 0;
1015 BOOL bMinus
= FALSE
;
1017 while (*str
== ' ' || (*str
>= '\011' && *str
<= '\015')) {
1023 } else if (*str
== '-') {
1028 while (*str
>= '0' && *str
<= '9') {
1029 RunningTotal
= RunningTotal
* 10 + *str
- '0';
1033 return bMinus
? -RunningTotal
: RunningTotal
;
1037 /*********************************************************************
1040 int __cdecl
atoi( const char *nptr
)
1042 return _atoi64( nptr
);
1046 /*********************************************************************
1049 __msvcrt_long __cdecl
atol( const char *nptr
)
1051 return _atoi64( nptr
);
1055 /* helper function for *scanf. Returns the value of character c in the
1056 * given base, or -1 if the given character is not a digit of the base.
1058 static int char2digit( char c
, int base
)
1060 if ((c
>= '0' && c
<= '9') && (c
<= '0'+base
-1)) return (c
-'0');
1061 if (base
<= 10) return -1;
1062 if ((c
>= 'A') && (c
<= 'Z') && (c
<= 'A'+base
-11)) return (c
-'A'+10);
1063 if ((c
>= 'a') && (c
<= 'z') && (c
<= 'a'+base
-11)) return (c
-'a'+10);
1068 static int vsscanf( const char *str
, const char *format
, va_list ap
)
1070 int rd
= 0, consumed
= 0;
1072 if (!*format
) return 0;
1074 nch
= (consumed
++, *str
++);
1080 if (isspace( *format
))
1082 /* skip whitespace */
1083 while ((nch
!= '\0') && isspace( nch
))
1084 nch
= (consumed
++, *str
++);
1086 else if (*format
== '%')
1089 BOOLEAN suppress
= 0;
1093 BOOLEAN l_prefix
= FALSE
;
1094 BOOLEAN w_prefix
= FALSE
;
1095 BOOLEAN I64_prefix
= FALSE
;
1096 BOOLEAN prefix_finished
= FALSE
;
1098 /* a leading asterisk means 'suppress assignment of this field' */
1104 /* look for width specification */
1105 while (isdigit( *format
))
1108 width
+= *format
++ - '0';
1110 if (width
== 0) width
= -1; /* no width spec seen */
1111 /* read prefix (if any) */
1112 while (!prefix_finished
)
1116 case 'h': h_prefix
++; break;
1118 if (*(format
+1) == 'l')
1125 case 'w': w_prefix
= TRUE
; break;
1127 if (*(format
+ 1) == '6' &&
1128 *(format
+ 2) == '4')
1135 prefix_finished
= TRUE
;
1137 if (!prefix_finished
) format
++;
1143 case 'P': /* pointer. */
1144 if (sizeof(void *) == sizeof(LONGLONG
)) I64_prefix
= TRUE
;
1147 case 'X': /* hexadecimal integer. */
1150 case 'o': /* octal integer */
1153 case 'u': /* unsigned decimal integer */
1156 case 'd': /* signed decimal integer */
1159 case 'i': /* generic integer */
1163 /* read an integer */
1165 BOOLEAN negative
= FALSE
;
1166 BOOLEAN seendigit
= FALSE
;
1167 /* skip initial whitespace */
1168 while ((nch
!= '\0') && isspace( nch
))
1169 nch
= (consumed
++, *str
++);
1171 if (nch
== '-' || nch
== '+')
1173 negative
= (nch
== '-');
1174 nch
= (consumed
++, *str
++);
1175 if (width
> 0) width
--;
1177 /* look for leading indication of base */
1178 if (width
!= 0 && nch
== '0' && *format
!= 'p' && *format
!= 'P')
1180 nch
= (consumed
++, *str
++);
1181 if (width
> 0) width
--;
1183 if (width
!= 0 && (nch
== 'x' || nch
== 'X'))
1189 nch
= (consumed
++, *str
++);
1190 if (width
> 0) width
--;
1193 } else if (base
== 0)
1196 /* format %i without indication of base */
1199 /* throw away leading zeros */
1200 while (width
!= 0 && nch
== '0')
1202 nch
= (consumed
++, *str
++);
1203 if (width
> 0) width
--;
1206 if (width
!= 0 && char2digit( nch
, base
) != -1)
1208 cur
= char2digit( nch
, base
);
1209 nch
= (consumed
++, *str
++);
1210 if (width
> 0) width
--;
1213 /* read until no more digits */
1214 while (width
!= 0 && nch
!= '\0' && char2digit( nch
, base
) != -1)
1216 cur
= cur
*base
+ char2digit( nch
, base
);
1217 nch
= (consumed
++, *str
++);
1218 if (width
> 0) width
--;
1222 if (!seendigit
) break; /* not a valid number */
1226 #define _SET_NUMBER_( type ) *va_arg( ap, type* ) = negative ? -cur : cur
1227 if (I64_prefix
) _SET_NUMBER_( LONGLONG
);
1228 else if (l_prefix
) _SET_NUMBER_( LONG
);
1229 else if (h_prefix
== 1) _SET_NUMBER_( short int );
1230 else _SET_NUMBER_( int );
1234 /* According to msdn,
1235 * 's' reads a character string in a call to fscanf
1236 * and 'S' a wide character string and vice versa in a
1237 * call to fwscanf. The 'h', 'w' and 'l' prefixes override
1238 * this behaviour. 'h' forces reading char * but 'l' and 'w'
1239 * force reading WCHAR. */
1241 if (w_prefix
|| l_prefix
) goto widecharstring
;
1242 else if (h_prefix
) goto charstring
;
1243 else goto charstring
;
1245 if (w_prefix
|| l_prefix
) goto widecharstring
;
1246 else if (h_prefix
) goto charstring
;
1247 else goto widecharstring
;
1249 { /* read a word into a char */
1250 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1251 char *sptr_beg
= sptr
;
1252 unsigned size
= UINT_MAX
;
1253 /* skip initial whitespace */
1254 while (nch
!= '\0' && isspace( nch
))
1255 nch
= (consumed
++, *str
++);
1256 /* read until whitespace */
1257 while (width
!= 0 && nch
!= '\0' && !isspace( nch
))
1262 if(size
> 1) size
--;
1270 nch
= (consumed
++, *str
++);
1271 if (width
> 0) width
--;
1274 if (st
&& !suppress
) *sptr
= 0;
1278 { /* read a word into a WCHAR * */
1279 WCHAR
*sptr
= suppress
? NULL
: va_arg( ap
, WCHAR
* );
1280 WCHAR
*sptr_beg
= sptr
;
1281 unsigned size
= UINT_MAX
;
1282 /* skip initial whitespace */
1283 while (nch
!= '\0' && isspace( nch
))
1284 nch
= (consumed
++, *str
++);
1285 /* read until whitespace */
1286 while (width
!= 0 && nch
!= '\0' && !isspace( nch
))
1291 if (size
> 1) size
--;
1299 nch
= (consumed
++, *str
++);
1300 if (width
> 0) width
--;
1303 if (st
&& !suppress
) *sptr
= 0;
1306 /* 'c' and 'C work analogously to 's' and 'S' as described
1309 if (w_prefix
|| l_prefix
) goto widecharacter
;
1310 else if (h_prefix
) goto character
;
1311 else goto character
;
1313 if (w_prefix
|| l_prefix
) goto widecharacter
;
1314 else if (h_prefix
) goto character
;
1315 else goto widecharacter
;
1317 { /* read single character into char */
1318 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1319 char *sptr_beg
= sptr
;
1320 unsigned size
= UINT_MAX
;
1321 if (width
== -1) width
= 1;
1322 while (width
&& nch
!= '\0')
1336 nch
= (consumed
++, *str
++);
1341 { /* read single character into a WCHAR */
1342 WCHAR
*sptr
= suppress
? NULL
: va_arg( ap
, WCHAR
* );
1343 WCHAR
*sptr_beg
= sptr
;
1344 unsigned size
= UINT_MAX
;
1345 if (width
== -1) width
= 1;
1346 while (width
&& nch
!= '\0')
1360 nch
= (consumed
++, *str
++);
1368 int *n
= va_arg( ap
, int * );
1371 /* This is an odd one: according to the standard,
1372 * "Execution of a %n directive does not increment the
1373 * assignment count returned at the completion of
1374 * execution" even if it wasn't suppressed with the
1375 * '*' flag. The Corrigendum to the standard seems
1376 * to contradict this (comment out the assignment to
1377 * suppress below if you want to implement these
1378 * alternate semantics) but the windows program I'm
1379 * looking at expects the behavior I've coded here
1380 * (which happens to be what glibc does as well).
1388 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1389 char *sptr_beg
= sptr
;
1391 ULONG Mask
[8] = { 0 };
1392 BOOLEAN invert
= FALSE
; /* Set if we are NOT to find the chars */
1393 unsigned size
= UINT_MAX
;
1395 RtlInitializeBitMap( &bitMask
, Mask
, sizeof(Mask
) * 8 );
1397 /* Read the format */
1406 RtlSetBits( &bitMask
, ']', 1 );
1409 while (*format
&& (*format
!= ']'))
1411 /* According to msdn:
1412 * "Note that %[a-z] and %[z-a] are interpreted as equivalent to %[abcde...z]." */
1413 if ((*format
== '-') && (*(format
+ 1) != ']'))
1415 if ((*(format
- 1)) < *(format
+ 1))
1416 RtlSetBits( &bitMask
, *(format
- 1) +1 , *(format
+ 1) - *(format
- 1) );
1418 RtlSetBits( &bitMask
, *(format
+ 1) , *(format
- 1) - *(format
+ 1) );
1422 RtlSetBits( &bitMask
, *format
, 1 );
1425 /* read until char is not suitable */
1426 while (width
!= 0 && nch
!= '\0')
1430 if(RtlAreBitsSet( &bitMask
, nch
, 1 ))
1432 if (!suppress
) *sptr
++ = nch
;
1439 if (RtlAreBitsClear( &bitMask
, nch
, 1 ))
1441 if (!suppress
) *sptr
++ = nch
;
1447 nch
= (consumed
++, *str
++);
1448 if (width
> 0) width
--;
1449 if(size
> 1) size
--;
1452 if (!suppress
) *sptr_beg
= 0;
1457 if (!suppress
) *sptr
= 0;
1461 /* From spec: "if a percent sign is followed by a character
1462 * that has no meaning as a format-control character, that
1463 * character and the following characters are treated as
1464 * an ordinary sequence of characters, that is, a sequence
1465 * of characters that must match the input. For example,
1466 * to specify that a percent-sign character is to be input,
1468 while (nch
!= '\0' && isspace( nch
))
1469 nch
= (consumed
++, *str
++);
1472 suppress
= TRUE
; /* whoops no field to be read */
1473 st
= 1; /* but we got what we expected */
1474 nch
= (consumed
++, *str
++);
1478 if (st
&& !suppress
) rd
++;
1479 else if (!st
) break;
1481 /* A non-white-space character causes scanf to read, but not store,
1482 * a matching non-white-space character. */
1486 nch
= (consumed
++, *str
++);
1500 /*********************************************************************
1503 int WINAPIV
sscanf( const char *str
, const char *format
, ... )
1507 va_start( valist
, format
);
1508 ret
= vsscanf( str
, format
, valist
);
1514 /*********************************************************************
1515 * _splitpath (NTDLL.@)
1517 * Split a path into its component pieces.
1520 * inpath [I] Path to split
1521 * drv [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
1522 * dir [O] Destination for directory component. Should be at least MAX_PATH characters.
1523 * fname [O] Destination for File name component. Should be at least MAX_PATH characters.
1524 * ext [O] Destination for file extension component. Should be at least MAX_PATH characters.
1529 void __cdecl
_splitpath(const char* inpath
, char * drv
, char * dir
,
1530 char* fname
, char * ext
)
1532 const char *p
, *end
;
1534 if (inpath
[0] && inpath
[1] == ':')
1544 else if (drv
) drv
[0] = 0;
1546 /* look for end of directory part */
1548 for (p
= inpath
; *p
; p
++) if (*p
== '/' || *p
== '\\') end
= p
+ 1;
1550 if (end
) /* got a directory */
1554 memcpy( dir
, inpath
, end
- inpath
);
1555 dir
[end
- inpath
] = 0;
1559 else if (dir
) dir
[0] = 0;
1561 /* look for extension: what's after the last dot */
1563 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
1565 if (!end
) end
= p
; /* there's no extension */
1569 memcpy( fname
, inpath
, end
- inpath
);
1570 fname
[end
- inpath
] = 0;
1572 if (ext
) strcpy( ext
, end
);