sprintf.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Copyright (C) 1997 Robey Pointer
  3. * Copyright (C) 1999 - 2002 Eggheads Development Team
  4. * Copyright (C) 2002 - 2014 Bryan Drewery
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. /* sprintf.c
  21. *
  22. */
  23. #include "common.h"
  24. #include "sprintf.h"
  25. #include "base64.h"
  26. #include <stdarg.h>
  27. static char buf_convert[20] = "";
  28. static char *int_to_string(const long val, const unsigned int base)
  29. {
  30. buf_convert[sizeof(buf_convert) - 1] = 0;
  31. if (!val) {
  32. buf_convert[sizeof(buf_convert) - 2] = '0';
  33. return buf_convert + sizeof(buf_convert) - 2;
  34. }
  35. bool negative = 0;
  36. long uval = val;
  37. if (val < 0) {
  38. negative = 1;
  39. uval = -val;
  40. }
  41. int place = sizeof(buf_convert) - 1;
  42. while (uval && place >= 0) {
  43. buf_convert[--place] = '0' + uval % base;
  44. uval /= base;
  45. }
  46. if (negative)
  47. buf_convert[--place] = '-';
  48. return buf_convert + place;
  49. }
  50. static char *unsigned_int_to_string(unsigned long val, const unsigned int base, bool caps = false)
  51. {
  52. buf_convert[sizeof(buf_convert) - 1] = 0;
  53. if (!val) {
  54. buf_convert[sizeof(buf_convert) - 2] = '0';
  55. return buf_convert + sizeof(buf_convert) - 2;
  56. }
  57. int place = sizeof(buf_convert) - 1;
  58. while (val && place >= 0) {
  59. buf_convert[--place] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")[val % base];
  60. val /= base;
  61. }
  62. return buf_convert + place;
  63. }
  64. size_t simple_vsnprintf(char *buf, size_t size, const char *format, va_list va)
  65. {
  66. char *s = NULL;
  67. char *fp = (char *) format;
  68. size_t c = 0;
  69. unsigned long i = 0;
  70. long width = 0;
  71. bool islong = 0, caps = false, width_modifier = false, rpad = false;
  72. char pad = ' ';
  73. re_eval:
  74. while (*fp && c < size - 1) {
  75. if (*fp == '%' || width_modifier) {
  76. re_eval_with_modifier:
  77. ++fp;
  78. if (unlikely(width_modifier)) {
  79. if (egg_isdigit(*fp)) {
  80. width = 10 * width + (*fp - '0');
  81. goto re_eval;
  82. } else
  83. width_modifier = false;
  84. }
  85. switch (*fp) {
  86. /* Left padding with zeroes */
  87. case '0':
  88. width_modifier = true;
  89. pad = '0';
  90. goto re_eval_with_modifier;
  91. /* Right padding with spaces */
  92. case '-':
  93. rpad = true;
  94. goto re_eval_with_modifier;
  95. /* Left padding with spaces */
  96. case '1':
  97. case '2':
  98. case '3':
  99. case '4':
  100. case '5':
  101. case '6':
  102. case '7':
  103. case '8':
  104. case '9':
  105. width_modifier = true;
  106. width = 10 * width + (*fp - '0');
  107. pad = ' ';
  108. goto re_eval_with_modifier;
  109. case 'z':
  110. case 'l':
  111. islong = 1;
  112. goto re_eval_with_modifier;
  113. case '^': //STRING
  114. caps = true;
  115. goto re_eval_with_modifier;
  116. case 's': //string
  117. s = va_arg(va, char *);
  118. break;
  119. case 'd': //int
  120. case 'i':
  121. if (islong) {
  122. i = va_arg(va, long);
  123. islong = 0;
  124. } else
  125. i = va_arg(va, int);
  126. s = int_to_string(i, 10);
  127. break;
  128. case 'D': //stupid eggdrop base64
  129. i = va_arg(va, int);
  130. s = int_to_base64((unsigned int) i);
  131. break;
  132. case 'u': //unsigned
  133. if (islong) {
  134. i = va_arg(va, unsigned long);
  135. islong = 0;
  136. } else
  137. i = va_arg(va, unsigned int);
  138. s = unsigned_int_to_string(i, 10);
  139. break;
  140. case 'X': //HEX
  141. caps = true;
  142. case 'x': //hex
  143. if (islong) {
  144. i = va_arg(va, unsigned long);
  145. islong = 0;
  146. } else
  147. i = va_arg(va, unsigned int);
  148. s = unsigned_int_to_string(i, 16, caps);
  149. caps = false;
  150. break;
  151. case '%': //%
  152. buf[c++] = *fp++;
  153. continue;
  154. case 'c': //char
  155. buf[c++] = (char) va_arg(va, int);
  156. fp++;
  157. continue;
  158. default:
  159. continue;
  160. }
  161. if (s) {
  162. if (unlikely(width > 0)) {
  163. width -= strlen(s);
  164. if (width < 0) width = 0;
  165. if (rpad) {
  166. width = -width;
  167. rpad = false;
  168. }
  169. }
  170. /* Left padding / right justification */
  171. if (unlikely(width > 0)) {
  172. while (width > 0 && c < size - 1) {
  173. buf[c++] = pad;
  174. --width;
  175. }
  176. width = 0;
  177. }
  178. /* Advance the buffer with content */
  179. if (unlikely(caps)) {
  180. while (*s && c < size - 1)
  181. buf[c++] = toupper(*s++);
  182. caps = false;
  183. } else {
  184. while (*s && c < size - 1)
  185. buf[c++] = *s++;
  186. }
  187. /* Right padding / left justification */
  188. while (width < 0 && c < size - 1) {
  189. buf[c++] = pad;
  190. ++width;
  191. }
  192. }
  193. fp++;
  194. } else
  195. buf[c++] = *fp++;
  196. }
  197. buf[c] = '\0';
  198. return c;
  199. }
  200. size_t simple_vsprintf(char *buf, const char *format, va_list va)
  201. {
  202. return simple_vsnprintf(buf, VSPRINTF_MAXSIZE, format, va);
  203. }
  204. size_t simple_snprintf2 (char *buf, size_t size, const char *format, ...)
  205. {
  206. size_t ret = 0;
  207. va_list va;
  208. va_start(va, format);
  209. ret = simple_vsnprintf(buf, size, format, va);
  210. va_end(va);
  211. return ret;
  212. }
  213. size_t simple_sprintf (char *buf, const char *format, ...)
  214. {
  215. size_t ret = 0;
  216. va_list va;
  217. va_start(va, format);
  218. ret = simple_vsprintf(buf, format, va);
  219. va_end(va);
  220. return ret;
  221. }
  222. size_t simple_snprintf (char *buf, size_t size, const char *format, ...)
  223. {
  224. size_t ret = 0;
  225. va_list va;
  226. va_start(va, format);
  227. ret = simple_vsnprintf(buf, size, format, va);
  228. va_end(va);
  229. return ret;
  230. }