1 /* taken from wine ntdll and msvcrt string.c */
2
3 #include <precomp.h>
4
5 /*
6 * @implemented
7 */
8 char *
9 CDECL
_i64toa(__int64 value,char * string,int radix)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 */
_i64toa_s(__int64 value,char * str,size_t size,int radix)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
_ui64toa(unsigned __int64 value,char * string,int radix)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 */
_ui64toa_s(unsigned __int64 value,char * str,size_t size,int radix)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 */
_itoa_s(int value,char * str,size_t size,int radix)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
_itoa(int value,char * string,int radix)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
_ltoa(long value,char * string,int radix)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 */
_ltoa_s(long value,char * str,size_t size,int radix)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
_ultoa(unsigned long value,char * string,int radix)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