xtox_s.inl 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. //
  2. // Copyright (c) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  4. //
  5. /***
  6. *xtoa.c - convert integers/longs to ASCII string
  7. *
  8. *
  9. *Purpose:
  10. * The module has code to convert integers/longs to ASCII strings. See
  11. *
  12. *******************************************************************************/
  13. #ifdef _UNICODE
  14. #define xtox_s xtow_s
  15. #define _itox_s _itow_s
  16. #define _ltox_s _ltow_s
  17. #define _ultox_s _ultow_s
  18. #define x64tox_s x64tow_s
  19. #define _i64tox_s _i64tow_s
  20. #define _ui64tox_s _ui64tow_s
  21. #define xtox xtow
  22. #define _itox _itow
  23. #define _ltox _ltow
  24. #define _ultox _ultow
  25. #define x64tox x64tow
  26. #define _i64tox _i64tow
  27. #define _ui64tox _ui64tow
  28. #else /* _UNICODE */
  29. #define xtox_s xtoa_s
  30. #define _itox_s _itoa_s
  31. #define _ltox_s _ltoa_s
  32. #define _ultox_s _ultoa_s
  33. #define x64tox_s x64toa_s
  34. #define _i64tox_s _i64toa_s
  35. #define _ui64tox_s _ui64toa_s
  36. #define xtox xtoa
  37. #define _itox _itoa
  38. #define _ltox _ltoa
  39. #define _ultox _ultoa
  40. #define x64tox x64toa
  41. #define _i64tox _i64toa
  42. #define _ui64tox _ui64toa
  43. #endif /* _UNICODE */
  44. /***
  45. *char *_itoa_s, *_ltoa_s, *_ultoa_s(val, buf, sizeInTChars, radix) - convert binary int to ASCII
  46. * string
  47. *
  48. *Purpose:
  49. * Converts an int to a character string.
  50. *
  51. *Entry:
  52. * val - number to be converted (int, long or unsigned long)
  53. * char *buf - ptr to buffer to place result
  54. * size_t sizeInTChars - size of the destination buffer
  55. * int radix - base to convert into
  56. *
  57. *Exit:
  58. * Fills in space pointed to by buf with string result.
  59. * Returns the errno_t: err != 0 means that something went wrong, and
  60. * an empty string (buf[0] = 0) is returned.
  61. *
  62. *Exceptions:
  63. * Input parameters and buffer length are validated.
  64. * Refer to the validation section of the function.
  65. *
  66. *******************************************************************************/
  67. /* helper routine that does the main job. */
  68. #ifdef _SECURE_ITOA
  69. errno_t __stdcall xtox_s
  70. (
  71. unsigned long val,
  72. TCHAR *buf,
  73. size_t sizeInTChars,
  74. unsigned radix,
  75. int is_neg
  76. )
  77. #else /* _SECURE_ITOA */
  78. void __stdcall xtox
  79. (
  80. unsigned long val,
  81. TCHAR *buf,
  82. unsigned radix,
  83. int is_neg
  84. )
  85. #endif /* _SECURE_ITOA */
  86. {
  87. TCHAR *p; /* pointer to traverse string */
  88. TCHAR *firstdig; /* pointer to first digit */
  89. TCHAR temp; /* temp char */
  90. unsigned digval; /* value of digit */
  91. #ifdef _SECURE_ITOA
  92. size_t length; /* current length of the string */
  93. /* validation section */
  94. _VALIDATE_RETURN_ERRCODE(buf != NULL, EINVAL);
  95. _VALIDATE_RETURN_ERRCODE(sizeInTChars > 0, EINVAL);
  96. _RESET_STRING(buf, sizeInTChars);
  97. _VALIDATE_RETURN_ERRCODE(sizeInTChars > (size_t)(is_neg ? 2 : 1), ERANGE);
  98. _VALIDATE_RETURN_ERRCODE(2 <= radix && radix <= 36, EINVAL);
  99. length = 0;
  100. #endif /* _SECURE_ITOA */
  101. p = buf;
  102. if (is_neg) {
  103. /* negative, so output '-' and negate */
  104. *p++ = _T('-');
  105. #ifdef _SECURE_ITOA
  106. length++;
  107. #endif /* _SECURE_ITOA */
  108. val = (unsigned long)(-(long)val);
  109. }
  110. firstdig = p; /* save pointer to first digit */
  111. do {
  112. digval = (unsigned) (val % radix);
  113. val /= radix; /* get next digit */
  114. /* convert to ascii and store */
  115. if (digval > 9)
  116. *p++ = (TCHAR) (digval - 10 + _T('a')); /* a letter */
  117. else
  118. *p++ = (TCHAR) (digval + _T('0')); /* a digit */
  119. #ifndef _SECURE_ITOA
  120. } while (val > 0);
  121. #else /* _SECURE_ITOA */
  122. length++;
  123. } while (val > 0 && length < sizeInTChars);
  124. /* Check for buffer overrun */
  125. if (length >= sizeInTChars)
  126. {
  127. buf[0] = '\0';
  128. _VALIDATE_RETURN_ERRCODE(length < sizeInTChars, ERANGE);
  129. }
  130. #endif /* _SECURE_ITOA */
  131. /* We now have the digit of the number in the buffer, but in reverse
  132. order. Thus we reverse them now. */
  133. *p-- = _T('\0'); /* terminate string; p points to last digit */
  134. do {
  135. temp = *p;
  136. *p = *firstdig;
  137. *firstdig = temp; /* swap *p and *firstdig */
  138. --p;
  139. ++firstdig; /* advance to next two digits */
  140. } while (firstdig < p); /* repeat until halfway */
  141. #ifdef _SECURE_ITOA
  142. return 0;
  143. #endif /* _SECURE_ITOA */
  144. }
  145. /* Actual functions just call conversion helper with neg flag set correctly,
  146. and return pointer to buffer. */
  147. #ifdef _SECURE_ITOA
  148. errno_t __cdecl _itox_s (
  149. int val,
  150. TCHAR *buf,
  151. size_t sizeInTChars,
  152. int radix
  153. )
  154. {
  155. errno_t e = 0;
  156. if (radix == 10 && val < 0)
  157. e = xtox_s((unsigned long)val, buf, sizeInTChars, (unsigned)radix, 1);
  158. else
  159. e = xtox_s((unsigned long)(unsigned int)val, buf, sizeInTChars, (unsigned)radix, 0);
  160. return e;
  161. }
  162. errno_t __cdecl _ltox_s (
  163. long val,
  164. TCHAR *buf,
  165. size_t sizeInTChars,
  166. int radix
  167. )
  168. {
  169. return xtox_s((unsigned long)val, buf, sizeInTChars, (unsigned)radix, (radix == 10 && val < 0));
  170. }
  171. errno_t __cdecl _ultox_s (
  172. unsigned long val,
  173. TCHAR *buf,
  174. size_t sizeInTChars,
  175. int radix
  176. )
  177. {
  178. return xtox_s(val, buf, sizeInTChars, (unsigned)radix, 0);
  179. }
  180. #else /* _SECURE_ITOA */
  181. /***
  182. *char *_itoa, *_ltoa, *_ultoa(val, buf, radix) - convert binary int to ASCII
  183. * string
  184. *
  185. *Purpose:
  186. * Converts an int to a character string.
  187. *
  188. *Entry:
  189. * val - number to be converted (int, long or unsigned long)
  190. * int radix - base to convert into
  191. * char *buf - ptr to buffer to place result
  192. *
  193. *Exit:
  194. * fills in space pointed to by buf with string result
  195. * returns a pointer to this buffer
  196. *
  197. *Exceptions:
  198. * Input parameters are validated. The buffer is assumed to be big enough to
  199. * contain the string. Refer to the validation section of the function.
  200. *
  201. *******************************************************************************/
  202. /* Actual functions just call conversion helper with neg flag set correctly,
  203. and return pointer to buffer. */
  204. TCHAR * __cdecl _itox (
  205. int val,
  206. TCHAR *buf,
  207. int radix
  208. )
  209. {
  210. if (radix == 10 && val < 0)
  211. xtox((unsigned long)val, buf, radix, 1);
  212. else
  213. xtox((unsigned long)(unsigned int)val, buf, radix, 0);
  214. return buf;
  215. }
  216. TCHAR * __cdecl _ltox (
  217. long val,
  218. TCHAR *buf,
  219. int radix
  220. )
  221. {
  222. xtox((unsigned long)val, buf, radix, (radix == 10 && val < 0));
  223. return buf;
  224. }
  225. TCHAR * __cdecl _ultox (
  226. unsigned long val,
  227. TCHAR *buf,
  228. int radix
  229. )
  230. {
  231. xtox(val, buf, radix, 0);
  232. return buf;
  233. }
  234. #endif /* _SECURE_ITOA */
  235. #ifndef _NO_INT64
  236. /***
  237. *char *_i64toa_s(val, buf, sizeInTChars, radix) - convert binary int to ASCII
  238. * string
  239. *
  240. *Purpose:
  241. * Converts an int64 to a character string.
  242. *
  243. *Entry:
  244. * val - number to be converted
  245. * char *buf - ptr to buffer to place result
  246. * size_t sizeInTChars - size of the destination buffer
  247. * int radix - base to convert into
  248. *
  249. *Exit:
  250. * Fills in space pointed to by buf with string result.
  251. * Returns the errno_t: err != 0 means that something went wrong, and
  252. * an empty string (buf[0] = 0) is returned.
  253. *
  254. *Exceptions:
  255. * Input parameters and buffer length are validated.
  256. * Refer to the validation section of the function.
  257. *
  258. *******************************************************************************/
  259. #ifdef _SECURE_ITOA
  260. errno_t __fastcall x64tox_s
  261. (/* stdcall is faster and smaller... Might as well use it for the helper. */
  262. unsigned __int64 val,
  263. TCHAR *buf,
  264. size_t sizeInTChars,
  265. unsigned radix,
  266. int is_neg
  267. )
  268. #else /* _SECURE_ITOA */
  269. void __fastcall x64tox
  270. (/* stdcall is faster and smaller... Might as well use it for the helper. */
  271. unsigned __int64 val,
  272. TCHAR *buf,
  273. unsigned radix,
  274. int is_neg
  275. )
  276. #endif /* _SECURE_ITOA */
  277. {
  278. TCHAR *p; /* pointer to traverse string */
  279. TCHAR *firstdig; /* pointer to first digit */
  280. TCHAR temp; /* temp char */
  281. unsigned digval; /* value of digit */
  282. #ifdef _SECURE_ITOA
  283. size_t length; /* current length of the string */
  284. /* validation section */
  285. _VALIDATE_RETURN_ERRCODE(buf != NULL, EINVAL);
  286. _VALIDATE_RETURN_ERRCODE(sizeInTChars > 0, EINVAL);
  287. _RESET_STRING(buf, sizeInTChars);
  288. _VALIDATE_RETURN_ERRCODE(sizeInTChars > (size_t)(is_neg ? 2 : 1), ERANGE);
  289. _VALIDATE_RETURN_ERRCODE(2 <= radix && radix <= 36, EINVAL);
  290. length = 0;
  291. #endif /* _SECURE_ITOA */
  292. p = buf;
  293. if ( is_neg )
  294. {
  295. *p++ = _T('-'); /* negative, so output '-' and negate */
  296. #ifdef _SECURE_ITOA
  297. length++;
  298. #endif /* _SECURE_ITOA */
  299. val = (unsigned __int64)(-(__int64)val);
  300. }
  301. firstdig = p; /* save pointer to first digit */
  302. do {
  303. digval = (unsigned) (val % radix);
  304. val /= radix; /* get next digit */
  305. /* convert to ascii and store */
  306. if (digval > 9)
  307. *p++ = (TCHAR) (digval - 10 + _T('a')); /* a letter */
  308. else
  309. *p++ = (TCHAR) (digval + _T('0')); /* a digit */
  310. #ifndef _SECURE_ITOA
  311. } while (val > 0);
  312. #else /* _SECURE_ITOA */
  313. length++;
  314. } while (val > 0 && length < sizeInTChars);
  315. /* Check for buffer overrun */
  316. if (length >= sizeInTChars)
  317. {
  318. buf[0] = '\0';
  319. _VALIDATE_RETURN_ERRCODE(length < sizeInTChars, ERANGE);
  320. }
  321. #endif /* _SECURE_ITOA */
  322. /* We now have the digit of the number in the buffer, but in reverse
  323. order. Thus we reverse them now. */
  324. *p-- = _T('\0'); /* terminate string; p points to last digit */
  325. do {
  326. temp = *p;
  327. *p = *firstdig;
  328. *firstdig = temp; /* swap *p and *firstdig */
  329. --p;
  330. ++firstdig; /* advance to next two digits */
  331. } while (firstdig < p); /* repeat until halfway */
  332. #ifdef _SECURE_ITOA
  333. return 0;
  334. #endif /* _SECURE_ITOA */
  335. }
  336. #ifdef _SECURE_ITOA
  337. /* Actual functions just call conversion helper with neg flag set correctly,
  338. and return pointer to buffer. */
  339. errno_t __cdecl _i64tox_s (
  340. long long val,
  341. TCHAR *buf,
  342. size_t sizeInTChars,
  343. int radix
  344. )
  345. {
  346. return x64tox_s((unsigned __int64)val, buf, sizeInTChars, (unsigned)radix, (radix == 10 && val < 0));
  347. }
  348. errno_t __cdecl _ui64tox_s (
  349. unsigned long long val,
  350. TCHAR *buf,
  351. size_t sizeInTChars,
  352. int radix
  353. )
  354. {
  355. return x64tox_s(val, buf, sizeInTChars, (unsigned)radix, 0);
  356. }
  357. #else /* _SECURE_ITOA */
  358. /***
  359. *char *_i64toa(val, buf, radix) - convert binary int to ASCII
  360. * string
  361. *
  362. *Purpose:
  363. * Converts an int64 to a character string.
  364. *
  365. *Entry:
  366. * val - number to be converted
  367. * int radix - base to convert into
  368. * char *buf - ptr to buffer to place result
  369. *
  370. *Exit:
  371. * fills in space pointed to by buf with string result
  372. * returns a pointer to this buffer
  373. *
  374. *Exceptions:
  375. * Input parameters are validated. The buffer is assumed to be big enough to
  376. * contain the string. Refer to the validation section of the function.
  377. *
  378. *******************************************************************************/
  379. /* Actual functions just call conversion helper with neg flag set correctly,
  380. and return pointer to buffer. */
  381. TCHAR * __cdecl _i64tox (
  382. __int64 val,
  383. TCHAR *buf,
  384. int radix
  385. )
  386. {
  387. x64tox((unsigned __int64)val, buf, radix, (radix == 10 && val < 0));
  388. return buf;
  389. }
  390. TCHAR * __cdecl _ui64tox (
  391. unsigned __int64 val,
  392. TCHAR *buf,
  393. int radix
  394. )
  395. {
  396. x64tox(val, buf, radix, 0);
  397. return buf;
  398. }
  399. #endif /* _SECURE_ITOA */
  400. #endif /* _NO_INT64 */