format.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * @Author: jiejie
  3. * @Github: https://github.com/jiejieTop
  4. * @Date: 2019-12-25 23:54:19
  5. * @LastEditTime: 2020-06-17 15:23:09
  6. * @Description: the code belongs to jiejie, please keep the author insalof_formation and source code according to the license.
  7. */
  8. #include "format.h"
  9. #include "salof_defconfig.h"
  10. #ifdef SALOF_USING_LOG
  11. static int _get_atoi(const char **str)
  12. {
  13. int n;
  14. for (n = 0; is_digit(**str); (*str)++)
  15. n = n * 10 + **str - '0';
  16. return n;
  17. }
  18. static void _buff_put_char(char *buf, unsigned int *pos, unsigned int max, char c)
  19. {
  20. if (*pos < max)
  21. buf[(*pos)] = c;
  22. (*pos)++;
  23. }
  24. /**
  25. * Formats an integer number
  26. * buf - buffer to print into
  27. * len - current position in buffer
  28. * maxlen - last valid position in buf
  29. * num - number to print
  30. * base - it's base
  31. * width - how many spaces this should have; padding
  32. * flags - above F flags
  33. */
  34. static void _salof_format_int(char *buf, unsigned int *len, unsigned int maxlen,
  35. signed long long num, int base, int width, int flags)
  36. {
  37. char nbuf[64], sign = 0;
  38. char altb[8]; // small buf for sign and #
  39. int n = num;
  40. int npad; // number of pads
  41. char pchar = ' '; // padding character
  42. char *digits = "0123456789ABCDEF";
  43. char *ldigits = "0123456789abcdef";
  44. int i, j;
  45. if (base < 2 || base > 16)
  46. return;
  47. if (flags & F_SMALL) digits = ldigits;
  48. if (flags & F_LEFT) flags &= ~F_ZEROPAD;
  49. if ((flags & F_SIGNED) && num < 0) {
  50. n = -num;
  51. sign = '-';
  52. } else if (flags & F_PLUS) {
  53. sign = '+';
  54. } else if (flags & F_SPACE)
  55. sign = ' ';
  56. i = 0;
  57. do {
  58. nbuf[i++] = digits[n % base];
  59. n = n / base;
  60. } while (n > 0);
  61. j = 0;
  62. if (sign) altb[j++] = sign;
  63. if (flags & F_ALTERNATE) {
  64. if (base == 8 || base == 16) {
  65. altb[j++] = '0';
  66. if (base == 16)
  67. altb[j++] = (flags & F_SMALL) ? 'x' : 'X';
  68. }
  69. }
  70. altb[j] = 0;
  71. npad = width > i + j ? width - i - j : 0;
  72. if (width > i + j)
  73. npad = width - i - j;
  74. if (npad > 0 && ((flags & F_LEFT) == 0)) {
  75. if (flags & F_ZEROPAD) {
  76. for (j = 0; altb[j]; j++)
  77. _buff_put_char(buf, len, maxlen, altb[j]);
  78. altb[0] = 0;
  79. }
  80. while (npad-- > 0)
  81. _buff_put_char(buf, len, maxlen, (flags & F_ZEROPAD) ? '0' : ' ');
  82. }
  83. for (j = 0; altb[j]; j++)
  84. _buff_put_char(buf, len, maxlen, altb[j]);
  85. while (i-- > 0)
  86. _buff_put_char(buf, len, maxlen, nbuf[i]);
  87. if (npad > 0 && (flags & F_LEFT))
  88. while(npad-- > 0)
  89. _buff_put_char(buf, len, maxlen, pchar);
  90. }
  91. static void _salof_format_char(char *buf, unsigned int *pos, unsigned int max, char c,
  92. int width, int flags)
  93. {
  94. int npad = 0;
  95. if (width > 0) npad = width - 1;
  96. if (npad < 0) npad = 0;
  97. if (npad && ((flags & F_LEFT) == 0))
  98. while (npad-- > 0)
  99. _buff_put_char(buf, pos, max, ' ');
  100. _buff_put_char(buf, pos, max, c);
  101. if (npad && (flags & F_LEFT))
  102. while (npad-- > 0)
  103. _buff_put_char(buf, pos, max, ' ');
  104. }
  105. /**
  106. * strlen()
  107. */
  108. static unsigned int _str_len(char *s)
  109. {
  110. unsigned int i;
  111. for (i = 0; *s; i++, s++)
  112. ;
  113. return i;
  114. }
  115. static void _salof_format_str(char *buf, unsigned int *pos, unsigned int max, char *s,
  116. int width, int flags)
  117. {
  118. int npad = 0;
  119. if (width > 0) npad = width - _str_len(s);
  120. if (npad < 0) npad = 0;
  121. if (npad && ((flags & F_LEFT) == 0))
  122. while (npad-- > 0)
  123. _buff_put_char(buf, pos, max, ' ');
  124. while (*s)
  125. _buff_put_char(buf, pos, max, *s++);
  126. if (npad && (flags & F_LEFT))
  127. while (npad-- > 0)
  128. _buff_put_char(buf, pos, max, ' ');
  129. }
  130. /***********************************************************************************************************************/
  131. /**
  132. * Shrinked down, vsnprintf implementation.
  133. * This will not handle floating numbers (yet).
  134. */
  135. int salof_format_nstr(char *buf, unsigned int size, const char *fmt, va_list ap)
  136. {
  137. unsigned int n = 0;
  138. char c, *s;
  139. char state = 0;
  140. signed long long num;
  141. int base;
  142. int flags, width, precision, lflags;
  143. if (!buf) size = 0;
  144. for (;;) {
  145. c = *fmt++;
  146. if (state == S_DEFAULT) {
  147. if (c == '%') {
  148. state = S_FLAGS;
  149. flags = 0;
  150. } else {
  151. _buff_put_char(buf, &n, size, c);
  152. }
  153. } else if (state == S_FLAGS) {
  154. switch (c) {
  155. case '#': flags |= F_ALTERNATE; break;
  156. case '0': flags |= F_ZEROPAD; break;
  157. case '-': flags |= F_LEFT; break;
  158. case ' ': flags |= F_SPACE; break;
  159. case '+': flags |= F_PLUS; break;
  160. case '\'':
  161. case 'I' : break; // not yet used
  162. default: fmt--; width = 0; state = S_WIDTH;
  163. }
  164. } else if (state == S_WIDTH) {
  165. if (c == '*') {
  166. width = va_arg(ap, int);
  167. if (width < 0) {
  168. width = -width;
  169. flags |= F_LEFT;
  170. }
  171. } else if (is_digit(c) && c > '0') {
  172. fmt--;
  173. width = _get_atoi(&fmt);
  174. } else {
  175. fmt--;
  176. precision = -1;
  177. state = S_PRECIS;
  178. }
  179. } else if (state == S_PRECIS) {
  180. // Ignored for now, but skip it
  181. if (c == '.') {
  182. if (is_digit(*fmt))
  183. precision = _get_atoi(&fmt);
  184. else if (*fmt == '*')
  185. precision = va_arg(ap, int);
  186. precision = precision < 0 ? 0 : precision;
  187. } else
  188. fmt--;
  189. lflags = 0;
  190. state = S_LENGTH;
  191. } else if (state == S_LENGTH) {
  192. switch(c) {
  193. case 'h': lflags = lflags == L_CHAR ? L_SHORT : L_CHAR; break;
  194. case 'l': lflags = lflags == L_LONG ? L_LLONG : L_LONG; break;
  195. case 'L': lflags = L_DOUBLE; break;
  196. default: fmt--; state = S_CONV;
  197. }
  198. } else if (state == S_CONV) {
  199. if (c == 'd' || c == 'i' || c == 'o' || c == 'b' || c == 'u'
  200. || c == 'x' || c == 'X') {
  201. if (lflags == L_LONG)
  202. num = va_arg(ap, int);
  203. else if (lflags & (L_LLONG | L_DOUBLE))
  204. num = va_arg(ap, signed long long);
  205. else if (c == 'd' || c == 'i')
  206. num = va_arg(ap, int);
  207. else
  208. num = (unsigned int) va_arg(ap, int);
  209. base = 10;
  210. if (c == 'd' || c == 'i') {
  211. flags |= F_SIGNED;
  212. } else if (c == 'x' || c == 'X') {
  213. flags |= c == 'x' ? F_SMALL : 0;
  214. base = 16;
  215. } else if (c == 'o') {
  216. base = 8;
  217. } else if (c == 'b') {
  218. base = 2;
  219. }
  220. _salof_format_int(buf, &n, size, num, base, width, flags);
  221. } else if (c == 'p') {
  222. num = (size_t) va_arg(ap, void *);
  223. base = 16;
  224. flags |= F_SMALL | F_ALTERNATE;
  225. _salof_format_int(buf, &n, size, num, base, width, flags);
  226. } else if (c == 's') {
  227. s = va_arg(ap, char *);
  228. if (!s)
  229. s = "(null)";
  230. _salof_format_str(buf, &n, size, s, width, flags);
  231. } else if (c == 'c') {
  232. c = va_arg(ap, int);
  233. _salof_format_char(buf, &n, size, c, width, flags);
  234. } else if (c == '%') {
  235. _buff_put_char(buf, &n, size, c);
  236. } else {
  237. _buff_put_char(buf, &n, size, '%');
  238. _buff_put_char(buf, &n, size, c);
  239. }
  240. state = S_DEFAULT;
  241. }
  242. if (c == 0)
  243. break;
  244. }
  245. n--;
  246. if (n < size)
  247. buf[n] = 0;
  248. else if (size > 0)
  249. buf[size - 1] = 0;
  250. return n;
  251. }
  252. #endif