update for HEAD-2002110701
[reactos.git] / 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  * 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
36 long atol(const char *str)
37 {
38   const char *s = str;
39   unsigned long acc;
40   int c;
41   unsigned long cutoff;
42   int neg = 0, any, cutlim;
43
44   /*
45    * Skip white space and pick up leading +/- sign if any.
46    */
47   do {
48     c = *s++;
49   } while (isspace(c));
50   if (c == '-')
51   {
52     neg = 1;
53     c = *s++;
54   }
55   else if (c == '+')
56     c = *s++;
57
58   /*
59    * Compute the cutoff value between legal numbers and illegal
60    * numbers.  That is the largest legal value, divided by the
61    * base.  An input number that is greater than this value, if
62    * followed by a legal input character, is too big.  One that
63    * is equal to this value may be valid or not; the limit
64    * between valid and invalid numbers is then based on the last
65    * digit.  For instance, if the range for longs is
66    * [-2147483648..2147483647] and the input base is 10,
67    * cutoff will be set to 214748364 and cutlim to either
68    * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
69    * a value > 214748364, or equal but the next digit is > 7 (or 8),
70    * the number is too big, and we will return a range error.
71    *
72    * Set any if any `digits' consumed; make it negative to indicate
73    * overflow.
74    */
75   cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
76   cutlim = cutoff % (unsigned long)10;
77   cutoff /= (unsigned long)10;
78   for (acc = 0, any = 0;; c = *s++)
79   {
80     if (isdigit(c))
81       c -= '0';
82     else
83       break;
84     if (c >= 10)
85       break;
86     if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
87       any = -1;
88     else
89     {
90       any = 1;
91       acc *= 10;
92       acc += c;
93     }
94   }
95   if (any < 0)
96   {
97     acc = neg ? LONG_MIN : LONG_MAX;
98   }
99   else if (neg)
100     acc = -acc;
101
102   return acc;
103 }
104
105
106 /*
107  * NOTE: no radix range check (valid range: 2 - 36)
108  */
109
110 char *_itoa (int value, char *string, int radix)
111 {
112   char tmp[33];
113   char *tp = tmp;
114   int i;
115   unsigned v;
116   int sign;
117   char *sp = NULL;
118
119   if (string == NULL)
120     return NULL;
121
122   sign = (radix == 10 && value < 0);
123   if (sign)
124     v = -value;
125   else
126     v = (unsigned)value;
127
128   while (v || tp == tmp)
129   {
130     i = v % radix;
131     v = v / radix;
132     if (i < 10)
133       *tp++ = i+'0';
134     else
135       *tp++ = i + 'a' - 10;
136   }
137
138   if (sign)
139     *sp++ = '-';
140
141   while (tp > tmp)
142     *sp++ = *--tp;
143   *sp = 0;
144
145   return string;
146 }
147
148
149 int rand(void)
150 {
151         next = next * 0x5deece66dLL + 11;
152         return (int)((next >> 16) & RAND_MAX);
153 }
154
155
156 void srand(unsigned seed)
157 {
158         next = seed;
159 }
160
161
162 int mbtowc (wchar_t *wchar, const char *mbchar, size_t count)
163 {
164         NTSTATUS Status;
165         ULONG Size;
166
167         if (wchar == NULL)
168                 return 0;
169
170         Status = RtlMultiByteToUnicodeN (wchar,
171                                          sizeof(WCHAR),
172                                          &Size,
173                                          (char *)mbchar,
174                                          count);
175         if (!NT_SUCCESS(Status))
176                 return -1;
177
178         return (int)Size;
179 }
180
181
182 size_t mbstowcs (wchar_t *wcstr, const char *mbstr, size_t count)
183 {
184         NTSTATUS Status;
185         ULONG Size;
186         ULONG Length;
187
188         Length = strlen (mbstr);
189
190         if (wcstr == NULL)
191         {
192                 RtlMultiByteToUnicodeSize (&Size,
193                                            (char *)mbstr,
194                                            Length);
195
196                 return (size_t)Size;
197         }
198
199         Status = RtlMultiByteToUnicodeN (wcstr,
200                                          count,
201                                          &Size,
202                                          (char *)mbstr,
203                                          Length);
204         if (!NT_SUCCESS(Status))
205                 return -1;
206
207         return (size_t)Size;
208 }
209
210
211 int wctomb (char *mbchar, wchar_t wchar)
212 {
213         NTSTATUS Status;
214         ULONG Size;
215
216         if (mbchar == NULL)
217                 return 0;
218
219         Status = RtlUnicodeToMultiByteN (mbchar,
220                                          1,
221                                          &Size,
222                                          &wchar,
223                                          sizeof(WCHAR));
224         if (!NT_SUCCESS(Status))
225                 return -1;
226
227         return (int)Size;
228 }
229
230
231 size_t wcstombs (char *mbstr, const wchar_t *wcstr, size_t count)
232 {
233         NTSTATUS Status;
234         ULONG Size;
235         ULONG Length;
236
237         Length = wcslen (wcstr);
238
239         if (mbstr == NULL)
240         {
241                 RtlUnicodeToMultiByteSize (&Size,
242                                            (wchar_t *)wcstr,
243                                            Length * sizeof(WCHAR));
244
245                 return (size_t)Size;
246         }
247
248         Status = RtlUnicodeToMultiByteN (mbstr,
249                                          count,
250                                          &Size,
251                                          (wchar_t *)wcstr,
252                                          Length * sizeof(WCHAR));
253         if (!NT_SUCCESS(Status))
254                 return -1;
255
256         return (size_t)Size;
257 }
258
259 /* EOF */