xref: /reactos/sdk/lib/crt/string/itoa.c (revision 845faec4)
1 /* taken from wine ntdll and msvcrt string.c */
2 
3 #include <precomp.h>
4 
5 /*
6  * @implemented
7  */
8 char *
9 CDECL
10 _i64toa(__int64 value, char *string, int radix)
11 {
12     ULONGLONG  val;
13     int negative;
14     char buffer[65];
15     char *pos;
16     int digit;
17 
18     if (value < 0 && radix == 10) {
19 	negative = 1;
20         val = -value;
21     } else {
22 	negative = 0;
23         val = value;
24     } /* if */
25 
26     pos = &buffer[64];
27     *pos = '\0';
28 
29     do {
30 	digit = val % radix;
31 	val = val / radix;
32 	if (digit < 10) {
33 	    *--pos = '0' + digit;
34 	} else {
35 	    *--pos = 'a' + digit - 10;
36 	} /* if */
37     } while (val != 0L);
38 
39     if (negative) {
40 	*--pos = '-';
41     } /* if */
42 
43     memcpy(string, pos, &buffer[64] - pos + 1);
44     return string;
45 }
46 
47 /*
48  * @implemented
49  */
50 int CDECL _i64toa_s(__int64 value, char *str, size_t size, int radix)
51 {
52     unsigned __int64 val;
53     unsigned int digit;
54     int is_negative;
55     char buffer[65], *pos;
56     size_t len;
57 
58     if (!MSVCRT_CHECK_PMT(str != NULL) || !MSVCRT_CHECK_PMT(size > 0) ||
59         !MSVCRT_CHECK_PMT(radix >= 2) || !MSVCRT_CHECK_PMT(radix <= 36))
60     {
61         if (str && size)
62             str[0] = '\0';
63 #ifndef _LIBCNT_
64         *_errno() = EINVAL;
65 #endif
66         return EINVAL;
67     }
68 
69     if (value < 0 && radix == 10)
70     {
71         is_negative = 1;
72         val = -value;
73     }
74     else
75     {
76         is_negative = 0;
77         val = value;
78     }
79 
80     pos = buffer + 64;
81     *pos = '\0';
82 
83     do
84     {
85         digit = val % radix;
86         val /= radix;
87 
88         if (digit < 10)
89             *--pos = '0' + digit;
90         else
91             *--pos = 'a' + digit - 10;
92     }
93     while (val != 0);
94 
95     if (is_negative)
96         *--pos = '-';
97 
98     len = buffer + 65 - pos;
99     if (len > size)
100     {
101         size_t i;
102         char *p = str;
103 
104         /* Copy the temporary buffer backwards up to the available number of
105          * characters. Don't copy the negative sign if present. */
106 
107         if (is_negative)
108         {
109             p++;
110             size--;
111         }
112 
113         for (pos = buffer + 63, i = 0; i < size; i++)
114             *p++ = *pos--;
115 
116         str[0] = '\0';
117         MSVCRT_INVALID_PMT("str[size] is too small", ERANGE);
118         return ERANGE;
119     }
120 
121     memcpy(str, pos, len);
122     return 0;
123 }
124 
125 /*
126  * @implemented
127  */
128 char *
129 CDECL
130 _ui64toa(unsigned __int64 value, char *string, int radix)
131 {
132     char buffer[65];
133     char *pos;
134     int digit;
135 
136     pos = &buffer[64];
137     *pos = '\0';
138 
139     do {
140 	digit = value % radix;
141 	value = value / radix;
142 	if (digit < 10) {
143 	    *--pos = '0' + digit;
144 	} else {
145 	    *--pos = 'a' + digit - 10;
146 	} /* if */
147     } while (value != 0L);
148 
149     memcpy(string, pos, &buffer[64] - pos + 1);
150     return string;
151 }
152 
153 /*
154  * @implemented
155  */
156 int CDECL _ui64toa_s(unsigned __int64 value, char *str,
157         size_t size, int radix)
158 {
159     char buffer[65], *pos;
160     int digit;
161 
162     if (!MSVCRT_CHECK_PMT(str != NULL) || !MSVCRT_CHECK_PMT(size > 0) ||
163         !MSVCRT_CHECK_PMT(radix>=2) || !MSVCRT_CHECK_PMT(radix<=36)) {
164 #ifndef _LIBCNT_
165         *_errno() = EINVAL;
166 #endif
167         return EINVAL;
168     }
169 
170     pos = buffer+64;
171     *pos = '\0';
172 
173     do {
174         digit = value%radix;
175         value /= radix;
176 
177         if(digit < 10)
178             *--pos = '0'+digit;
179         else
180             *--pos = 'a'+digit-10;
181     }while(value != 0);
182 
183     if((unsigned)(buffer-pos+65) > size) {
184         MSVCRT_INVALID_PMT("str[size] is too small", EINVAL);
185         return EINVAL;
186     }
187 
188     memcpy(str, pos, buffer-pos+65);
189     return 0;
190 }
191 
192 /*
193  * @implemented
194  */
195 int CDECL _itoa_s(int value, char *str, size_t size, int radix)
196 {
197     return _ltoa_s(value, str, size, radix);
198 }
199 
200 /*
201  * @implemented
202  */
203 char *
204 CDECL
205 _itoa(int value, char *string, int radix)
206 {
207   return _ltoa(value, string, radix);
208 }
209 
210 /*
211  * @implemented
212  */
213 char *
214 CDECL
215 _ltoa(long value, char *string, int radix)
216 {
217     unsigned long val;
218     int negative;
219     char buffer[33];
220     char *pos;
221     int digit;
222 
223     if (value < 0 && radix == 10) {
224 	negative = 1;
225         val = -value;
226     } else {
227 	negative = 0;
228         val = value;
229     } /* if */
230 
231     pos = &buffer[32];
232     *pos = '\0';
233 
234     do {
235 	digit = val % radix;
236 	val = val / radix;
237 	if (digit < 10) {
238 	    *--pos = '0' + digit;
239 	} else {
240 	    *--pos = 'a' + digit - 10;
241 	} /* if */
242     } while (val != 0L);
243 
244     if (negative) {
245 	*--pos = '-';
246     } /* if */
247 
248     memcpy(string, pos, &buffer[32] - pos + 1);
249     return string;
250 }
251 
252 /*
253  * @implemented
254  */
255 int CDECL _ltoa_s(long value, char *str, size_t size, int radix)
256 {
257     unsigned long val;
258     unsigned int digit;
259     int is_negative;
260     char buffer[33], *pos;
261     size_t len;
262 
263     if (!MSVCRT_CHECK_PMT(str != NULL) || !MSVCRT_CHECK_PMT(size > 0) ||
264         !MSVCRT_CHECK_PMT(radix >= 2) || !MSVCRT_CHECK_PMT(radix <= 36))
265     {
266         if (str && size)
267             str[0] = '\0';
268 
269 #ifndef _LIBCNT_
270         *_errno() = EINVAL;
271 #endif
272         return EINVAL;
273     }
274 
275     if (value < 0 && radix == 10)
276     {
277         is_negative = 1;
278         val = -value;
279     }
280     else
281     {
282         is_negative = 0;
283         val = value;
284     }
285 
286     pos = buffer + 32;
287     *pos = '\0';
288 
289     do
290     {
291         digit = val % radix;
292         val /= radix;
293 
294         if (digit < 10)
295             *--pos = '0' + digit;
296         else
297             *--pos = 'a' + digit - 10;
298     }
299     while (val != 0);
300 
301     if (is_negative)
302         *--pos = '-';
303 
304     len = buffer + 33 - pos;
305     if (len > size)
306     {
307         size_t i;
308         char *p = str;
309 
310         /* Copy the temporary buffer backwards up to the available number of
311          * characters. Don't copy the negative sign if present. */
312 
313         if (is_negative)
314         {
315             p++;
316             size--;
317         }
318 
319         for (pos = buffer + 31, i = 0; i < size; i++)
320             *p++ = *pos--;
321 
322         str[0] = '\0';
323         MSVCRT_INVALID_PMT("str[size] is too small", ERANGE);
324         return ERANGE;
325     }
326 
327     memcpy(str, pos, len);
328     return 0;
329 }
330 
331 /*
332  * @implemented
333  */
334 char *
335 CDECL
336 _ultoa(unsigned long value, char *string, int radix)
337 {
338     char buffer[33];
339     char *pos;
340     int digit;
341 
342     pos = &buffer[32];
343     *pos = '\0';
344 
345     do {
346 	digit = value % radix;
347 	value = value / radix;
348 	if (digit < 10) {
349 	    *--pos = '0' + digit;
350 	} else {
351 	    *--pos = 'a' + digit - 10;
352 	} /* if */
353     } while (value != 0L);
354 
355     memcpy(string, pos, &buffer[32] - pos + 1);
356 
357     return string;
358 }
359