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
24 #include "wine/port.h"
37 /*********************************************************************
40 void * __cdecl
NTDLL_memchr( const void *ptr
, int c
, size_t n
)
42 return memchr( ptr
, c
, n
);
46 /*********************************************************************
49 int __cdecl
NTDLL_memcmp( const void *ptr1
, const void *ptr2
, size_t n
)
51 return memcmp( ptr1
, ptr2
, n
);
55 /*********************************************************************
59 * Behaves like memmove.
61 void * __cdecl
NTDLL_memcpy( void *dst
, const void *src
, size_t n
)
63 return memmove( dst
, src
, n
);
67 /*********************************************************************
70 void * __cdecl
NTDLL_memmove( void *dst
, const void *src
, size_t n
)
72 return memmove( dst
, src
, n
);
76 /*********************************************************************
79 void * __cdecl
NTDLL_memset( void *dst
, int c
, size_t n
)
81 return memset( dst
, c
, n
);
85 /*********************************************************************
88 char * __cdecl
NTDLL_strcat( char *dst
, const char *src
)
90 return strcat( dst
, src
);
94 /*********************************************************************
97 char * __cdecl
NTDLL_strchr( const char *str
, int c
)
99 return strchr( str
, c
);
103 /*********************************************************************
106 int __cdecl
NTDLL_strcmp( const char *str1
, const char *str2
)
108 return strcmp( str1
, str2
);
112 /*********************************************************************
115 char * __cdecl
NTDLL_strcpy( char *dst
, const char *src
)
117 return strcpy( dst
, src
);
121 /*********************************************************************
124 size_t __cdecl
NTDLL_strcspn( const char *str
, const char *reject
)
126 return strcspn( str
, reject
);
130 /*********************************************************************
133 size_t __cdecl
NTDLL_strlen( const char *str
)
135 return strlen( str
);
139 /*********************************************************************
142 char * __cdecl
NTDLL_strncat( char *dst
, const char *src
, size_t len
)
144 return strncat( dst
, src
, len
);
148 /*********************************************************************
151 int __cdecl
NTDLL_strncmp( const char *str1
, const char *str2
, size_t len
)
153 return strncmp( str1
, str2
, len
);
157 /*********************************************************************
160 char * __cdecl
NTDLL_strncpy( char *dst
, const char *src
, size_t len
)
162 return strncpy( dst
, src
, len
);
166 /*********************************************************************
169 size_t __cdecl
NTDLL_strnlen( const char *str
, size_t len
)
171 return strnlen( str
, len
);
175 /*********************************************************************
178 char * __cdecl
NTDLL_strpbrk( const char *str
, const char *accept
)
180 return strpbrk( str
, accept
);
184 /*********************************************************************
187 char * __cdecl
NTDLL_strrchr( const char *str
, int c
)
189 return strrchr( str
, c
);
193 /*********************************************************************
196 size_t __cdecl
NTDLL_strspn( const char *str
, const char *accept
)
198 return strspn( str
, accept
);
202 /*********************************************************************
205 char * __cdecl
NTDLL_strstr( const char *haystack
, const char *needle
)
207 return strstr( haystack
, needle
);
211 /*********************************************************************
214 void * __cdecl
_memccpy( void *dst
, const void *src
, int c
, size_t n
)
216 return memccpy( dst
, src
, c
, n
);
220 /*********************************************************************
223 * Compare two blocks of memory as strings, ignoring case.
226 * s1 [I] First string to compare to s2
227 * s2 [I] Second string to compare to s1
228 * len [I] Number of bytes to compare
231 * An integer less than, equal to, or greater than zero indicating that
232 * s1 is less than, equal to or greater than s2 respectively.
235 * Any Nul characters in s1 or s2 are ignored. This function always
236 * compares up to len bytes or the first place where s1 and s2 differ.
238 INT __cdecl
_memicmp( LPCSTR s1
, LPCSTR s2
, DWORD len
)
243 if ((ret
= tolower(*s1
) - tolower(*s2
))) break;
251 /*********************************************************************
255 int __cdecl
_stricmp( LPCSTR str1
, LPCSTR str2
)
257 return strcasecmp( str1
, str2
);
261 /*********************************************************************
262 * _strnicmp (NTDLL.@)
264 int __cdecl
_strnicmp( LPCSTR str1
, LPCSTR str2
, size_t n
)
266 return strncasecmp( str1
, str2
, n
);
270 /*********************************************************************
273 * Convert a string to upper case.
276 * str [I/O] String to convert
279 * str. There is no error return, if str is NULL or invalid, this
280 * function will crash.
282 LPSTR __cdecl
_strupr( LPSTR str
)
285 for ( ; *str
; str
++) *str
= toupper(*str
);
290 /*********************************************************************
293 * Convert a string to lowercase
296 * str [I/O] String to convert
299 * str. There is no error return, if str is NULL or invalid, this
300 * function will crash.
302 LPSTR __cdecl
_strlwr( LPSTR str
)
305 for ( ; *str
; str
++) *str
= tolower(*str
);
310 /*********************************************************************
313 int __cdecl
NTDLL_tolower( int c
)
319 /*********************************************************************
322 int __cdecl
NTDLL_toupper( int c
)
328 /*********************************************************************
331 int __cdecl
NTDLL_isalnum( int c
)
337 /*********************************************************************
340 int __cdecl
NTDLL_isalpha( int c
)
346 /*********************************************************************
349 int __cdecl
NTDLL_iscntrl( int c
)
355 /*********************************************************************
358 int __cdecl
NTDLL_isdigit( int c
)
364 /*********************************************************************
367 int __cdecl
NTDLL_isgraph( int c
)
373 /*********************************************************************
376 int __cdecl
NTDLL_islower( int c
)
382 /*********************************************************************
385 int __cdecl
NTDLL_isprint( int c
)
391 /*********************************************************************
394 int __cdecl
NTDLL_ispunct( int c
)
400 /*********************************************************************
403 int __cdecl
NTDLL_isspace( int c
)
409 /*********************************************************************
412 int __cdecl
NTDLL_isupper( int c
)
418 /*********************************************************************
421 int __cdecl
NTDLL_isxdigit( int c
)
423 return isxdigit( c
);
427 /*********************************************************************
428 * __isascii (NTDLL.@)
430 int CDECL
NTDLL___isascii(int c
)
432 return (unsigned)c
< 0x80;
436 /*********************************************************************
437 * __toascii (NTDLL.@)
439 int CDECL
NTDLL___toascii(int c
)
441 return (unsigned)c
& 0x7f;
445 /*********************************************************************
448 int CDECL
NTDLL___iscsym(int c
)
450 return (c
< 127 && (isalnum(c
) || c
== '_'));
454 /*********************************************************************
455 * __iscsymf (NTDLL.@)
457 int CDECL
NTDLL___iscsymf(int c
)
459 return (c
< 127 && (isalpha(c
) || c
== '_'));
463 /*********************************************************************
466 int CDECL
NTDLL__toupper(int c
)
468 return c
- 0x20; /* sic */
472 /*********************************************************************
475 int CDECL
NTDLL__tolower(int c
)
477 return c
+ 0x20; /* sic */
481 /*********************************************************************
484 LONG __cdecl
NTDLL_strtol( const char *nptr
, char **endptr
, int base
)
486 return strtol( nptr
, endptr
, base
);
490 /*********************************************************************
493 ULONG __cdecl
NTDLL_strtoul( const char *nptr
, char **endptr
, int base
)
495 return strtoul( nptr
, endptr
, base
);
499 /*********************************************************************
502 * Convert an unsigned long integer to a string.
508 * - Converts value to a Nul terminated string which is copied to str.
509 * - The maximum length of the copied str is 33 bytes.
510 * - Does not check if radix is in the range of 2 to 36.
511 * - If str is NULL it crashes, as the native function does.
513 char * __cdecl
_ultoa(
514 ULONG value
, /* [I] Value to be converted */
515 char *str
, /* [O] Destination for the converted value */
516 int radix
) /* [I] Number base for conversion */
526 digit
= value
% radix
;
527 value
= value
/ radix
;
529 *--pos
= '0' + digit
;
531 *--pos
= 'a' + digit
- 10;
533 } while (value
!= 0L);
535 memcpy(str
, pos
, &buffer
[32] - pos
+ 1);
540 /*********************************************************************
543 * Convert a long integer to a string.
549 * - Converts value to a Nul terminated string which is copied to str.
550 * - The maximum length of the copied str is 33 bytes. If radix
551 * is 10 and value is negative, the value is converted with sign.
552 * - Does not check if radix is in the range of 2 to 36.
553 * - If str is NULL it crashes, as the native function does.
555 char * __cdecl
_ltoa(
556 LONG value
, /* [I] Value to be converted */
557 char *str
, /* [O] Destination for the converted value */
558 int radix
) /* [I] Number base for conversion */
566 if (value
< 0 && radix
== 10) {
581 *--pos
= '0' + digit
;
583 *--pos
= 'a' + digit
- 10;
591 memcpy(str
, pos
, &buffer
[32] - pos
+ 1);
596 /*********************************************************************
599 * Converts an integer to a string.
605 * - Converts value to a '\0' terminated string which is copied to str.
606 * - The maximum length of the copied str is 33 bytes. If radix
607 * is 10 and value is negative, the value is converted with sign.
608 * - Does not check if radix is in the range of 2 to 36.
609 * - If str is NULL it crashes, as the native function does.
611 char * __cdecl
_itoa(
612 int value
, /* [I] Value to be converted */
613 char *str
, /* [O] Destination for the converted value */
614 int radix
) /* [I] Number base for conversion */
616 return _ltoa(value
, str
, radix
);
620 /*********************************************************************
623 * Converts a large unsigned integer to a string.
629 * - Converts value to a '\0' terminated string which is copied to str.
630 * - The maximum length of the copied str is 65 bytes.
631 * - Does not check if radix is in the range of 2 to 36.
632 * - If str is NULL it crashes, as the native function does.
634 char * __cdecl
_ui64toa(
635 ULONGLONG value
, /* [I] Value to be converted */
636 char *str
, /* [O] Destination for the converted value */
637 int radix
) /* [I] Number base for conversion */
647 digit
= value
% radix
;
648 value
= value
/ radix
;
650 *--pos
= '0' + digit
;
652 *--pos
= 'a' + digit
- 10;
654 } while (value
!= 0L);
656 memcpy(str
, pos
, &buffer
[64] - pos
+ 1);
661 /*********************************************************************
664 * Converts a large integer to a string.
670 * - Converts value to a Nul terminated string which is copied to str.
671 * - The maximum length of the copied str is 65 bytes. If radix
672 * is 10 and value is negative, the value is converted with sign.
673 * - Does not check if radix is in the range of 2 to 36.
674 * - If str is NULL it crashes, as the native function does.
677 * - The native DLL converts negative values (for base 10) wrong:
678 *| -1 is converted to -18446744073709551615
679 *| -2 is converted to -18446744073709551614
680 *| -9223372036854775807 is converted to -9223372036854775809
681 *| -9223372036854775808 is converted to -9223372036854775808
682 * The native msvcrt _i64toa function and our ntdll _i64toa function
683 * do not have this bug.
685 char * __cdecl
_i64toa(
686 LONGLONG value
, /* [I] Value to be converted */
687 char *str
, /* [O] Destination for the converted value */
688 int radix
) /* [I] Number base for conversion */
696 if (value
< 0 && radix
== 10) {
711 *--pos
= '0' + digit
;
713 *--pos
= 'a' + digit
- 10;
721 memcpy(str
, pos
, &buffer
[64] - pos
+ 1);
726 /*********************************************************************
729 * Convert a string to a large integer.
732 * str [I] String to be converted
735 * Success: The integer value represented by str.
736 * Failure: 0. Note that this cannot be distinguished from a successful
737 * return, if the string contains "0".
740 * - Accepts: {whitespace} [+|-] {digits}
741 * - No check is made for value overflow, only the lower 64 bits are assigned.
742 * - If str is NULL it crashes, as the native function does.
744 LONGLONG __cdecl
_atoi64( const char *str
)
746 ULONGLONG RunningTotal
= 0;
749 while (*str
== ' ' || (*str
>= '\011' && *str
<= '\015')) {
755 } else if (*str
== '-') {
760 while (*str
>= '0' && *str
<= '9') {
761 RunningTotal
= RunningTotal
* 10 + *str
- '0';
765 return bMinus
? -RunningTotal
: RunningTotal
;
769 /*********************************************************************
772 int __cdecl
NTDLL_atoi( const char *nptr
)
774 return _atoi64( nptr
);
778 /*********************************************************************
781 LONG __cdecl
NTDLL_atol( const char *nptr
)
783 return _atoi64( nptr
);
787 /* helper function for *scanf. Returns the value of character c in the
788 * given base, or -1 if the given character is not a digit of the base.
790 static int char2digit( char c
, int base
)
792 if ((c
>= '0' && c
<= '9') && (c
<= '0'+base
-1)) return (c
-'0');
793 if (base
<= 10) return -1;
794 if ((c
>= 'A') && (c
<= 'Z') && (c
<= 'A'+base
-11)) return (c
-'A'+10);
795 if ((c
>= 'a') && (c
<= 'z') && (c
<= 'a'+base
-11)) return (c
-'a'+10);
800 static int NTDLL_vsscanf( const char *str
, const char *format
, __ms_va_list ap
)
802 int rd
= 0, consumed
= 0;
804 if (!*format
) return 0;
806 nch
= (consumed
++, *str
++);
812 if (isspace( *format
))
814 /* skip whitespace */
815 while ((nch
!= '\0') && isspace( nch
))
816 nch
= (consumed
++, *str
++);
818 else if (*format
== '%')
821 BOOLEAN suppress
= 0;
825 BOOLEAN l_prefix
= FALSE
;
826 BOOLEAN L_prefix
= FALSE
;
827 BOOLEAN w_prefix
= FALSE
;
828 BOOLEAN I64_prefix
= FALSE
;
829 BOOLEAN prefix_finished
= FALSE
;
831 /* a leading asterisk means 'suppress assignment of this field' */
837 /* look for width specification */
838 while (isdigit( *format
))
841 width
+= *format
++ - '0';
843 if (width
== 0) width
= -1; /* no width spec seen */
844 /* read prefix (if any) */
845 while (!prefix_finished
)
849 case 'h': h_prefix
++; break;
851 if (*(format
+1) == 'l')
858 case 'w': w_prefix
= TRUE
; break;
859 case 'L': L_prefix
= TRUE
; break;
861 if (*(format
+ 1) == '6' &&
862 *(format
+ 2) == '4')
869 prefix_finished
= TRUE
;
871 if (!prefix_finished
) format
++;
877 case 'P': /* pointer. */
878 if (sizeof(void *) == sizeof(LONGLONG
)) I64_prefix
= TRUE
;
881 case 'X': /* hexadecimal integer. */
884 case 'o': /* octal integer */
887 case 'u': /* unsigned decimal integer */
890 case 'd': /* signed decimal integer */
893 case 'i': /* generic integer */
897 /* read an integer */
899 BOOLEAN negative
= FALSE
;
900 BOOLEAN seendigit
= FALSE
;
901 /* skip initial whitespace */
902 while ((nch
!= '\0') && isspace( nch
))
903 nch
= (consumed
++, *str
++);
905 if (nch
== '-' || nch
== '+')
907 negative
= (nch
== '-');
908 nch
= (consumed
++, *str
++);
909 if (width
> 0) width
--;
911 /* look for leading indication of base */
912 if (width
!= 0 && nch
== '0' && *format
!= 'p' && *format
!= 'P')
914 nch
= (consumed
++, *str
++);
915 if (width
> 0) width
--;
917 if (width
!= 0 && (nch
== 'x' || nch
== 'X'))
923 nch
= (consumed
++, *str
++);
924 if (width
> 0) width
--;
927 } else if (base
== 0)
930 /* format %i without indication of base */
933 /* throw away leading zeros */
934 while (width
!= 0 && nch
== '0')
936 nch
= (consumed
++, *str
++);
937 if (width
> 0) width
--;
940 if (width
!= 0 && char2digit( nch
, base
) != -1)
942 cur
= char2digit( nch
, base
);
943 nch
= (consumed
++, *str
++);
944 if (width
> 0) width
--;
947 /* read until no more digits */
948 while (width
!= 0 && nch
!= '\0' && char2digit( nch
, base
) != -1)
950 cur
= cur
*base
+ char2digit( nch
, base
);
951 nch
= (consumed
++, *str
++);
952 if (width
> 0) width
--;
956 if (!seendigit
) break; /* not a valid number */
960 #define _SET_NUMBER_( type ) *va_arg( ap, type* ) = negative ? -cur : cur
961 if (I64_prefix
) _SET_NUMBER_( LONGLONG
);
962 else if (l_prefix
) _SET_NUMBER_( LONG
);
963 else if (h_prefix
== 1) _SET_NUMBER_( short int );
964 else _SET_NUMBER_( int );
974 long double cur
= 1, expcnt
= 10;
977 BOOLEAN negative
= FALSE
;
978 /*unsigned fpcontrol;*/
981 /* skip initial whitespace */
982 while (nch
!= '\0' && isspace( nch
))
983 nch
= (consumed
++, *str
++);
986 if (nch
== '-' || nch
== '+')
988 negative
= (nch
== '-');
989 if (width
> 0) width
--;
990 if (width
== 0) break;
991 nch
= (consumed
++, *str
++);
994 /* get first digit */
997 if (!isdigit( nch
)) break;
999 nch
= (consumed
++, *str
++);
1000 if (width
> 0) width
--;
1001 /* read until no more digits */
1002 while (width
!= 0 && nch
!= '\0' && isdigit( nch
))
1004 hlp
= d
* 10 + nch
- '0';
1005 nch
= (consumed
++, *str
++);
1006 if (width
> 0) width
--;
1007 if(d
> (ULONGLONG
)-1/10 || hlp
< d
)
1015 while (width
!= 0 && nch
!= '\0' && isdigit( nch
))
1018 nch
= (consumed
++, *str
++);
1019 if (width
> 0) width
--;
1023 d
= 0; /* Fix: .8 -> 0.8 */
1025 /* handle decimals */
1026 if (width
!= 0 && nch
== '.')
1028 nch
= (consumed
++, *str
++);
1029 if (width
> 0) width
--;
1031 while (width
!= 0 && nch
!= '\0' && isdigit( nch
))
1033 hlp
= d
* 10 + nch
- '0';
1034 nch
= (consumed
++, *str
++);
1035 if (width
> 0) width
--;
1036 if(d
> (ULONGLONG
)-1/10 || hlp
< d
)
1042 while (width
!= 0 && nch
!= '\0' && isdigit( nch
))
1044 nch
= (consumed
++, *str
++);
1045 if (width
> 0) width
--;
1049 /* handle exponent */
1050 if (width
!= 0 && (nch
== 'e' || nch
== 'E'))
1052 int sign
= 1, e
= 0;
1054 nch
= (consumed
++, *str
++);
1055 if (width
> 0) width
--;
1056 if (width
!= 0 && (nch
== '+' || nch
== '-'))
1060 nch
= (consumed
++, *str
++);
1061 if (width
> 0) width
--;
1064 /* exponent digits */
1065 while (width
!= 0 && nch
!= '\0' && isdigit( nch
))
1067 if (e
> INT_MAX
/10 || (e
= e
* 10 + nch
- '0') < 0)
1069 nch
= (consumed
++, *str
++);
1070 if (width
> 0) width
--;
1074 if(exp
< 0 && e
< 0 && e
+exp
> 0) exp
= INT_MIN
;
1075 else if(exp
> 0 && e
> 0 && e
+exp
< 0) exp
= INT_MAX
;
1079 /*fpcontrol = _control87(0, 0);
1080 _control87(MSVCRT__EM_DENORMAL|MSVCRT__EM_INVALID|MSVCRT__EM_ZERODIVIDE
1081 |MSVCRT__EM_OVERFLOW|MSVCRT__EM_UNDERFLOW|MSVCRT__EM_INEXACT, 0xffffffff);*/
1086 /* update 'cur' with this exponent. */
1092 expcnt
= expcnt
*expcnt
;
1094 cur
= (negexp
? d
/cur
: d
*cur
);
1096 /*_control87(fpcontrol, 0xffffffff);*/
1101 if (L_prefix
|| l_prefix
) _SET_NUMBER_( double );
1102 else _SET_NUMBER_( float );
1106 /* According to msdn,
1107 * 's' reads a character string in a call to fscanf
1108 * and 'S' a wide character string and vice versa in a
1109 * call to fwscanf. The 'h', 'w' and 'l' prefixes override
1110 * this behaviour. 'h' forces reading char * but 'l' and 'w'
1111 * force reading WCHAR. */
1113 if (w_prefix
|| l_prefix
) goto widecharstring
;
1114 else if (h_prefix
) goto charstring
;
1115 else goto charstring
;
1117 if (w_prefix
|| l_prefix
) goto widecharstring
;
1118 else if (h_prefix
) goto charstring
;
1119 else goto widecharstring
;
1121 { /* read a word into a char */
1122 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1123 char *sptr_beg
= sptr
;
1124 unsigned size
= UINT_MAX
;
1125 /* skip initial whitespace */
1126 while (nch
!= '\0' && isspace( nch
))
1127 nch
= (consumed
++, *str
++);
1128 /* read until whitespace */
1129 while (width
!= 0 && nch
!= '\0' && !isspace( nch
))
1134 if(size
> 1) size
--;
1142 nch
= (consumed
++, *str
++);
1143 if (width
> 0) width
--;
1146 if (st
&& !suppress
) *sptr
= 0;
1150 { /* read a word into a WCHAR * */
1151 WCHAR
*sptr
= suppress
? NULL
: va_arg( ap
, WCHAR
* );
1152 WCHAR
*sptr_beg
= sptr
;
1153 unsigned size
= UINT_MAX
;
1154 /* skip initial whitespace */
1155 while (nch
!= '\0' && isspace( nch
))
1156 nch
= (consumed
++, *str
++);
1157 /* read until whitespace */
1158 while (width
!= 0 && nch
!= '\0' && !isspace( nch
))
1163 if (size
> 1) size
--;
1171 nch
= (consumed
++, *str
++);
1172 if (width
> 0) width
--;
1175 if (st
&& !suppress
) *sptr
= 0;
1178 /* 'c' and 'C work analogously to 's' and 'S' as described
1181 if (w_prefix
|| l_prefix
) goto widecharacter
;
1182 else if (h_prefix
) goto character
;
1183 else goto character
;
1185 if (w_prefix
|| l_prefix
) goto widecharacter
;
1186 else if (h_prefix
) goto character
;
1187 else goto widecharacter
;
1189 { /* read single character into char */
1190 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1191 char *sptr_beg
= sptr
;
1192 unsigned size
= UINT_MAX
;
1193 if (width
== -1) width
= 1;
1194 while (width
&& nch
!= '\0')
1208 nch
= (consumed
++, *str
++);
1213 { /* read single character into a WCHAR */
1214 WCHAR
*sptr
= suppress
? NULL
: va_arg( ap
, WCHAR
* );
1215 WCHAR
*sptr_beg
= sptr
;
1216 unsigned size
= UINT_MAX
;
1217 if (width
== -1) width
= 1;
1218 while (width
&& nch
!= '\0')
1232 nch
= (consumed
++, *str
++);
1240 int *n
= va_arg( ap
, int * );
1243 /* This is an odd one: according to the standard,
1244 * "Execution of a %n directive does not increment the
1245 * assignment count returned at the completion of
1246 * execution" even if it wasn't suppressed with the
1247 * '*' flag. The Corrigendum to the standard seems
1248 * to contradict this (comment out the assignment to
1249 * suppress below if you want to implement these
1250 * alternate semantics) but the windows program I'm
1251 * looking at expects the behavior I've coded here
1252 * (which happens to be what glibc does as well).
1260 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1261 char *sptr_beg
= sptr
;
1263 ULONG Mask
[8] = { 0 };
1264 BOOLEAN invert
= FALSE
; /* Set if we are NOT to find the chars */
1265 unsigned size
= UINT_MAX
;
1267 RtlInitializeBitMap( &bitMask
, Mask
, sizeof(Mask
) * 8 );
1269 /* Read the format */
1278 RtlSetBits( &bitMask
, ']', 1 );
1281 while (*format
&& (*format
!= ']'))
1283 /* According to msdn:
1284 * "Note that %[a-z] and %[z-a] are interpreted as equivalent to %[abcde...z]." */
1285 if ((*format
== '-') && (*(format
+ 1) != ']'))
1287 if ((*(format
- 1)) < *(format
+ 1))
1288 RtlSetBits( &bitMask
, *(format
- 1) +1 , *(format
+ 1) - *(format
- 1) );
1290 RtlSetBits( &bitMask
, *(format
+ 1) , *(format
- 1) - *(format
+ 1) );
1294 RtlSetBits( &bitMask
, *format
, 1 );
1297 /* read until char is not suitable */
1298 while (width
!= 0 && nch
!= '\0')
1302 if(RtlAreBitsSet( &bitMask
, nch
, 1 ))
1304 if (!suppress
) *sptr
++ = nch
;
1311 if (RtlAreBitsClear( &bitMask
, nch
, 1 ))
1313 if (!suppress
) *sptr
++ = nch
;
1319 nch
= (consumed
++, *str
++);
1320 if (width
> 0) width
--;
1321 if(size
> 1) size
--;
1324 if (!suppress
) *sptr_beg
= 0;
1329 if (!suppress
) *sptr
= 0;
1333 /* From spec: "if a percent sign is followed by a character
1334 * that has no meaning as a format-control character, that
1335 * character and the following characters are treated as
1336 * an ordinary sequence of characters, that is, a sequence
1337 * of characters that must match the input. For example,
1338 * to specify that a percent-sign character is to be input,
1340 while (nch
!= '\0' && isspace( nch
))
1341 nch
= (consumed
++, *str
++);
1344 suppress
= TRUE
; /* whoops no field to be read */
1345 st
= 1; /* but we got what we expected */
1346 nch
= (consumed
++, *str
++);
1350 if (st
&& !suppress
) rd
++;
1351 else if (!st
) break;
1353 /* A non-white-space character causes scanf to read, but not store,
1354 * a matching non-white-space character. */
1358 nch
= (consumed
++, *str
++);
1372 /*********************************************************************
1375 int WINAPIV
NTDLL_sscanf( const char *str
, const char *format
, ... )
1378 __ms_va_list valist
;
1379 __ms_va_start( valist
, format
);
1380 ret
= NTDLL_vsscanf( str
, format
, valist
);
1381 __ms_va_end( valist
);
1386 /*********************************************************************
1387 * _splitpath (NTDLL.@)
1389 * Split a path into its component pieces.
1392 * inpath [I] Path to split
1393 * drv [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
1394 * dir [O] Destination for directory component. Should be at least MAX_PATH characters.
1395 * fname [O] Destination for File name component. Should be at least MAX_PATH characters.
1396 * ext [O] Destination for file extension component. Should be at least MAX_PATH characters.
1401 void __cdecl
_splitpath(const char* inpath
, char * drv
, char * dir
,
1402 char* fname
, char * ext
)
1404 const char *p
, *end
;
1406 if (inpath
[0] && inpath
[1] == ':')
1416 else if (drv
) drv
[0] = 0;
1418 /* look for end of directory part */
1420 for (p
= inpath
; *p
; p
++) if (*p
== '/' || *p
== '\\') end
= p
+ 1;
1422 if (end
) /* got a directory */
1426 memcpy( dir
, inpath
, end
- inpath
);
1427 dir
[end
- inpath
] = 0;
1431 else if (dir
) dir
[0] = 0;
1433 /* look for extension: what's after the last dot */
1435 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
1437 if (!end
) end
= p
; /* there's no extension */
1441 memcpy( fname
, inpath
, end
- inpath
);
1442 fname
[end
- inpath
] = 0;
1444 if (ext
) strcpy( ext
, end
);