ntdll/tests: Fix a memory leak (Smatch).
[wine] / dlls / ntdll / string.c
1 /*
2  * NTDLL string functions
3  *
4  * Copyright 2000 Alexandre Julliard
5  * Copyright 2000 Jon Griffiths
6  * Copyright 2003 Thomas Mertes
7  *
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.
12  *
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.
17  *
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
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <ctype.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <search.h>
32
33 #include "windef.h"
34 #include "winternl.h"
35
36
37 /*********************************************************************
38  *                  memchr   (NTDLL.@)
39  */
40 void * __cdecl NTDLL_memchr( const void *ptr, int c, size_t n )
41 {
42     return memchr( ptr, c, n );
43 }
44
45
46 /*********************************************************************
47  *                  memcmp   (NTDLL.@)
48  */
49 int __cdecl NTDLL_memcmp( const void *ptr1, const void *ptr2, size_t n )
50 {
51     return memcmp( ptr1, ptr2, n );
52 }
53
54
55 /*********************************************************************
56  *                  memcpy   (NTDLL.@)
57  *
58  * NOTES
59  *  Behaves like memmove.
60  */
61 void * __cdecl NTDLL_memcpy( void *dst, const void *src, size_t n )
62 {
63     return memmove( dst, src, n );
64 }
65
66
67 /*********************************************************************
68  *                  memmove   (NTDLL.@)
69  */
70 void * __cdecl NTDLL_memmove( void *dst, const void *src, size_t n )
71 {
72     return memmove( dst, src, n );
73 }
74
75
76 /*********************************************************************
77  *                  memset   (NTDLL.@)
78  */
79 void * __cdecl NTDLL_memset( void *dst, int c, size_t n )
80 {
81     return memset( dst, c, n );
82 }
83
84
85 /*********************************************************************
86  *                  strcat   (NTDLL.@)
87  */
88 char * __cdecl NTDLL_strcat( char *dst, const char *src )
89 {
90     return strcat( dst, src );
91 }
92
93
94 /*********************************************************************
95  *                  strchr   (NTDLL.@)
96  */
97 char * __cdecl NTDLL_strchr( const char *str, int c )
98 {
99     return strchr( str, c );
100 }
101
102
103 /*********************************************************************
104  *                  strcmp   (NTDLL.@)
105  */
106 int __cdecl NTDLL_strcmp( const char *str1, const char *str2 )
107 {
108     return strcmp( str1, str2 );
109 }
110
111
112 /*********************************************************************
113  *                  strcpy   (NTDLL.@)
114  */
115 char * __cdecl NTDLL_strcpy( char *dst, const char *src )
116 {
117     return strcpy( dst, src );
118 }
119
120
121 /*********************************************************************
122  *                  strcspn   (NTDLL.@)
123  */
124 size_t __cdecl NTDLL_strcspn( const char *str, const char *reject )
125 {
126     return strcspn( str, reject );
127 }
128
129
130 /*********************************************************************
131  *                  strlen   (NTDLL.@)
132  */
133 size_t __cdecl NTDLL_strlen( const char *str )
134 {
135     return strlen( str );
136 }
137
138
139 /*********************************************************************
140  *                  strncat   (NTDLL.@)
141  */
142 char * __cdecl NTDLL_strncat( char *dst, const char *src, size_t len )
143 {
144     return strncat( dst, src, len );
145 }
146
147
148 /*********************************************************************
149  *                  strncmp   (NTDLL.@)
150  */
151 int __cdecl NTDLL_strncmp( const char *str1, const char *str2, size_t len )
152 {
153     return strncmp( str1, str2, len );
154 }
155
156
157 /*********************************************************************
158  *                  strncpy   (NTDLL.@)
159  */
160 char * __cdecl NTDLL_strncpy( char *dst, const char *src, size_t len )
161 {
162     return strncpy( dst, src, len );
163 }
164
165
166 /*********************************************************************
167  *                  strpbrk   (NTDLL.@)
168  */
169 char * __cdecl NTDLL_strpbrk( const char *str, const char *accept )
170 {
171     return strpbrk( str, accept );
172 }
173
174
175 /*********************************************************************
176  *                  strrchr   (NTDLL.@)
177  */
178 char * __cdecl NTDLL_strrchr( const char *str, int c )
179 {
180     return strrchr( str, c );
181 }
182
183
184 /*********************************************************************
185  *                  strspn   (NTDLL.@)
186  */
187 size_t __cdecl NTDLL_strspn( const char *str, const char *accept )
188 {
189     return strspn( str, accept );
190 }
191
192
193 /*********************************************************************
194  *                  strstr   (NTDLL.@)
195  */
196 char * __cdecl NTDLL_strstr( const char *haystack, const char *needle )
197 {
198     return strstr( haystack, needle );
199 }
200
201
202 /*********************************************************************
203  *                  _memccpy   (NTDLL.@)
204  */
205 void * __cdecl _memccpy( void *dst, const void *src, int c, size_t n )
206 {
207     return memccpy( dst, src, c, n );
208 }
209
210
211 /*********************************************************************
212  *                  _memicmp   (NTDLL.@)
213  *
214  * Compare two blocks of memory as strings, ignoring case.
215  *
216  * PARAMS
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
220  *
221  * RETURNS
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.
224  *
225  * NOTES
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.
228  */
229 INT __cdecl _memicmp( LPCSTR s1, LPCSTR s2, DWORD len )
230 {
231     int ret = 0;
232     while (len--)
233     {
234         if ((ret = tolower(*s1) - tolower(*s2))) break;
235         s1++;
236         s2++;
237     }
238     return ret;
239 }
240
241
242 /*********************************************************************
243  *                  _stricmp   (NTDLL.@)
244  *                  _strcmpi   (NTDLL.@)
245  */
246 int __cdecl _stricmp( LPCSTR str1, LPCSTR str2 )
247 {
248     return strcasecmp( str1, str2 );
249 }
250
251
252 /*********************************************************************
253  *                  _strnicmp   (NTDLL.@)
254  */
255 int __cdecl _strnicmp( LPCSTR str1, LPCSTR str2, size_t n )
256 {
257     return strncasecmp( str1, str2, n );
258 }
259
260
261 /*********************************************************************
262  *                  _strupr   (NTDLL.@)
263  *
264  * Convert a string to upper case.
265  *
266  * PARAMS
267  *  str [I/O] String to convert
268  *
269  * RETURNS
270  *  str. There is no error return, if str is NULL or invalid, this
271  *  function will crash.
272  */
273 LPSTR __cdecl _strupr( LPSTR str )
274 {
275     LPSTR ret = str;
276     for ( ; *str; str++) *str = toupper(*str);
277     return ret;
278 }
279
280
281 /*********************************************************************
282  *                  _strlwr   (NTDLL.@)
283  *
284  * Convert a string to lowercase
285  *
286  * PARAMS
287  *  str [I/O] String to convert
288  *
289  * RETURNS
290  *  str. There is no error return, if str is NULL or invalid, this
291  *  function will crash.
292  */
293 LPSTR __cdecl _strlwr( LPSTR str )
294 {
295     LPSTR ret = str;
296     for ( ; *str; str++) *str = tolower(*str);
297     return ret;
298 }
299
300
301 /*********************************************************************
302  *                  tolower   (NTDLL.@)
303  */
304 int __cdecl NTDLL_tolower( int c )
305 {
306     return tolower( c );
307 }
308
309
310 /*********************************************************************
311  *                  toupper   (NTDLL.@)
312  */
313 int __cdecl NTDLL_toupper( int c )
314 {
315     return toupper( c );
316 }
317
318
319 /*********************************************************************
320  *                  isalnum   (NTDLL.@)
321  */
322 int __cdecl NTDLL_isalnum( int c )
323 {
324     return isalnum( c );
325 }
326
327
328 /*********************************************************************
329  *                  isalpha   (NTDLL.@)
330  */
331 int __cdecl NTDLL_isalpha( int c )
332 {
333     return isalpha( c );
334 }
335
336
337 /*********************************************************************
338  *                  iscntrl   (NTDLL.@)
339  */
340 int __cdecl NTDLL_iscntrl( int c )
341 {
342     return iscntrl( c );
343 }
344
345
346 /*********************************************************************
347  *                  isdigit   (NTDLL.@)
348  */
349 int __cdecl NTDLL_isdigit( int c )
350 {
351     return isdigit( c );
352 }
353
354
355 /*********************************************************************
356  *                  isgraph   (NTDLL.@)
357  */
358 int __cdecl NTDLL_isgraph( int c )
359 {
360     return isgraph( c );
361 }
362
363
364 /*********************************************************************
365  *                  islower   (NTDLL.@)
366  */
367 int __cdecl NTDLL_islower( int c )
368 {
369     return islower( c );
370 }
371
372
373 /*********************************************************************
374  *                  isprint   (NTDLL.@)
375  */
376 int __cdecl NTDLL_isprint( int c )
377 {
378     return isprint( c );
379 }
380
381
382 /*********************************************************************
383  *                  ispunct   (NTDLL.@)
384  */
385 int __cdecl NTDLL_ispunct( int c )
386 {
387     return ispunct( c );
388 }
389
390
391 /*********************************************************************
392  *                  isspace   (NTDLL.@)
393  */
394 int __cdecl NTDLL_isspace( int c )
395 {
396     return isspace( c );
397 }
398
399
400 /*********************************************************************
401  *                  isupper   (NTDLL.@)
402  */
403 int __cdecl NTDLL_isupper( int c )
404 {
405     return isupper( c );
406 }
407
408
409 /*********************************************************************
410  *                  isxdigit   (NTDLL.@)
411  */
412 int __cdecl NTDLL_isxdigit( int c )
413 {
414     return isxdigit( c );
415 }
416
417
418 /*********************************************************************
419  *                  strtol   (NTDLL.@)
420  */
421 LONG __cdecl NTDLL_strtol( const char *nptr, char **endptr, int base )
422 {
423     return strtol( nptr, endptr, base );
424 }
425
426
427 /*********************************************************************
428  *                  strtoul   (NTDLL.@)
429  */
430 ULONG __cdecl NTDLL_strtoul( const char *nptr, char **endptr, int base )
431 {
432     return strtoul( nptr, endptr, base );
433 }
434
435
436 /*********************************************************************
437  *      _ultoa   (NTDLL.@)
438  *
439  * Convert an unsigned long integer to a string.
440  *
441  * RETURNS
442  *  str.
443  *
444  * NOTES
445  *  - Converts value to a Nul terminated string which is copied to str.
446  *  - The maximum length of the copied str is 33 bytes.
447  *  - Does not check if radix is in the range of 2 to 36.
448  *  - If str is NULL it crashes, as the native function does.
449  */
450 char * __cdecl _ultoa(
451     ULONG value,         /* [I] Value to be converted */
452     char *str,           /* [O] Destination for the converted value */
453     int radix)           /* [I] Number base for conversion */
454 {
455     char buffer[33];
456     char *pos;
457     int digit;
458
459     pos = &buffer[32];
460     *pos = '\0';
461
462     do {
463         digit = value % radix;
464         value = value / radix;
465         if (digit < 10) {
466             *--pos = '0' + digit;
467         } else {
468             *--pos = 'a' + digit - 10;
469         } /* if */
470     } while (value != 0L);
471
472     memcpy(str, pos, &buffer[32] - pos + 1);
473     return str;
474 }
475
476
477 /*********************************************************************
478  *      _ltoa   (NTDLL.@)
479  *
480  * Convert a long integer to a string.
481  *
482  * RETURNS
483  *  str.
484  *
485  * NOTES
486  *  - Converts value to a Nul terminated string which is copied to str.
487  *  - The maximum length of the copied str is 33 bytes. If radix
488  *  is 10 and value is negative, the value is converted with sign.
489  *  - Does not check if radix is in the range of 2 to 36.
490  *  - If str is NULL it crashes, as the native function does.
491  */
492 char * __cdecl _ltoa(
493     LONG value, /* [I] Value to be converted */
494     char *str,  /* [O] Destination for the converted value */
495     int radix)  /* [I] Number base for conversion */
496 {
497     ULONG val;
498     int negative;
499     char buffer[33];
500     char *pos;
501     int digit;
502
503     if (value < 0 && radix == 10) {
504         negative = 1;
505         val = -value;
506     } else {
507         negative = 0;
508         val = value;
509     } /* if */
510
511     pos = &buffer[32];
512     *pos = '\0';
513
514     do {
515         digit = val % radix;
516         val = val / radix;
517         if (digit < 10) {
518             *--pos = '0' + digit;
519         } else {
520             *--pos = 'a' + digit - 10;
521         } /* if */
522     } while (val != 0L);
523
524     if (negative) {
525         *--pos = '-';
526     } /* if */
527
528     memcpy(str, pos, &buffer[32] - pos + 1);
529     return str;
530 }
531
532
533 /*********************************************************************
534  *      _itoa    (NTDLL.@)
535  *
536  * Converts an integer to a string.
537  *
538  * RETURNS
539  *  str.
540  *
541  * NOTES
542  *  - Converts value to a '\0' terminated string which is copied to str.
543  *  - The maximum length of the copied str is 33 bytes. If radix
544  *  is 10 and value is negative, the value is converted with sign.
545  *  - Does not check if radix is in the range of 2 to 36.
546  *  - If str is NULL it crashes, as the native function does.
547  */
548 char * __cdecl _itoa(
549     int value, /* [I] Value to be converted */
550     char *str, /* [O] Destination for the converted value */
551     int radix) /* [I] Number base for conversion */
552 {
553     return _ltoa(value, str, radix);
554 }
555
556
557 /*********************************************************************
558  *      _ui64toa   (NTDLL.@)
559  *
560  * Converts a large unsigned integer to a string.
561  *
562  * RETURNS
563  *  str.
564  *
565  * NOTES
566  *  - Converts value to a '\0' terminated string which is copied to str.
567  *  - The maximum length of the copied str is 65 bytes.
568  *  - Does not check if radix is in the range of 2 to 36.
569  *  - If str is NULL it crashes, as the native function does.
570  */
571 char * __cdecl _ui64toa(
572     ULONGLONG value, /* [I] Value to be converted */
573     char *str,       /* [O] Destination for the converted value */
574     int radix)       /* [I] Number base for conversion */
575 {
576     char buffer[65];
577     char *pos;
578     int digit;
579
580     pos = &buffer[64];
581     *pos = '\0';
582
583     do {
584         digit = value % radix;
585         value = value / radix;
586         if (digit < 10) {
587             *--pos = '0' + digit;
588         } else {
589             *--pos = 'a' + digit - 10;
590         } /* if */
591     } while (value != 0L);
592
593     memcpy(str, pos, &buffer[64] - pos + 1);
594     return str;
595 }
596
597
598 /*********************************************************************
599  *      _i64toa   (NTDLL.@)
600  *
601  * Converts a large integer to a string.
602  *
603  * RETURNS
604  *  str.
605  *
606  * NOTES
607  *  - Converts value to a Nul terminated string which is copied to str.
608  *  - The maximum length of the copied str is 65 bytes. If radix
609  *  is 10 and value is negative, the value is converted with sign.
610  *  - Does not check if radix is in the range of 2 to 36.
611  *  - If str is NULL it crashes, as the native function does.
612  *
613  * DIFFERENCES
614  * - The native DLL converts negative values (for base 10) wrong:
615  *|                     -1 is converted to -18446744073709551615
616  *|                     -2 is converted to -18446744073709551614
617  *|   -9223372036854775807 is converted to  -9223372036854775809
618  *|   -9223372036854775808 is converted to  -9223372036854775808
619  *   The native msvcrt _i64toa function and our ntdll _i64toa function
620  *   do not have this bug.
621  */
622 char * __cdecl _i64toa(
623     LONGLONG value, /* [I] Value to be converted */
624     char *str,      /* [O] Destination for the converted value */
625     int radix)      /* [I] Number base for conversion */
626 {
627     ULONGLONG val;
628     int negative;
629     char buffer[65];
630     char *pos;
631     int digit;
632
633     if (value < 0 && radix == 10) {
634         negative = 1;
635         val = -value;
636     } else {
637         negative = 0;
638         val = value;
639     } /* if */
640
641     pos = &buffer[64];
642     *pos = '\0';
643
644     do {
645         digit = val % radix;
646         val = val / radix;
647         if (digit < 10) {
648             *--pos = '0' + digit;
649         } else {
650             *--pos = 'a' + digit - 10;
651         } /* if */
652     } while (val != 0L);
653
654     if (negative) {
655         *--pos = '-';
656     } /* if */
657
658     memcpy(str, pos, &buffer[64] - pos + 1);
659     return str;
660 }
661
662
663 /*********************************************************************
664  *      _atoi64   (NTDLL.@)
665  *
666  * Convert a string to a large integer.
667  *
668  * PARAMS
669  *  str [I] String to be converted
670  *
671  * RETURNS
672  *  Success: The integer value represented by str.
673  *  Failure: 0. Note that this cannot be distinguished from a successful
674  *           return, if the string contains "0".
675  *
676  * NOTES
677  *  - Accepts: {whitespace} [+|-] {digits}
678  *  - No check is made for value overflow, only the lower 64 bits are assigned.
679  *  - If str is NULL it crashes, as the native function does.
680  */
681 LONGLONG __cdecl _atoi64( const char *str )
682 {
683     ULONGLONG RunningTotal = 0;
684     char bMinus = 0;
685
686     while (*str == ' ' || (*str >= '\011' && *str <= '\015')) {
687         str++;
688     } /* while */
689
690     if (*str == '+') {
691         str++;
692     } else if (*str == '-') {
693         bMinus = 1;
694         str++;
695     } /* if */
696
697     while (*str >= '0' && *str <= '9') {
698         RunningTotal = RunningTotal * 10 + *str - '0';
699         str++;
700     } /* while */
701
702     return bMinus ? -RunningTotal : RunningTotal;
703 }
704
705
706 /*********************************************************************
707  *                  atoi   (NTDLL.@)
708  */
709 int __cdecl NTDLL_atoi( const char *nptr )
710 {
711     return _atoi64( nptr );
712 }
713
714
715 /*********************************************************************
716  *                  atol   (NTDLL.@)
717  */
718 LONG __cdecl NTDLL_atol( const char *nptr )
719 {
720     return _atoi64( nptr );
721 }
722
723
724 /*********************************************************************
725  *                  sscanf   (NTDLL.@)
726  */
727 int __cdecl NTDLL_sscanf( const char *str, const char *format, ... )
728 {
729     int ret;
730     va_list valist;
731     va_start( valist, format );
732     ret = vsscanf( str, format, valist );
733     va_end( valist );
734     return ret;
735 }
736
737
738 /*********************************************************************
739  *              _splitpath (NTDLL.@)
740  *
741  * Split a path into its component pieces.
742  *
743  * PARAMS
744  *  inpath [I] Path to split
745  *  drv    [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
746  *  dir    [O] Destination for directory component. Should be at least MAX_PATH characters.
747  *  fname  [O] Destination for File name component. Should be at least MAX_PATH characters.
748  *  ext    [O] Destination for file extension component. Should be at least MAX_PATH characters.
749  *
750  * RETURNS
751  *  Nothing.
752  */
753 void __cdecl _splitpath(const char* inpath, char * drv, char * dir,
754                         char* fname, char * ext )
755 {
756     const char *p, *end;
757
758     if (inpath[0] && inpath[1] == ':')
759     {
760         if (drv)
761         {
762             drv[0] = inpath[0];
763             drv[1] = inpath[1];
764             drv[2] = 0;
765         }
766         inpath += 2;
767     }
768     else if (drv) drv[0] = 0;
769
770     /* look for end of directory part */
771     end = NULL;
772     for (p = inpath; *p; p++) if (*p == '/' || *p == '\\') end = p + 1;
773
774     if (end)  /* got a directory */
775     {
776         if (dir)
777         {
778             memcpy( dir, inpath, end - inpath );
779             dir[end - inpath] = 0;
780         }
781         inpath = end;
782     }
783     else if (dir) dir[0] = 0;
784
785     /* look for extension: what's after the last dot */
786     end = NULL;
787     for (p = inpath; *p; p++) if (*p == '.') end = p;
788
789     if (!end) end = p; /* there's no extension */
790
791     if (fname)
792     {
793         memcpy( fname, inpath, end - inpath );
794         fname[end - inpath] = 0;
795     }
796     if (ext) strcpy( ext, end );
797 }