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
[2], *p
= str
;
515 wc
= RtlAnsiCharToUnicodeChar( &p
);
516 wc
= RtlUpcaseUnicodeChar( wc
);
517 RtlUnicodeToMultiByteN( str
, sizeof(str
), &len
, &wc
, sizeof(wc
) );
518 if (len
== 2) return ((unsigned char)str
[0] << 8) + (unsigned char)str
[1];
519 return (unsigned char)str
[0];
523 /*********************************************************************
526 int __cdecl
isalnum( int c
)
528 return ctypes
[c
+ 1] & (C1_LOWER
| C1_UPPER
| C1_DIGIT
);
532 /*********************************************************************
535 int __cdecl
isalpha( int c
)
537 return ctypes
[c
+ 1] & (C1_LOWER
| C1_UPPER
);
541 /*********************************************************************
544 int __cdecl
iscntrl( int c
)
546 return ctypes
[c
+ 1] & C1_CNTRL
;
550 /*********************************************************************
553 int __cdecl
isdigit( int c
)
555 return ctypes
[c
+ 1] & C1_DIGIT
;
559 /*********************************************************************
562 int __cdecl
isgraph( int c
)
564 return ctypes
[c
+ 1] & (C1_LOWER
| C1_UPPER
| C1_DIGIT
| C1_PUNCT
);
568 /*********************************************************************
571 int __cdecl
islower( int c
)
573 return ctypes
[c
+ 1] & C1_LOWER
;
577 /*********************************************************************
580 int __cdecl
isprint( int c
)
582 return ctypes
[c
+ 1] & (C1_LOWER
| C1_UPPER
| C1_DIGIT
| C1_PUNCT
| C1_BLANK
);
586 /*********************************************************************
589 int __cdecl
ispunct( int c
)
591 return ctypes
[c
+ 1] & C1_PUNCT
;
595 /*********************************************************************
598 int __cdecl
isspace( int c
)
600 return ctypes
[c
+ 1] & C1_SPACE
;
604 /*********************************************************************
607 int __cdecl
isupper( int c
)
609 return ctypes
[c
+ 1] & C1_UPPER
;
613 /*********************************************************************
616 int __cdecl
isxdigit( int c
)
618 return ctypes
[c
+ 1] & C1_XDIGIT
;
622 /*********************************************************************
623 * __isascii (NTDLL.@)
625 int CDECL
__isascii(int c
)
627 return (unsigned)c
< 0x80;
631 /*********************************************************************
632 * __toascii (NTDLL.@)
634 int CDECL
__toascii(int c
)
636 return (unsigned)c
& 0x7f;
640 /*********************************************************************
643 int CDECL
__iscsym(int c
)
645 return (c
< 127 && (isalnum(c
) || c
== '_'));
649 /*********************************************************************
650 * __iscsymf (NTDLL.@)
652 int CDECL
__iscsymf(int c
)
654 return (c
< 127 && (isalpha(c
) || c
== '_'));
658 /*********************************************************************
661 int CDECL
_toupper(int c
)
663 return c
- 0x20; /* sic */
667 /*********************************************************************
670 int CDECL
_tolower(int c
)
672 return c
+ 0x20; /* sic */
676 static int char_to_int( char c
)
678 if ('0' <= c
&& c
<= '9') return c
- '0';
679 if ('A' <= c
&& c
<= 'Z') return c
- 'A' + 10;
680 if ('a' <= c
&& c
<= 'z') return c
- 'a' + 10;
684 /*********************************************************************
687 __msvcrt_long __cdecl
strtol( const char *s
, char **end
, int base
)
689 BOOL negative
= FALSE
, empty
= TRUE
;
692 if (base
< 0 || base
== 1 || base
> 36) return 0;
693 if (end
) *end
= (char *)s
;
694 while (isspace(*s
)) s
++;
701 else if (*s
== '+') s
++;
703 if ((base
== 0 || base
== 16) && !char_to_int( *s
) && (s
[1] == 'x' || s
[1] == 'X'))
708 if (base
== 0) base
= char_to_int( *s
) ? 10 : 8;
712 int v
= char_to_int( *s
);
713 if (v
< 0 || v
>= base
) break;
714 if (negative
) v
= -v
;
718 if (!negative
&& (ret
> MAXLONG
/ base
|| ret
* base
> MAXLONG
- v
))
720 else if (negative
&& (ret
< (LONG
)MINLONG
/ base
|| ret
* base
< (LONG
)(MINLONG
- v
)))
723 ret
= ret
* base
+ v
;
726 if (end
&& !empty
) *end
= (char *)s
;
731 /*********************************************************************
734 __msvcrt_ulong __cdecl
strtoul( const char *s
, char **end
, int base
)
736 BOOL negative
= FALSE
, empty
= TRUE
;
739 if (base
< 0 || base
== 1 || base
> 36) return 0;
740 if (end
) *end
= (char *)s
;
741 while (isspace(*s
)) s
++;
748 else if (*s
== '+') s
++;
750 if ((base
== 0 || base
== 16) && !char_to_int( *s
) && (s
[1] == 'x' || s
[1] == 'X'))
755 if (base
== 0) base
= char_to_int( *s
) ? 10 : 8;
759 int v
= char_to_int( *s
);
760 if (v
< 0 || v
>= base
) break;
764 if (ret
> MAXDWORD
/ base
|| ret
* base
> MAXDWORD
- v
)
767 ret
= ret
* base
+ v
;
770 if (end
&& !empty
) *end
= (char *)s
;
771 return negative
? -ret
: ret
;
775 /*********************************************************************
778 * Convert an unsigned long integer to a string.
784 * - Converts value to a Nul terminated string which is copied to str.
785 * - The maximum length of the copied str is 33 bytes.
786 * - Does not check if radix is in the range of 2 to 36.
787 * - If str is NULL it crashes, as the native function does.
789 char * __cdecl
_ultoa( __msvcrt_ulong value
, char *str
, int radix
)
799 digit
= value
% radix
;
800 value
= value
/ radix
;
802 *--pos
= '0' + digit
;
804 *--pos
= 'a' + digit
- 10;
806 } while (value
!= 0L);
808 memcpy(str
, pos
, &buffer
[32] - pos
+ 1);
813 /*********************************************************************
816 * Convert a long integer to a string.
822 * - Converts value to a Nul terminated string which is copied to str.
823 * - The maximum length of the copied str is 33 bytes. If radix
824 * is 10 and value is negative, the value is converted with sign.
825 * - Does not check if radix is in the range of 2 to 36.
826 * - If str is NULL it crashes, as the native function does.
828 char * __cdecl
_ltoa( __msvcrt_long value
, char *str
, int radix
)
836 if (value
< 0 && radix
== 10) {
851 *--pos
= '0' + digit
;
853 *--pos
= 'a' + digit
- 10;
861 memcpy(str
, pos
, &buffer
[32] - pos
+ 1);
866 /*********************************************************************
869 * Converts an integer to a string.
875 * - Converts value to a '\0' terminated string which is copied to str.
876 * - The maximum length of the copied str is 33 bytes. If radix
877 * is 10 and value is negative, the value is converted with sign.
878 * - Does not check if radix is in the range of 2 to 36.
879 * - If str is NULL it crashes, as the native function does.
881 char * __cdecl
_itoa(
882 int value
, /* [I] Value to be converted */
883 char *str
, /* [O] Destination for the converted value */
884 int radix
) /* [I] Number base for conversion */
886 return _ltoa(value
, str
, radix
);
890 /*********************************************************************
893 * Converts a large unsigned integer to a string.
899 * - Converts value to a '\0' terminated string which is copied to str.
900 * - The maximum length of the copied str is 65 bytes.
901 * - Does not check if radix is in the range of 2 to 36.
902 * - If str is NULL it crashes, as the native function does.
904 char * __cdecl
_ui64toa(
905 ULONGLONG value
, /* [I] Value to be converted */
906 char *str
, /* [O] Destination for the converted value */
907 int radix
) /* [I] Number base for conversion */
917 digit
= value
% radix
;
918 value
= value
/ radix
;
920 *--pos
= '0' + digit
;
922 *--pos
= 'a' + digit
- 10;
924 } while (value
!= 0L);
926 memcpy(str
, pos
, &buffer
[64] - pos
+ 1);
931 /*********************************************************************
934 * Converts a large integer to a string.
940 * - Converts value to a Nul terminated string which is copied to str.
941 * - The maximum length of the copied str is 65 bytes. If radix
942 * is 10 and value is negative, the value is converted with sign.
943 * - Does not check if radix is in the range of 2 to 36.
944 * - If str is NULL it crashes, as the native function does.
947 * - The native DLL converts negative values (for base 10) wrong:
948 *| -1 is converted to -18446744073709551615
949 *| -2 is converted to -18446744073709551614
950 *| -9223372036854775807 is converted to -9223372036854775809
951 *| -9223372036854775808 is converted to -9223372036854775808
952 * The native msvcrt _i64toa function and our ntdll _i64toa function
953 * do not have this bug.
955 char * __cdecl
_i64toa(
956 LONGLONG value
, /* [I] Value to be converted */
957 char *str
, /* [O] Destination for the converted value */
958 int radix
) /* [I] Number base for conversion */
966 if (value
< 0 && radix
== 10) {
981 *--pos
= '0' + digit
;
983 *--pos
= 'a' + digit
- 10;
991 memcpy(str
, pos
, &buffer
[64] - pos
+ 1);
996 /*********************************************************************
999 * Convert a string to a large integer.
1002 * str [I] String to be converted
1005 * Success: The integer value represented by str.
1006 * Failure: 0. Note that this cannot be distinguished from a successful
1007 * return, if the string contains "0".
1010 * - Accepts: {whitespace} [+|-] {digits}
1011 * - No check is made for value overflow, only the lower 64 bits are assigned.
1012 * - If str is NULL it crashes, as the native function does.
1014 LONGLONG __cdecl
_atoi64( const char *str
)
1016 ULONGLONG RunningTotal
= 0;
1017 BOOL bMinus
= FALSE
;
1019 while (*str
== ' ' || (*str
>= '\011' && *str
<= '\015')) {
1025 } else if (*str
== '-') {
1030 while (*str
>= '0' && *str
<= '9') {
1031 RunningTotal
= RunningTotal
* 10 + *str
- '0';
1035 return bMinus
? -RunningTotal
: RunningTotal
;
1039 /*********************************************************************
1042 int __cdecl
atoi( const char *nptr
)
1044 return _atoi64( nptr
);
1048 /*********************************************************************
1051 __msvcrt_long __cdecl
atol( const char *nptr
)
1053 return _atoi64( nptr
);
1057 /* helper function for *scanf. Returns the value of character c in the
1058 * given base, or -1 if the given character is not a digit of the base.
1060 static int char2digit( char c
, int base
)
1062 if ((c
>= '0' && c
<= '9') && (c
<= '0'+base
-1)) return (c
-'0');
1063 if (base
<= 10) return -1;
1064 if ((c
>= 'A') && (c
<= 'Z') && (c
<= 'A'+base
-11)) return (c
-'A'+10);
1065 if ((c
>= 'a') && (c
<= 'z') && (c
<= 'a'+base
-11)) return (c
-'a'+10);
1070 static int vsscanf( const char *str
, const char *format
, va_list ap
)
1072 int rd
= 0, consumed
= 0;
1074 if (!*format
) return 0;
1076 nch
= (consumed
++, *str
++);
1082 if (isspace( *format
))
1084 /* skip whitespace */
1085 while ((nch
!= '\0') && isspace( nch
))
1086 nch
= (consumed
++, *str
++);
1088 else if (*format
== '%')
1091 BOOLEAN suppress
= 0;
1095 BOOLEAN l_prefix
= FALSE
;
1096 BOOLEAN w_prefix
= FALSE
;
1097 BOOLEAN I64_prefix
= FALSE
;
1098 BOOLEAN prefix_finished
= FALSE
;
1100 /* a leading asterisk means 'suppress assignment of this field' */
1106 /* look for width specification */
1107 while (isdigit( *format
))
1110 width
+= *format
++ - '0';
1112 if (width
== 0) width
= -1; /* no width spec seen */
1113 /* read prefix (if any) */
1114 while (!prefix_finished
)
1118 case 'h': h_prefix
++; break;
1120 if (*(format
+1) == 'l')
1127 case 'w': w_prefix
= TRUE
; break;
1129 if (*(format
+ 1) == '6' &&
1130 *(format
+ 2) == '4')
1137 prefix_finished
= TRUE
;
1139 if (!prefix_finished
) format
++;
1145 case 'P': /* pointer. */
1146 if (sizeof(void *) == sizeof(LONGLONG
)) I64_prefix
= TRUE
;
1149 case 'X': /* hexadecimal integer. */
1152 case 'o': /* octal integer */
1155 case 'u': /* unsigned decimal integer */
1158 case 'd': /* signed decimal integer */
1161 case 'i': /* generic integer */
1165 /* read an integer */
1167 BOOLEAN negative
= FALSE
;
1168 BOOLEAN seendigit
= FALSE
;
1169 /* skip initial whitespace */
1170 while ((nch
!= '\0') && isspace( nch
))
1171 nch
= (consumed
++, *str
++);
1173 if (nch
== '-' || nch
== '+')
1175 negative
= (nch
== '-');
1176 nch
= (consumed
++, *str
++);
1177 if (width
> 0) width
--;
1179 /* look for leading indication of base */
1180 if (width
!= 0 && nch
== '0' && *format
!= 'p' && *format
!= 'P')
1182 nch
= (consumed
++, *str
++);
1183 if (width
> 0) width
--;
1185 if (width
!= 0 && (nch
== 'x' || nch
== 'X'))
1191 nch
= (consumed
++, *str
++);
1192 if (width
> 0) width
--;
1195 } else if (base
== 0)
1198 /* format %i without indication of base */
1201 /* throw away leading zeros */
1202 while (width
!= 0 && nch
== '0')
1204 nch
= (consumed
++, *str
++);
1205 if (width
> 0) width
--;
1208 if (width
!= 0 && char2digit( nch
, base
) != -1)
1210 cur
= char2digit( nch
, base
);
1211 nch
= (consumed
++, *str
++);
1212 if (width
> 0) width
--;
1215 /* read until no more digits */
1216 while (width
!= 0 && nch
!= '\0' && char2digit( nch
, base
) != -1)
1218 cur
= cur
*base
+ char2digit( nch
, base
);
1219 nch
= (consumed
++, *str
++);
1220 if (width
> 0) width
--;
1224 if (!seendigit
) break; /* not a valid number */
1228 #define _SET_NUMBER_( type ) *va_arg( ap, type* ) = negative ? -cur : cur
1229 if (I64_prefix
) _SET_NUMBER_( LONGLONG
);
1230 else if (l_prefix
) _SET_NUMBER_( LONG
);
1231 else if (h_prefix
== 1) _SET_NUMBER_( short int );
1232 else _SET_NUMBER_( int );
1236 /* According to msdn,
1237 * 's' reads a character string in a call to fscanf
1238 * and 'S' a wide character string and vice versa in a
1239 * call to fwscanf. The 'h', 'w' and 'l' prefixes override
1240 * this behaviour. 'h' forces reading char * but 'l' and 'w'
1241 * force reading WCHAR. */
1243 if (w_prefix
|| l_prefix
) goto widecharstring
;
1244 else if (h_prefix
) goto charstring
;
1245 else goto charstring
;
1247 if (w_prefix
|| l_prefix
) goto widecharstring
;
1248 else if (h_prefix
) goto charstring
;
1249 else goto widecharstring
;
1251 { /* read a word into a char */
1252 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1253 char *sptr_beg
= sptr
;
1254 unsigned size
= UINT_MAX
;
1255 /* skip initial whitespace */
1256 while (nch
!= '\0' && isspace( nch
))
1257 nch
= (consumed
++, *str
++);
1258 /* read until whitespace */
1259 while (width
!= 0 && nch
!= '\0' && !isspace( nch
))
1264 if(size
> 1) size
--;
1272 nch
= (consumed
++, *str
++);
1273 if (width
> 0) width
--;
1276 if (st
&& !suppress
) *sptr
= 0;
1280 { /* read a word into a WCHAR * */
1281 WCHAR
*sptr
= suppress
? NULL
: va_arg( ap
, WCHAR
* );
1282 WCHAR
*sptr_beg
= sptr
;
1283 unsigned size
= UINT_MAX
;
1284 /* skip initial whitespace */
1285 while (nch
!= '\0' && isspace( nch
))
1286 nch
= (consumed
++, *str
++);
1287 /* read until whitespace */
1288 while (width
!= 0 && nch
!= '\0' && !isspace( nch
))
1293 if (size
> 1) size
--;
1301 nch
= (consumed
++, *str
++);
1302 if (width
> 0) width
--;
1305 if (st
&& !suppress
) *sptr
= 0;
1308 /* 'c' and 'C work analogously to 's' and 'S' as described
1311 if (w_prefix
|| l_prefix
) goto widecharacter
;
1312 else if (h_prefix
) goto character
;
1313 else goto character
;
1315 if (w_prefix
|| l_prefix
) goto widecharacter
;
1316 else if (h_prefix
) goto character
;
1317 else goto widecharacter
;
1319 { /* read single character into char */
1320 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1321 char *sptr_beg
= sptr
;
1322 unsigned size
= UINT_MAX
;
1323 if (width
== -1) width
= 1;
1324 while (width
&& nch
!= '\0')
1338 nch
= (consumed
++, *str
++);
1343 { /* read single character into a WCHAR */
1344 WCHAR
*sptr
= suppress
? NULL
: va_arg( ap
, WCHAR
* );
1345 WCHAR
*sptr_beg
= sptr
;
1346 unsigned size
= UINT_MAX
;
1347 if (width
== -1) width
= 1;
1348 while (width
&& nch
!= '\0')
1362 nch
= (consumed
++, *str
++);
1370 int *n
= va_arg( ap
, int * );
1373 /* This is an odd one: according to the standard,
1374 * "Execution of a %n directive does not increment the
1375 * assignment count returned at the completion of
1376 * execution" even if it wasn't suppressed with the
1377 * '*' flag. The Corrigendum to the standard seems
1378 * to contradict this (comment out the assignment to
1379 * suppress below if you want to implement these
1380 * alternate semantics) but the windows program I'm
1381 * looking at expects the behavior I've coded here
1382 * (which happens to be what glibc does as well).
1390 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1391 char *sptr_beg
= sptr
;
1393 ULONG Mask
[8] = { 0 };
1394 BOOLEAN invert
= FALSE
; /* Set if we are NOT to find the chars */
1395 unsigned size
= UINT_MAX
;
1397 RtlInitializeBitMap( &bitMask
, Mask
, sizeof(Mask
) * 8 );
1399 /* Read the format */
1408 RtlSetBits( &bitMask
, ']', 1 );
1411 while (*format
&& (*format
!= ']'))
1413 /* According to msdn:
1414 * "Note that %[a-z] and %[z-a] are interpreted as equivalent to %[abcde...z]." */
1415 if ((*format
== '-') && (*(format
+ 1) != ']'))
1417 if ((*(format
- 1)) < *(format
+ 1))
1418 RtlSetBits( &bitMask
, *(format
- 1) +1 , *(format
+ 1) - *(format
- 1) );
1420 RtlSetBits( &bitMask
, *(format
+ 1) , *(format
- 1) - *(format
+ 1) );
1424 RtlSetBits( &bitMask
, *format
, 1 );
1427 /* read until char is not suitable */
1428 while (width
!= 0 && nch
!= '\0')
1432 if(RtlAreBitsSet( &bitMask
, nch
, 1 ))
1434 if (!suppress
) *sptr
++ = nch
;
1441 if (RtlAreBitsClear( &bitMask
, nch
, 1 ))
1443 if (!suppress
) *sptr
++ = nch
;
1449 nch
= (consumed
++, *str
++);
1450 if (width
> 0) width
--;
1451 if(size
> 1) size
--;
1454 if (!suppress
) *sptr_beg
= 0;
1459 if (!suppress
) *sptr
= 0;
1463 /* From spec: "if a percent sign is followed by a character
1464 * that has no meaning as a format-control character, that
1465 * character and the following characters are treated as
1466 * an ordinary sequence of characters, that is, a sequence
1467 * of characters that must match the input. For example,
1468 * to specify that a percent-sign character is to be input,
1470 while (nch
!= '\0' && isspace( nch
))
1471 nch
= (consumed
++, *str
++);
1474 suppress
= TRUE
; /* whoops no field to be read */
1475 st
= 1; /* but we got what we expected */
1476 nch
= (consumed
++, *str
++);
1480 if (st
&& !suppress
) rd
++;
1481 else if (!st
) break;
1483 /* A non-white-space character causes scanf to read, but not store,
1484 * a matching non-white-space character. */
1488 nch
= (consumed
++, *str
++);
1502 /*********************************************************************
1505 int WINAPIV
sscanf( const char *str
, const char *format
, ... )
1509 va_start( valist
, format
);
1510 ret
= vsscanf( str
, format
, valist
);
1516 /*********************************************************************
1517 * _splitpath (NTDLL.@)
1519 * Split a path into its component pieces.
1522 * inpath [I] Path to split
1523 * drv [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
1524 * dir [O] Destination for directory component. Should be at least MAX_PATH characters.
1525 * fname [O] Destination for File name component. Should be at least MAX_PATH characters.
1526 * ext [O] Destination for file extension component. Should be at least MAX_PATH characters.
1531 void __cdecl
_splitpath(const char* inpath
, char * drv
, char * dir
,
1532 char* fname
, char * ext
)
1534 const char *p
, *end
;
1536 if (inpath
[0] && inpath
[1] == ':')
1546 else if (drv
) drv
[0] = 0;
1548 /* look for end of directory part */
1550 for (p
= inpath
; *p
; p
++) if (*p
== '/' || *p
== '\\') end
= p
+ 1;
1552 if (end
) /* got a directory */
1556 memcpy( dir
, inpath
, end
- inpath
);
1557 dir
[end
- inpath
] = 0;
1561 else if (dir
) dir
[0] = 0;
1563 /* look for extension: what's after the last dot */
1565 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
1567 if (!end
) end
= p
; /* there's no extension */
1571 memcpy( fname
, inpath
, end
- inpath
);
1572 fname
[end
- inpath
] = 0;
1574 if (ext
) strcpy( ext
, end
);