Remove unneeded headers to reduce unneeded rebuilds.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24
25 #include <ctype.h>
26 #include <stdarg.h>
27 #include <string.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winreg.h"
32 #include "winternl.h"
33
34
35 /*********************************************************************
36  *                  _memicmp   (NTDLL.@)
37  *
38  * Compare two blocks of memory as strings, ignoring case.
39  *
40  * PARAMS
41  *  s1  [I] First string to compare to s2
42  *  s2  [I] Second string to compare to s1
43  *  len [I] Number of bytes to compare
44  *
45  * RETURNS
46  *  An integer less than, equal to, or greater than zero indicating that
47  *  s1 is less than, equal to or greater than s2 respectively.
48  *
49  * NOTES
50  *  Any Nul characters in s1 or s2 are ignored. This function always
51  *  compares up to len bytes or the first place where s1 and s2 differ.
52  */
53 INT __cdecl NTDLL__memicmp( LPCSTR s1, LPCSTR s2, DWORD len )
54 {
55     int ret = 0;
56     while (len--)
57     {
58         if ((ret = tolower(*s1) - tolower(*s2))) break;
59         s1++;
60         s2++;
61     }
62     return ret;
63 }
64
65
66 /*********************************************************************
67  *                  _strupr   (NTDLL.@)
68  *
69  * Convert a string to upper case.
70  *
71  * PARAMS
72  *  str [I/O] String to convert
73  *
74  * RETURNS
75  *  str. There is no error return, if str is NULL or invalid, this
76  *  function will crash.
77  */
78 LPSTR __cdecl _strupr( LPSTR str )
79 {
80     LPSTR ret = str;
81     for ( ; *str; str++) *str = toupper(*str);
82     return ret;
83 }
84
85
86 /*********************************************************************
87  *                  _strlwr   (NTDLL.@)
88  *
89  * Convert a string to lowercase
90  *
91  * PARAMS
92  *  str [I/O] String to convert
93  *
94  * RETURNS
95  *  str. There is no error return, if str is NULL or invalid, this
96  *  function will crash.
97  */
98 LPSTR __cdecl _strlwr( LPSTR str )
99 {
100     LPSTR ret = str;
101     for ( ; *str; str++) *str = tolower(*str);
102     return ret;
103 }
104
105
106 /*********************************************************************
107  *      _ultoa   (NTDLL.@)
108  *
109  * Convert an unsigned long integer to a string.
110  *
111  * RETURNS
112  *  str.
113  *
114  * NOTES
115  *  - Converts value to a Nul terminated string which is copied to str.
116  *  - The maximum length of the copied str is 33 bytes.
117  *  - Does not check if radix is in the range of 2 to 36.
118  *  - If str is NULL it crashes, as the native function does.
119  */
120 char * __cdecl _ultoa(
121     unsigned long value, /* [I] Value to be converted */
122     char *str,           /* [O] Destination for the converted value */
123     int radix)           /* [I] Number base for conversion */
124 {
125     char buffer[33];
126     char *pos;
127     int digit;
128
129     pos = &buffer[32];
130     *pos = '\0';
131
132     do {
133         digit = value % radix;
134         value = value / radix;
135         if (digit < 10) {
136             *--pos = '0' + digit;
137         } else {
138             *--pos = 'a' + digit - 10;
139         } /* if */
140     } while (value != 0L);
141
142     memcpy(str, pos, &buffer[32] - pos + 1);
143     return str;
144 }
145
146
147 /*********************************************************************
148  *      _ltoa   (NTDLL.@)
149  *
150  * Convert a long integer to a string.
151  *
152  * RETURNS
153  *  str.
154  *
155  * NOTES
156  *  - Converts value to a Nul terminated string which is copied to str.
157  *  - The maximum length of the copied str is 33 bytes. If radix
158  *  is 10 and value is negative, the value is converted with sign.
159  *  - Does not check if radix is in the range of 2 to 36.
160  *  - If str is NULL it crashes, as the native function does.
161  */
162 char * __cdecl _ltoa(
163     long value, /* [I] Value to be converted */
164     char *str,  /* [O] Destination for the converted value */
165     int radix)  /* [I] Number base for conversion */
166 {
167     unsigned long val;
168     int negative;
169     char buffer[33];
170     char *pos;
171     int digit;
172
173     if (value < 0 && radix == 10) {
174         negative = 1;
175         val = -value;
176     } else {
177         negative = 0;
178         val = value;
179     } /* if */
180
181     pos = &buffer[32];
182     *pos = '\0';
183
184     do {
185         digit = val % radix;
186         val = val / radix;
187         if (digit < 10) {
188             *--pos = '0' + digit;
189         } else {
190             *--pos = 'a' + digit - 10;
191         } /* if */
192     } while (val != 0L);
193
194     if (negative) {
195         *--pos = '-';
196     } /* if */
197
198     memcpy(str, pos, &buffer[32] - pos + 1);
199     return str;
200 }
201
202
203 /*********************************************************************
204  *      _itoa    (NTDLL.@)
205  *
206  * Converts an integer to a string.
207  *
208  * RETURNS
209  *  str.
210  *
211  * NOTES
212  *  - Converts value to a '\0' terminated string which is copied to str.
213  *  - The maximum length of the copied str is 33 bytes. If radix
214  *  is 10 and value is negative, the value is converted with sign.
215  *  - Does not check if radix is in the range of 2 to 36.
216  *  - If str is NULL it crashes, as the native function does.
217  */
218 char * __cdecl _itoa(
219     int value, /* [I] Value to be converted */
220     char *str, /* [O] Destination for the converted value */
221     int radix) /* [I] Number base for conversion */
222 {
223     return _ltoa(value, str, radix);
224 }
225
226
227 /*********************************************************************
228  *      _ui64toa   (NTDLL.@)
229  *
230  * Converts a large unsigned integer to a string.
231  *
232  * RETURNS
233  *  str.
234  *
235  * NOTES
236  *  - Converts value to a '\0' terminated string which is copied to str.
237  *  - The maximum length of the copied str is 65 bytes.
238  *  - Does not check if radix is in the range of 2 to 36.
239  *  - If str is NULL it crashes, as the native function does.
240  */
241 char * __cdecl _ui64toa(
242     ULONGLONG value, /* [I] Value to be converted */
243     char *str,       /* [O] Destination for the converted value */
244     int radix)       /* [I] Number base for conversion */
245 {
246     char buffer[65];
247     char *pos;
248     int digit;
249
250     pos = &buffer[64];
251     *pos = '\0';
252
253     do {
254         digit = value % radix;
255         value = value / radix;
256         if (digit < 10) {
257             *--pos = '0' + digit;
258         } else {
259             *--pos = 'a' + digit - 10;
260         } /* if */
261     } while (value != 0L);
262
263     memcpy(str, pos, &buffer[64] - pos + 1);
264     return str;
265 }
266
267
268 /*********************************************************************
269  *      _i64toa   (NTDLL.@)
270  *
271  * Converts a large integer to a string.
272  *
273  * RETURNS
274  *  str.
275  *
276  * NOTES
277  *  - Converts value to a Nul terminated string which is copied to str.
278  *  - The maximum length of the copied str is 65 bytes. If radix
279  *  is 10 and value is negative, the value is converted with sign.
280  *  - Does not check if radix is in the range of 2 to 36.
281  *  - If str is NULL it crashes, as the native function does.
282  *
283  * DIFFERENCES
284  * - The native DLL converts negative values (for base 10) wrong:
285  *|                     -1 is converted to -18446744073709551615
286  *|                     -2 is converted to -18446744073709551614
287  *|   -9223372036854775807 is converted to  -9223372036854775809
288  *|   -9223372036854775808 is converted to  -9223372036854775808
289  *   The native msvcrt _i64toa function and our ntdll _i64toa function
290  *   do not have this bug.
291  */
292 char * __cdecl _i64toa(
293     LONGLONG value, /* [I] Value to be converted */
294     char *str,      /* [O] Destination for the converted value */
295     int radix)      /* [I] Number base for conversion */
296 {
297     ULONGLONG val;
298     int negative;
299     char buffer[65];
300     char *pos;
301     int digit;
302
303     if (value < 0 && radix == 10) {
304         negative = 1;
305         val = -value;
306     } else {
307         negative = 0;
308         val = value;
309     } /* if */
310
311     pos = &buffer[64];
312     *pos = '\0';
313
314     do {
315         digit = val % radix;
316         val = val / radix;
317         if (digit < 10) {
318             *--pos = '0' + digit;
319         } else {
320             *--pos = 'a' + digit - 10;
321         } /* if */
322     } while (val != 0L);
323
324     if (negative) {
325         *--pos = '-';
326     } /* if */
327
328     memcpy(str, pos, &buffer[64] - pos + 1);
329     return str;
330 }
331
332
333 /*********************************************************************
334  *      _atoi64   (NTDLL.@)
335  *
336  * Convert a string to a large integer.
337  *
338  * PARAMS
339  *  str [I] String to be converted
340  *
341  * RETURNS
342  *  Success: The integer value represented by str.
343  *  Failure: 0. Note that this cannot be distinguished from a successful
344  *           return, if the string contains "0".
345  *
346  * NOTES
347  *  - Accepts: {whitespace} [+|-] {digits}
348  *  - No check is made for value overflow, only the lower 64 bits are assigned.
349  *  - If str is NULL it crashes, as the native function does.
350  */
351 LONGLONG __cdecl _atoi64( char *str )
352 {
353     ULONGLONG RunningTotal = 0;
354     char bMinus = 0;
355
356     while (*str == ' ' || (*str >= '\011' && *str <= '\015')) {
357         str++;
358     } /* while */
359
360     if (*str == '+') {
361         str++;
362     } else if (*str == '-') {
363         bMinus = 1;
364         str++;
365     } /* if */
366
367     while (*str >= '0' && *str <= '9') {
368         RunningTotal = RunningTotal * 10 + *str - '0';
369         str++;
370     } /* while */
371
372     return bMinus ? -RunningTotal : RunningTotal;
373 }
374
375
376 /*********************************************************************
377  *              _splitpath (NTDLL.@)
378  *
379  * Split a path into its component pieces.
380  *
381  * PARAMS
382  *  inpath [I] Path to split
383  *  drv    [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
384  *  dir    [O] Destination for directory component. Should be at least MAX_PATH characters.
385  *  fname  [O] Destination for File name component. Should be at least MAX_PATH characters.
386  *  ext    [O] Destination for file extension component. Should be at least MAX_PATH characters.
387  */
388 void __cdecl _splitpath(const char* inpath, char * drv, char * dir,
389                         char* fname, char * ext )
390 {
391     const char *p, *end;
392
393     if (inpath[0] && inpath[1] == ':')
394     {
395         if (drv)
396         {
397             drv[0] = inpath[0];
398             drv[1] = inpath[1];
399             drv[2] = 0;
400         }
401         inpath += 2;
402     }
403     else if (drv) drv[0] = 0;
404
405     /* look for end of directory part */
406     end = NULL;
407     for (p = inpath; *p; p++) if (*p == '/' || *p == '\\') end = p + 1;
408
409     if (end)  /* got a directory */
410     {
411         if (dir)
412         {
413             memcpy( dir, inpath, end - inpath );
414             dir[end - inpath] = 0;
415         }
416         inpath = end;
417     }
418     else if (dir) dir[0] = 0;
419
420     /* look for extension: what's after the last dot */
421     end = NULL;
422     for (p = inpath; *p; p++) if (*p == '.') end = p;
423
424     if (!end) end = p; /* there's no extension */
425
426     if (fname)
427     {
428         memcpy( fname, inpath, end - inpath );
429         fname[end - inpath] = 0;
430     }
431     if (ext) strcpy( ext, end );
432 }