finished applying @implemented and @unimplemented comments and remove the comments...
[reactos.git] / reactos / ntoskrnl / rtl / stdlib.c
1 /* $Id: stdlib.c,v 1.8 2003/07/11 01:23:16 royce 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 <ddk/ntddk.h>
15 #include <ctype.h>
16 #include <limits.h>
17 #include <stdlib.h>
18 #include <string.h>
19
20 /* GLOBALS ****************************************************************/
21
22 static unsigned long long next = 0;
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)LONG_MIN : LONG_MAX;
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 ? LONG_MIN : LONG_MAX;
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 /*
153 * @implemented
154 */
155 int rand(void)
156 {
157 next = next * 0x5deece66dLL + 11;
158 return (int)((next >> 16) & RAND_MAX);
159 }
160
161
162 /*
163 * @implemented
164 */
165 void srand(unsigned seed)
166 {
167 next = seed;
168 }
169
170
171 /*
172 * @implemented
173 */
174 int mbtowc (wchar_t *wchar, const char *mbchar, size_t count)
175 {
176 NTSTATUS Status;
177 ULONG Size;
178
179 if (wchar == NULL)
180 return 0;
181
182 Status = RtlMultiByteToUnicodeN (wchar,
183 sizeof(WCHAR),
184 &Size,
185 (char *)mbchar,
186 count);
187 if (!NT_SUCCESS(Status))
188 return -1;
189
190 return (int)Size;
191 }
192
193
194 /*
195 * @implemented
196 */
197 size_t mbstowcs (wchar_t *wcstr, const char *mbstr, size_t count)
198 {
199 NTSTATUS Status;
200 ULONG Size;
201 ULONG Length;
202
203 Length = strlen (mbstr);
204
205 if (wcstr == NULL)
206 {
207 RtlMultiByteToUnicodeSize (&Size,
208 (char *)mbstr,
209 Length);
210
211 return (size_t)Size;
212 }
213
214 Status = RtlMultiByteToUnicodeN (wcstr,
215 count,
216 &Size,
217 (char *)mbstr,
218 Length);
219 if (!NT_SUCCESS(Status))
220 return -1;
221
222 return (size_t)Size;
223 }
224
225
226 /*
227 * @implemented
228 */
229 int wctomb (char *mbchar, wchar_t wchar)
230 {
231 NTSTATUS Status;
232 ULONG Size;
233
234 if (mbchar == NULL)
235 return 0;
236
237 Status = RtlUnicodeToMultiByteN (mbchar,
238 1,
239 &Size,
240 &wchar,
241 sizeof(WCHAR));
242 if (!NT_SUCCESS(Status))
243 return -1;
244
245 return (int)Size;
246 }
247
248
249 /*
250 * @implemented
251 */
252 size_t wcstombs (char *mbstr, const wchar_t *wcstr, size_t count)
253 {
254 NTSTATUS Status;
255 ULONG Size;
256 ULONG Length;
257
258 Length = wcslen (wcstr);
259
260 if (mbstr == NULL)
261 {
262 RtlUnicodeToMultiByteSize (&Size,
263 (wchar_t *)wcstr,
264 Length * sizeof(WCHAR));
265
266 return (size_t)Size;
267 }
268
269 Status = RtlUnicodeToMultiByteN (mbstr,
270 count,
271 &Size,
272 (wchar_t *)wcstr,
273 Length * sizeof(WCHAR));
274 if (!NT_SUCCESS(Status))
275 return -1;
276
277 return (size_t)Size;
278 }
279
280 /* EOF */