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 char * __cdecl
NTDLL_strpbrk( const char *str
, const char *accept
)
171 return strpbrk( str
, accept
);
175 /*********************************************************************
178 char * __cdecl
NTDLL_strrchr( const char *str
, int c
)
180 return strrchr( str
, c
);
184 /*********************************************************************
187 size_t __cdecl
NTDLL_strspn( const char *str
, const char *accept
)
189 return strspn( str
, accept
);
193 /*********************************************************************
196 char * __cdecl
NTDLL_strstr( const char *haystack
, const char *needle
)
198 return strstr( haystack
, needle
);
202 /*********************************************************************
205 void * __cdecl
_memccpy( void *dst
, const void *src
, int c
, size_t n
)
207 return memccpy( dst
, src
, c
, n
);
211 /*********************************************************************
214 * Compare two blocks of memory as strings, ignoring case.
217 * s1 [I] First string to compare to s2
218 * s2 [I] Second string to compare to s1
219 * len [I] Number of bytes to compare
222 * An integer less than, equal to, or greater than zero indicating that
223 * s1 is less than, equal to or greater than s2 respectively.
226 * Any Nul characters in s1 or s2 are ignored. This function always
227 * compares up to len bytes or the first place where s1 and s2 differ.
229 INT __cdecl
_memicmp( LPCSTR s1
, LPCSTR s2
, DWORD len
)
234 if ((ret
= tolower(*s1
) - tolower(*s2
))) break;
242 /*********************************************************************
246 int __cdecl
_stricmp( LPCSTR str1
, LPCSTR str2
)
248 return strcasecmp( str1
, str2
);
252 /*********************************************************************
253 * _strnicmp (NTDLL.@)
255 int __cdecl
_strnicmp( LPCSTR str1
, LPCSTR str2
, size_t n
)
257 return strncasecmp( str1
, str2
, n
);
261 /*********************************************************************
264 * Convert a string to upper case.
267 * str [I/O] String to convert
270 * str. There is no error return, if str is NULL or invalid, this
271 * function will crash.
273 LPSTR __cdecl
_strupr( LPSTR str
)
276 for ( ; *str
; str
++) *str
= toupper(*str
);
281 /*********************************************************************
284 * Convert a string to lowercase
287 * str [I/O] String to convert
290 * str. There is no error return, if str is NULL or invalid, this
291 * function will crash.
293 LPSTR __cdecl
_strlwr( LPSTR str
)
296 for ( ; *str
; str
++) *str
= tolower(*str
);
301 /*********************************************************************
304 int __cdecl
NTDLL_tolower( int c
)
310 /*********************************************************************
313 int __cdecl
NTDLL_toupper( int c
)
319 /*********************************************************************
322 int __cdecl
NTDLL_isalnum( int c
)
328 /*********************************************************************
331 int __cdecl
NTDLL_isalpha( int c
)
337 /*********************************************************************
340 int __cdecl
NTDLL_iscntrl( int c
)
346 /*********************************************************************
349 int __cdecl
NTDLL_isdigit( int c
)
355 /*********************************************************************
358 int __cdecl
NTDLL_isgraph( int c
)
364 /*********************************************************************
367 int __cdecl
NTDLL_islower( int c
)
373 /*********************************************************************
376 int __cdecl
NTDLL_isprint( int c
)
382 /*********************************************************************
385 int __cdecl
NTDLL_ispunct( int c
)
391 /*********************************************************************
394 int __cdecl
NTDLL_isspace( int c
)
400 /*********************************************************************
403 int __cdecl
NTDLL_isupper( int c
)
409 /*********************************************************************
412 int __cdecl
NTDLL_isxdigit( int c
)
414 return isxdigit( c
);
418 /*********************************************************************
419 * __isascii (NTDLL.@)
421 int CDECL
NTDLL___isascii(int c
)
423 return (unsigned)c
< 0x80;
427 /*********************************************************************
428 * __toascii (NTDLL.@)
430 int CDECL
NTDLL___toascii(int c
)
432 return (unsigned)c
& 0x7f;
436 /*********************************************************************
439 int CDECL
NTDLL___iscsym(int c
)
441 return (c
< 127 && (isalnum(c
) || c
== '_'));
445 /*********************************************************************
446 * __iscsymf (NTDLL.@)
448 int CDECL
NTDLL___iscsymf(int c
)
450 return (c
< 127 && (isalpha(c
) || c
== '_'));
454 /*********************************************************************
457 int CDECL
NTDLL__toupper(int c
)
459 return c
- 0x20; /* sic */
463 /*********************************************************************
466 int CDECL
NTDLL__tolower(int c
)
468 return c
+ 0x20; /* sic */
472 /*********************************************************************
475 LONG __cdecl
NTDLL_strtol( const char *nptr
, char **endptr
, int base
)
477 return strtol( nptr
, endptr
, base
);
481 /*********************************************************************
484 ULONG __cdecl
NTDLL_strtoul( const char *nptr
, char **endptr
, int base
)
486 return strtoul( nptr
, endptr
, base
);
490 /*********************************************************************
493 * Convert an unsigned long integer to a string.
499 * - Converts value to a Nul terminated string which is copied to str.
500 * - The maximum length of the copied str is 33 bytes.
501 * - Does not check if radix is in the range of 2 to 36.
502 * - If str is NULL it crashes, as the native function does.
504 char * __cdecl
_ultoa(
505 ULONG value
, /* [I] Value to be converted */
506 char *str
, /* [O] Destination for the converted value */
507 int radix
) /* [I] Number base for conversion */
517 digit
= value
% radix
;
518 value
= value
/ radix
;
520 *--pos
= '0' + digit
;
522 *--pos
= 'a' + digit
- 10;
524 } while (value
!= 0L);
526 memcpy(str
, pos
, &buffer
[32] - pos
+ 1);
531 /*********************************************************************
534 * Convert a long integer to a string.
540 * - Converts value to a Nul terminated string which is copied to str.
541 * - The maximum length of the copied str is 33 bytes. If radix
542 * is 10 and value is negative, the value is converted with sign.
543 * - Does not check if radix is in the range of 2 to 36.
544 * - If str is NULL it crashes, as the native function does.
546 char * __cdecl
_ltoa(
547 LONG value
, /* [I] Value to be converted */
548 char *str
, /* [O] Destination for the converted value */
549 int radix
) /* [I] Number base for conversion */
557 if (value
< 0 && radix
== 10) {
572 *--pos
= '0' + digit
;
574 *--pos
= 'a' + digit
- 10;
582 memcpy(str
, pos
, &buffer
[32] - pos
+ 1);
587 /*********************************************************************
590 * Converts an integer to a string.
596 * - Converts value to a '\0' terminated string which is copied to str.
597 * - The maximum length of the copied str is 33 bytes. If radix
598 * is 10 and value is negative, the value is converted with sign.
599 * - Does not check if radix is in the range of 2 to 36.
600 * - If str is NULL it crashes, as the native function does.
602 char * __cdecl
_itoa(
603 int value
, /* [I] Value to be converted */
604 char *str
, /* [O] Destination for the converted value */
605 int radix
) /* [I] Number base for conversion */
607 return _ltoa(value
, str
, radix
);
611 /*********************************************************************
614 * Converts a large unsigned integer to a string.
620 * - Converts value to a '\0' terminated string which is copied to str.
621 * - The maximum length of the copied str is 65 bytes.
622 * - Does not check if radix is in the range of 2 to 36.
623 * - If str is NULL it crashes, as the native function does.
625 char * __cdecl
_ui64toa(
626 ULONGLONG value
, /* [I] Value to be converted */
627 char *str
, /* [O] Destination for the converted value */
628 int radix
) /* [I] Number base for conversion */
638 digit
= value
% radix
;
639 value
= value
/ radix
;
641 *--pos
= '0' + digit
;
643 *--pos
= 'a' + digit
- 10;
645 } while (value
!= 0L);
647 memcpy(str
, pos
, &buffer
[64] - pos
+ 1);
652 /*********************************************************************
655 * Converts a large integer to a string.
661 * - Converts value to a Nul terminated string which is copied to str.
662 * - The maximum length of the copied str is 65 bytes. If radix
663 * is 10 and value is negative, the value is converted with sign.
664 * - Does not check if radix is in the range of 2 to 36.
665 * - If str is NULL it crashes, as the native function does.
668 * - The native DLL converts negative values (for base 10) wrong:
669 *| -1 is converted to -18446744073709551615
670 *| -2 is converted to -18446744073709551614
671 *| -9223372036854775807 is converted to -9223372036854775809
672 *| -9223372036854775808 is converted to -9223372036854775808
673 * The native msvcrt _i64toa function and our ntdll _i64toa function
674 * do not have this bug.
676 char * __cdecl
_i64toa(
677 LONGLONG value
, /* [I] Value to be converted */
678 char *str
, /* [O] Destination for the converted value */
679 int radix
) /* [I] Number base for conversion */
687 if (value
< 0 && radix
== 10) {
702 *--pos
= '0' + digit
;
704 *--pos
= 'a' + digit
- 10;
712 memcpy(str
, pos
, &buffer
[64] - pos
+ 1);
717 /*********************************************************************
720 * Convert a string to a large integer.
723 * str [I] String to be converted
726 * Success: The integer value represented by str.
727 * Failure: 0. Note that this cannot be distinguished from a successful
728 * return, if the string contains "0".
731 * - Accepts: {whitespace} [+|-] {digits}
732 * - No check is made for value overflow, only the lower 64 bits are assigned.
733 * - If str is NULL it crashes, as the native function does.
735 LONGLONG __cdecl
_atoi64( const char *str
)
737 ULONGLONG RunningTotal
= 0;
740 while (*str
== ' ' || (*str
>= '\011' && *str
<= '\015')) {
746 } else if (*str
== '-') {
751 while (*str
>= '0' && *str
<= '9') {
752 RunningTotal
= RunningTotal
* 10 + *str
- '0';
756 return bMinus
? -RunningTotal
: RunningTotal
;
760 /*********************************************************************
763 int __cdecl
NTDLL_atoi( const char *nptr
)
765 return _atoi64( nptr
);
769 /*********************************************************************
772 LONG __cdecl
NTDLL_atol( const char *nptr
)
774 return _atoi64( nptr
);
778 /* helper function for *scanf. Returns the value of character c in the
779 * given base, or -1 if the given character is not a digit of the base.
781 static int char2digit( char c
, int base
)
783 if ((c
>= '0' && c
<= '9') && (c
<= '0'+base
-1)) return (c
-'0');
784 if (base
<= 10) return -1;
785 if ((c
>= 'A') && (c
<= 'Z') && (c
<= 'A'+base
-11)) return (c
-'A'+10);
786 if ((c
>= 'a') && (c
<= 'z') && (c
<= 'a'+base
-11)) return (c
-'a'+10);
791 static int NTDLL_vsscanf( const char *str
, const char *format
, __ms_va_list ap
)
793 int rd
= 0, consumed
= 0;
795 if (!*format
) return 0;
797 nch
= (consumed
++, *str
++);
803 if (isspace( *format
))
805 /* skip whitespace */
806 while ((nch
!= '\0') && isspace( nch
))
807 nch
= (consumed
++, *str
++);
809 else if (*format
== '%')
812 BOOLEAN suppress
= 0;
816 BOOLEAN l_prefix
= FALSE
;
817 BOOLEAN L_prefix
= FALSE
;
818 BOOLEAN w_prefix
= FALSE
;
819 BOOLEAN I64_prefix
= FALSE
;
820 BOOLEAN prefix_finished
= FALSE
;
822 /* a leading asterisk means 'suppress assignment of this field' */
828 /* look for width specification */
829 while (isdigit( *format
))
832 width
+= *format
++ - '0';
834 if (width
== 0) width
= -1; /* no width spec seen */
835 /* read prefix (if any) */
836 while (!prefix_finished
)
840 case 'h': h_prefix
++; break;
842 if (*(format
+1) == 'l')
849 case 'w': w_prefix
= TRUE
; break;
850 case 'L': L_prefix
= TRUE
; break;
852 if (*(format
+ 1) == '6' &&
853 *(format
+ 2) == '4')
860 prefix_finished
= TRUE
;
862 if (!prefix_finished
) format
++;
868 case 'P': /* pointer. */
869 if (sizeof(void *) == sizeof(LONGLONG
)) I64_prefix
= TRUE
;
872 case 'X': /* hexadecimal integer. */
875 case 'o': /* octal integer */
878 case 'u': /* unsigned decimal integer */
881 case 'd': /* signed decimal integer */
884 case 'i': /* generic integer */
888 /* read an integer */
890 BOOLEAN negative
= FALSE
;
891 BOOLEAN seendigit
= FALSE
;
892 /* skip initial whitespace */
893 while ((nch
!= '\0') && isspace( nch
))
894 nch
= (consumed
++, *str
++);
896 if (nch
== '-' || nch
== '+')
898 negative
= (nch
== '-');
899 nch
= (consumed
++, *str
++);
900 if (width
> 0) width
--;
902 /* look for leading indication of base */
903 if (width
!= 0 && nch
== '0' && *format
!= 'p' && *format
!= 'P')
905 nch
= (consumed
++, *str
++);
906 if (width
> 0) width
--;
908 if (width
!= 0 && (nch
== 'x' || nch
== 'X'))
914 nch
= (consumed
++, *str
++);
915 if (width
> 0) width
--;
918 } else if (base
== 0)
921 /* format %i without indication of base */
924 /* throw away leading zeros */
925 while (width
!= 0 && nch
== '0')
927 nch
= (consumed
++, *str
++);
928 if (width
> 0) width
--;
931 if (width
!= 0 && char2digit( nch
, base
) != -1)
933 cur
= char2digit( nch
, base
);
934 nch
= (consumed
++, *str
++);
935 if (width
> 0) width
--;
938 /* read until no more digits */
939 while (width
!= 0 && nch
!= '\0' && char2digit( nch
, base
) != -1)
941 cur
= cur
*base
+ char2digit( nch
, base
);
942 nch
= (consumed
++, *str
++);
943 if (width
> 0) width
--;
947 if (!seendigit
) break; /* not a valid number */
951 #define _SET_NUMBER_( type ) *va_arg( ap, type* ) = negative ? -cur : cur
952 if (I64_prefix
) _SET_NUMBER_( LONGLONG
);
953 else if (l_prefix
) _SET_NUMBER_( LONG
);
954 else if (h_prefix
== 1) _SET_NUMBER_( short int );
955 else _SET_NUMBER_( int );
965 long double cur
= 1, expcnt
= 10;
968 BOOLEAN negative
= FALSE
;
969 /*unsigned fpcontrol;*/
972 /* skip initial whitespace */
973 while (nch
!= '\0' && isspace( nch
))
974 nch
= (consumed
++, *str
++);
977 if (nch
== '-' || nch
== '+')
979 negative
= (nch
== '-');
980 if (width
> 0) width
--;
981 if (width
== 0) break;
982 nch
= (consumed
++, *str
++);
985 /* get first digit */
988 if (!isdigit( nch
)) break;
990 nch
= (consumed
++, *str
++);
991 if (width
> 0) width
--;
992 /* read until no more digits */
993 while (width
!= 0 && nch
!= '\0' && isdigit( nch
))
995 hlp
= d
* 10 + nch
- '0';
996 nch
= (consumed
++, *str
++);
997 if (width
> 0) width
--;
998 if(d
> (ULONGLONG
)-1/10 || hlp
< d
)
1006 while (width
!= 0 && nch
!= '\0' && isdigit( nch
))
1009 nch
= (consumed
++, *str
++);
1010 if (width
> 0) width
--;
1014 d
= 0; /* Fix: .8 -> 0.8 */
1016 /* handle decimals */
1017 if (width
!= 0 && nch
== '.')
1019 nch
= (consumed
++, *str
++);
1020 if (width
> 0) width
--;
1022 while (width
!= 0 && nch
!= '\0' && isdigit( nch
))
1024 hlp
= d
* 10 + nch
- '0';
1025 nch
= (consumed
++, *str
++);
1026 if (width
> 0) width
--;
1027 if(d
> (ULONGLONG
)-1/10 || hlp
< d
)
1033 while (width
!= 0 && nch
!= '\0' && isdigit( nch
))
1035 nch
= (consumed
++, *str
++);
1036 if (width
> 0) width
--;
1040 /* handle exponent */
1041 if (width
!= 0 && (nch
== 'e' || nch
== 'E'))
1043 int sign
= 1, e
= 0;
1045 nch
= (consumed
++, *str
++);
1046 if (width
> 0) width
--;
1047 if (width
!= 0 && (nch
== '+' || nch
== '-'))
1051 nch
= (consumed
++, *str
++);
1052 if (width
> 0) width
--;
1055 /* exponent digits */
1056 while (width
!= 0 && nch
!= '\0' && isdigit( nch
))
1058 if (e
> INT_MAX
/10 || (e
= e
* 10 + nch
- '0') < 0)
1060 nch
= (consumed
++, *str
++);
1061 if (width
> 0) width
--;
1065 if(exp
< 0 && e
< 0 && e
+exp
> 0) exp
= INT_MIN
;
1066 else if(exp
> 0 && e
> 0 && e
+exp
< 0) exp
= INT_MAX
;
1070 /*fpcontrol = _control87(0, 0);
1071 _control87(MSVCRT__EM_DENORMAL|MSVCRT__EM_INVALID|MSVCRT__EM_ZERODIVIDE
1072 |MSVCRT__EM_OVERFLOW|MSVCRT__EM_UNDERFLOW|MSVCRT__EM_INEXACT, 0xffffffff);*/
1077 /* update 'cur' with this exponent. */
1083 expcnt
= expcnt
*expcnt
;
1085 cur
= (negexp
? d
/cur
: d
*cur
);
1087 /*_control87(fpcontrol, 0xffffffff);*/
1092 if (L_prefix
|| l_prefix
) _SET_NUMBER_( double );
1093 else _SET_NUMBER_( float );
1097 /* According to msdn,
1098 * 's' reads a character string in a call to fscanf
1099 * and 'S' a wide character string and vice versa in a
1100 * call to fwscanf. The 'h', 'w' and 'l' prefixes override
1101 * this behaviour. 'h' forces reading char * but 'l' and 'w'
1102 * force reading WCHAR. */
1104 if (w_prefix
|| l_prefix
) goto widecharstring
;
1105 else if (h_prefix
) goto charstring
;
1106 else goto charstring
;
1108 if (w_prefix
|| l_prefix
) goto widecharstring
;
1109 else if (h_prefix
) goto charstring
;
1110 else goto widecharstring
;
1112 { /* read a word into a char */
1113 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1114 char *sptr_beg
= sptr
;
1115 unsigned size
= UINT_MAX
;
1116 /* skip initial whitespace */
1117 while (nch
!= '\0' && isspace( nch
))
1118 nch
= (consumed
++, *str
++);
1119 /* read until whitespace */
1120 while (width
!= 0 && nch
!= '\0' && !isspace( nch
))
1125 if(size
> 1) size
--;
1133 nch
= (consumed
++, *str
++);
1134 if (width
> 0) width
--;
1137 if (st
&& !suppress
) *sptr
= 0;
1141 { /* read a word into a WCHAR * */
1142 WCHAR
*sptr
= suppress
? NULL
: va_arg( ap
, WCHAR
* );
1143 WCHAR
*sptr_beg
= sptr
;
1144 unsigned size
= UINT_MAX
;
1145 /* skip initial whitespace */
1146 while (nch
!= '\0' && isspace( nch
))
1147 nch
= (consumed
++, *str
++);
1148 /* read until whitespace */
1149 while (width
!= 0 && nch
!= '\0' && !isspace( nch
))
1154 if (size
> 1) size
--;
1162 nch
= (consumed
++, *str
++);
1163 if (width
> 0) width
--;
1166 if (st
&& !suppress
) *sptr
= 0;
1169 /* 'c' and 'C work analogously to 's' and 'S' as described
1172 if (w_prefix
|| l_prefix
) goto widecharacter
;
1173 else if (h_prefix
) goto character
;
1174 else goto character
;
1176 if (w_prefix
|| l_prefix
) goto widecharacter
;
1177 else if (h_prefix
) goto character
;
1178 else goto widecharacter
;
1180 { /* read single character into char */
1181 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1182 char *sptr_beg
= sptr
;
1183 unsigned size
= UINT_MAX
;
1184 if (width
== -1) width
= 1;
1185 while (width
&& nch
!= '\0')
1199 nch
= (consumed
++, *str
++);
1204 { /* read single character into a WCHAR */
1205 WCHAR
*sptr
= suppress
? NULL
: va_arg( ap
, WCHAR
* );
1206 WCHAR
*sptr_beg
= sptr
;
1207 unsigned size
= UINT_MAX
;
1208 if (width
== -1) width
= 1;
1209 while (width
&& nch
!= '\0')
1223 nch
= (consumed
++, *str
++);
1231 int *n
= va_arg( ap
, int * );
1234 /* This is an odd one: according to the standard,
1235 * "Execution of a %n directive does not increment the
1236 * assignment count returned at the completion of
1237 * execution" even if it wasn't suppressed with the
1238 * '*' flag. The Corrigendum to the standard seems
1239 * to contradict this (comment out the assignment to
1240 * suppress below if you want to implement these
1241 * alternate semantics) but the windows program I'm
1242 * looking at expects the behavior I've coded here
1243 * (which happens to be what glibc does as well).
1251 char *sptr
= suppress
? NULL
: va_arg( ap
, char * );
1252 char *sptr_beg
= sptr
;
1254 ULONG Mask
[8] = { 0 };
1255 BOOLEAN invert
= FALSE
; /* Set if we are NOT to find the chars */
1256 unsigned size
= UINT_MAX
;
1258 RtlInitializeBitMap( &bitMask
, Mask
, sizeof(Mask
) * 8 );
1260 /* Read the format */
1269 RtlSetBits( &bitMask
, ']', 1 );
1272 while (*format
&& (*format
!= ']'))
1274 /* According to msdn:
1275 * "Note that %[a-z] and %[z-a] are interpreted as equivalent to %[abcde...z]." */
1276 if ((*format
== '-') && (*(format
+ 1) != ']'))
1278 if ((*(format
- 1)) < *(format
+ 1))
1279 RtlSetBits( &bitMask
, *(format
- 1) +1 , *(format
+ 1) - *(format
- 1) );
1281 RtlSetBits( &bitMask
, *(format
+ 1) , *(format
- 1) - *(format
+ 1) );
1285 RtlSetBits( &bitMask
, *format
, 1 );
1288 /* read until char is not suitable */
1289 while (width
!= 0 && nch
!= '\0')
1293 if(RtlAreBitsSet( &bitMask
, nch
, 1 ))
1295 if (!suppress
) *sptr
++ = nch
;
1302 if (RtlAreBitsClear( &bitMask
, nch
, 1 ))
1304 if (!suppress
) *sptr
++ = nch
;
1310 nch
= (consumed
++, *str
++);
1311 if (width
> 0) width
--;
1312 if(size
> 1) size
--;
1315 if (!suppress
) *sptr_beg
= 0;
1320 if (!suppress
) *sptr
= 0;
1324 /* From spec: "if a percent sign is followed by a character
1325 * that has no meaning as a format-control character, that
1326 * character and the following characters are treated as
1327 * an ordinary sequence of characters, that is, a sequence
1328 * of characters that must match the input. For example,
1329 * to specify that a percent-sign character is to be input,
1331 while (nch
!= '\0' && isspace( nch
))
1332 nch
= (consumed
++, *str
++);
1335 suppress
= TRUE
; /* whoops no field to be read */
1336 st
= 1; /* but we got what we expected */
1337 nch
= (consumed
++, *str
++);
1341 if (st
&& !suppress
) rd
++;
1342 else if (!st
) break;
1344 /* A non-white-space character causes scanf to read, but not store,
1345 * a matching non-white-space character. */
1349 nch
= (consumed
++, *str
++);
1363 /*********************************************************************
1366 int WINAPIV
NTDLL_sscanf( const char *str
, const char *format
, ... )
1369 __ms_va_list valist
;
1370 __ms_va_start( valist
, format
);
1371 ret
= NTDLL_vsscanf( str
, format
, valist
);
1372 __ms_va_end( valist
);
1377 /*********************************************************************
1378 * _splitpath (NTDLL.@)
1380 * Split a path into its component pieces.
1383 * inpath [I] Path to split
1384 * drv [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
1385 * dir [O] Destination for directory component. Should be at least MAX_PATH characters.
1386 * fname [O] Destination for File name component. Should be at least MAX_PATH characters.
1387 * ext [O] Destination for file extension component. Should be at least MAX_PATH characters.
1392 void __cdecl
_splitpath(const char* inpath
, char * drv
, char * dir
,
1393 char* fname
, char * ext
)
1395 const char *p
, *end
;
1397 if (inpath
[0] && inpath
[1] == ':')
1407 else if (drv
) drv
[0] = 0;
1409 /* look for end of directory part */
1411 for (p
= inpath
; *p
; p
++) if (*p
== '/' || *p
== '\\') end
= p
+ 1;
1413 if (end
) /* got a directory */
1417 memcpy( dir
, inpath
, end
- inpath
);
1418 dir
[end
- inpath
] = 0;
1422 else if (dir
) dir
[0] = 0;
1424 /* look for extension: what's after the last dot */
1426 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
1428 if (!end
) end
= p
; /* there's no extension */
1432 memcpy( fname
, inpath
, end
- inpath
);
1433 fname
[end
- inpath
] = 0;
1435 if (ext
) strcpy( ext
, end
);