Take advantage of new winebuild syntax to remove redundant function
[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 <string.h>
27
28 #include "windef.h"
29 #include "winternl.h"
30
31
32 /*********************************************************************
33  *                  _memicmp   (NTDLL.@)
34  */
35 INT __cdecl NTDLL__memicmp( LPCSTR s1, LPCSTR s2, DWORD len )
36 {
37     int ret = 0;
38     while (len--)
39     {
40         if ((ret = tolower(*s1) - tolower(*s2))) break;
41         s1++;
42         s2++;
43     }
44     return ret;
45 }
46
47
48 /*********************************************************************
49  *                  _strupr   (NTDLL.@)
50  */
51 LPSTR __cdecl _strupr( LPSTR str )
52 {
53     LPSTR ret = str;
54     for ( ; *str; str++) *str = toupper(*str);
55     return ret;
56 }
57
58
59 /*********************************************************************
60  *                  _strlwr   (NTDLL.@)
61  *
62  * convert a string in place to lowercase
63  */
64 LPSTR __cdecl _strlwr( LPSTR str )
65 {
66     LPSTR ret = str;
67     for ( ; *str; str++) *str = tolower(*str);
68     return ret;
69 }
70
71
72 /*********************************************************************
73  *      _ultoa   (NTDLL.@)
74  *
75  * Converts an unsigned long integer to a string.
76  *
77  * Assigns a '\0' terminated string to str and returns str.
78  * Does not check if radix is in the range of 2 to 36 (as native DLL).
79  * For str == NULL just crashes (as native DLL).
80  */
81 char * __cdecl _ultoa( unsigned long value, char *str, int radix )
82 {
83     char buffer[33];
84     char *pos;
85     int digit;
86
87     pos = &buffer[32];
88     *pos = '\0';
89
90     do {
91         digit = value % radix;
92         value = value / radix;
93         if (digit < 10) {
94             *--pos = '0' + digit;
95         } else {
96             *--pos = 'a' + digit - 10;
97         } /* if */
98     } while (value != 0L);
99
100     memcpy(str, pos, &buffer[32] - pos + 1);
101     return str;
102 }
103
104
105 /*********************************************************************
106  *      _ltoa   (NTDLL.@)
107  *
108  * Converts a long integer to a string.
109  *
110  * Assigns a '\0' terminated string to str and returns str. If radix
111  * is 10 and value is negative, the value is converted with sign.
112  * Does not check if radix is in the range of 2 to 36 (as native DLL).
113  * For str == NULL just crashes (as native DLL).
114  */
115 char * __cdecl _ltoa( long value, char *str, int radix )
116 {
117     unsigned long val;
118     int negative;
119     char buffer[33];
120     char *pos;
121     int digit;
122
123     if (value < 0 && radix == 10) {
124         negative = 1;
125         val = -value;
126     } else {
127         negative = 0;
128         val = value;
129     } /* if */
130
131     pos = &buffer[32];
132     *pos = '\0';
133
134     do {
135         digit = val % radix;
136         val = val / radix;
137         if (digit < 10) {
138             *--pos = '0' + digit;
139         } else {
140             *--pos = 'a' + digit - 10;
141         } /* if */
142     } while (val != 0L);
143
144     if (negative) {
145         *--pos = '-';
146     } /* if */
147
148     memcpy(str, pos, &buffer[32] - pos + 1);
149     return str;
150 }
151
152
153 /*********************************************************************
154  *      _itoa    (NTDLL.@)
155  *
156  * Converts an integer to a string.
157  *
158  * Assigns a '\0' terminated wstring to str and returns str. If radix
159  * is 10 and value is negative, the value is converted with sign.
160  * Does not check if radix is in the range of 2 to 36 (as native DLL).
161  * For str == NULL just crashes (as native DLL).
162  */
163 char * __cdecl _itoa( int value, char *str, int radix )
164 {
165     return _ltoa(value, str, radix);
166 }
167
168
169 /*********************************************************************
170  *      _ui64toa   (NTDLL.@)
171  *
172  * Converts a large unsigned integer to a string.
173  *
174  * Assigns a '\0' terminated string to str and returns str.
175  * Does not check if radix is in the range of 2 to 36 (as native DLL).
176  * For str == NULL just crashes (as native DLL).
177  */
178 char * __cdecl _ui64toa( ULONGLONG value, char *str, int radix )
179 {
180     char buffer[65];
181     char *pos;
182     int digit;
183
184     pos = &buffer[64];
185     *pos = '\0';
186
187     do {
188         digit = value % radix;
189         value = value / radix;
190         if (digit < 10) {
191             *--pos = '0' + digit;
192         } else {
193             *--pos = 'a' + digit - 10;
194         } /* if */
195     } while (value != 0L);
196
197     memcpy(str, pos, &buffer[64] - pos + 1);
198     return str;
199 }
200
201
202 /*********************************************************************
203  *      _i64toa   (NTDLL.@)
204  *
205  * Converts a large integer to a string.
206  *
207  * Assigns a '\0' terminated string to str and returns str. If radix
208  * is 10 and value is negative, the value is converted with sign.
209  * Does not check if radix is in the range of 2 to 36 (as native DLL).
210  * For str == NULL just crashes (as native DLL).
211  *
212  * Difference:
213  * - The native DLL converts negative values (for base 10) wrong:
214  *                     -1 is converted to -18446744073709551615
215  *                     -2 is converted to -18446744073709551614
216  *   -9223372036854775807 is converted to  -9223372036854775809
217  *   -9223372036854775808 is converted to  -9223372036854775808
218  *   The native msvcrt _i64toa function and our ntdll function do
219  *   not have this bug.
220  */
221 char * __cdecl _i64toa( LONGLONG value, char *str, int radix )
222 {
223     ULONGLONG val;
224     int negative;
225     char buffer[65];
226     char *pos;
227     int digit;
228
229     if (value < 0 && radix == 10) {
230         negative = 1;
231         val = -value;
232     } else {
233         negative = 0;
234         val = value;
235     } /* if */
236
237     pos = &buffer[64];
238     *pos = '\0';
239
240     do {
241         digit = val % radix;
242         val = val / radix;
243         if (digit < 10) {
244             *--pos = '0' + digit;
245         } else {
246             *--pos = 'a' + digit - 10;
247         } /* if */
248     } while (val != 0L);
249
250     if (negative) {
251         *--pos = '-';
252     } /* if */
253
254     memcpy(str, pos, &buffer[64] - pos + 1);
255     return str;
256 }
257
258
259 /*********************************************************************
260  *      _atoi64   (NTDLL.@)
261  *
262  * Converts a string to a large integer.
263  *
264  * On success it returns the integer value otherwise it returns 0.
265  * Accepts: {whitespace} [+|-] {digits}
266  * No check of overflow: Just assigns lower 64 bits (as native DLL).
267  * Does not check for str != NULL (as native DLL).
268  */
269 LONGLONG __cdecl _atoi64( char *str )
270 {
271     ULONGLONG RunningTotal = 0;
272     char bMinus = 0;
273
274     while (*str == ' ' || (*str >= '\011' && *str <= '\015')) {
275         str++;
276     } /* while */
277
278     if (*str == '+') {
279         str++;
280     } else if (*str == '-') {
281         bMinus = 1;
282         str++;
283     } /* if */
284
285     while (*str >= '0' && *str <= '9') {
286         RunningTotal = RunningTotal * 10 + *str - '0';
287         str++;
288     } /* while */
289
290     return bMinus ? -RunningTotal : RunningTotal;
291 }
292
293
294 /*********************************************************************
295  *              _splitpath (NTDLL.@)
296  */
297 void __cdecl _splitpath(const char* inpath, char * drv, char * dir,
298                         char* fname, char * ext )
299 {
300   /* Modified PD code from 'snippets' collection. */
301   char ch, *ptr, *p;
302   char pathbuff[MAX_PATH], *path=pathbuff;
303
304   strcpy(pathbuff, inpath);
305
306   /* convert slashes to backslashes for searching */
307   for (ptr = (char*)path; *ptr; ++ptr)
308     if ('/' == *ptr)
309       *ptr = '\\';
310
311   /* look for drive spec */
312   if ('\0' != (ptr = strchr(path, ':')))
313   {
314     ++ptr;
315     if (drv)
316     {
317       strncpy(drv, path, ptr - path);
318       drv[ptr - path] = '\0';
319     }
320     path = ptr;
321   }
322   else if (drv)
323     *drv = '\0';
324
325   /* find rightmost backslash or leftmost colon */
326   if (NULL == (ptr = strrchr(path, '\\')))
327     ptr = (strchr(path, ':'));
328
329   if (!ptr)
330   {
331     ptr = (char *)path; /* no path */
332     if (dir)
333       *dir = '\0';
334   }
335   else
336   {
337     ++ptr; /* skip the delimiter */
338     if (dir)
339     {
340       ch = *ptr;
341       *ptr = '\0';
342       strcpy(dir, path);
343       *ptr = ch;
344     }
345   }
346
347   if (NULL == (p = strrchr(ptr, '.')))
348   {
349     if (fname)
350       strcpy(fname, ptr);
351     if (ext)
352       *ext = '\0';
353   }
354   else
355   {
356     *p = '\0';
357     if (fname)
358       strcpy(fname, ptr);
359     *p = '.';
360     if (ext)
361       strcpy(ext, p);
362   }
363
364   /* Fix pathological case - Win returns ':' as part of the
365    * directory when no drive letter is given.
366    */
367   if (drv && drv[0] == ':')
368   {
369     *drv = '\0';
370     if (dir)
371     {
372       pathbuff[0] = ':';
373       pathbuff[1] = '\0';
374       strcat(pathbuff,dir);
375       strcpy(dir,pathbuff);
376     }
377   }
378 }