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