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