2004-08-15 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / ntoskrnl / rtl / stdlib.c
1 /* $Id: stdlib.c,v 1.12 2004/08/15 16:39:11 chorns Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/rtl/stdlib.c
6 * PURPOSE: Standard library functions
7 * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
8 * UPDATE HISTORY:
9 * 1999/07/29 ekohl Created
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #include <internal/ctype.h>
16
17 /* GLOBALS ****************************************************************/
18
19 #if defined(__GNUC__)
20 static unsigned long long next = 0;
21 #else
22 static unsigned __int64 next = 0;
23 #endif
24
25 /* FUNCTIONS ****************************************************************/
26
27 int atoi(const char *str)
28 {
29 return (int)atol (str);
30 }
31
32
33 /*
34 * NOTE: no error
35 *
36 * @implemented
37 */
38 long atol(const char *str)
39 {
40 const char *s = str;
41 unsigned long acc;
42 int c;
43 unsigned long cutoff;
44 int neg = 0, any, cutlim;
45
46 /*
47 * Skip white space and pick up leading +/- sign if any.
48 */
49 do {
50 c = *s++;
51 } while (isspace(c));
52 if (c == '-')
53 {
54 neg = 1;
55 c = *s++;
56 }
57 else if (c == '+')
58 c = *s++;
59
60 /*
61 * Compute the cutoff value between legal numbers and illegal
62 * numbers. That is the largest legal value, divided by the
63 * base. An input number that is greater than this value, if
64 * followed by a legal input character, is too big. One that
65 * is equal to this value may be valid or not; the limit
66 * between valid and invalid numbers is then based on the last
67 * digit. For instance, if the range for longs is
68 * [-2147483648..2147483647] and the input base is 10,
69 * cutoff will be set to 214748364 and cutlim to either
70 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
71 * a value > 214748364, or equal but the next digit is > 7 (or 8),
72 * the number is too big, and we will return a range error.
73 *
74 * Set any if any `digits' consumed; make it negative to indicate
75 * overflow.
76 */
77 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
78 cutlim = cutoff % (unsigned long)10;
79 cutoff /= (unsigned long)10;
80 for (acc = 0, any = 0;; c = *s++)
81 {
82 if (isdigit(c))
83 c -= '0';
84 else
85 break;
86 if (c >= 10)
87 break;
88 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
89 any = -1;
90 else
91 {
92 any = 1;
93 acc *= 10;
94 acc += c;
95 }
96 }
97 if (any < 0)
98 {
99 acc = neg ? LONG_MIN : LONG_MAX;
100 }
101 else if (neg)
102 acc = -acc;
103
104 return acc;
105 }
106
107
108 /*
109 * NOTE: no radix range check (valid range: 2 - 36)
110 *
111 * @implemented
112 */
113
114 char *_itoa (int value, char *string, int radix)
115 {
116 char tmp[33];
117 char *tp = tmp;
118 int i;
119 unsigned v;
120 int sign;
121 char *sp = NULL;
122
123 if (string == NULL)
124 return NULL;
125
126 sign = (radix == 10 && value < 0);
127 if (sign)
128 v = -value;
129 else
130 v = (unsigned)value;
131
132 while (v || tp == tmp)
133 {
134 i = v % radix;
135 v = v / radix;
136 if (i < 10)
137 *tp++ = i + '0';
138 else
139 *tp++ = i + 'a' - 10;
140 }
141
142 if (sign)
143 *sp++ = '-';
144
145 while (tp > tmp)
146 *sp++ = *--tp;
147 *sp = 0;
148
149 return string;
150 }
151
152 /*
153 * NOTE: no radix range check (valid range: 2 - 36)
154 *
155 * @implemented
156 */
157
158 wchar_t *_itow (int value, wchar_t *string, int radix)
159 {
160 wchar_t tmp[33];
161 wchar_t *tp = tmp;
162 int i;
163 unsigned v;
164 int sign;
165 wchar_t *sp = NULL;
166
167 if (string == NULL)
168 return NULL;
169
170 sign = (radix == 10 && value < 0);
171 if (sign)
172 v = -value;
173 else
174 v = (unsigned)value;
175
176 while (v || tp == tmp)
177 {
178 i = v % radix;
179 v = v / radix;
180 if (i < 10)
181 *tp++ = i + L'0';
182 else
183 *tp++ = i + L'a' - 10;
184 }
185
186 if (sign)
187 *sp++ = L'-';
188
189 while (tp > tmp)
190 *sp++ = *--tp;
191 *sp = 0;
192
193 return string;
194 }
195
196
197 /*
198 * @implemented
199 */
200 int rand(void)
201 {
202 #if defined(__GNUC__)
203 next = next * 0x5deece66dLL + 11;
204 #else
205 next = next * 0x5deece66di64 + 11;
206 #endif
207 return (int)((next >> 16) & RAND_MAX);
208 }
209
210
211 /*
212 * @implemented
213 */
214 void srand(unsigned seed)
215 {
216 next = seed;
217 }
218
219
220 /*
221 * @implemented
222 */
223 int mbtowc (wchar_t *wchar, const char *mbchar, size_t count)
224 {
225 NTSTATUS Status;
226 ULONG Size;
227
228 if (wchar == NULL)
229 return 0;
230
231 Status = RtlMultiByteToUnicodeN (wchar,
232 sizeof(WCHAR),
233 &Size,
234 (char *)mbchar,
235 count);
236 if (!NT_SUCCESS(Status))
237 return -1;
238
239 return (int)Size;
240 }
241
242
243 /*
244 * @implemented
245 */
246 size_t mbstowcs (wchar_t *wcstr, const char *mbstr, size_t count)
247 {
248 NTSTATUS Status;
249 ULONG Size;
250 ULONG Length;
251
252 Length = strlen (mbstr);
253
254 if (wcstr == NULL)
255 {
256 RtlMultiByteToUnicodeSize (&Size,
257 (char *)mbstr,
258 Length);
259
260 return (size_t)Size;
261 }
262
263 Status = RtlMultiByteToUnicodeN (wcstr,
264 count,
265 &Size,
266 (char *)mbstr,
267 Length);
268 if (!NT_SUCCESS(Status))
269 return -1;
270
271 return (size_t)Size;
272 }
273
274
275 /*
276 * @implemented
277 */
278 int wctomb (char *mbchar, wchar_t wchar)
279 {
280 NTSTATUS Status;
281 ULONG Size;
282
283 if (mbchar == NULL)
284 return 0;
285
286 Status = RtlUnicodeToMultiByteN (mbchar,
287 1,
288 &Size,
289 &wchar,
290 sizeof(WCHAR));
291 if (!NT_SUCCESS(Status))
292 return -1;
293
294 return (int)Size;
295 }
296
297
298 /*
299 * @implemented
300 */
301 size_t wcstombs (char *mbstr, const wchar_t *wcstr, size_t count)
302 {
303 NTSTATUS Status;
304 ULONG Size;
305 ULONG Length;
306
307 Length = wcslen (wcstr);
308
309 if (mbstr == NULL)
310 {
311 RtlUnicodeToMultiByteSize (&Size,
312 (wchar_t *)wcstr,
313 Length * sizeof(WCHAR));
314
315 return (size_t)Size;
316 }
317
318 Status = RtlUnicodeToMultiByteN (mbstr,
319 count,
320 &Size,
321 (wchar_t *)wcstr,
322 Length * sizeof(WCHAR));
323 if (!NT_SUCCESS(Status))
324 return -1;
325
326 return (size_t)Size;
327 }
328
329 /* EOF */