printf.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #define ALWAYS_INLINE inline __attribute__ ((always_inline))
  2. typedef unsigned char byte;
  3. typedef unsigned short word;
  4. typedef unsigned int dword;
  5. ALWAYS_INLINE size_t strlen(const char* str)
  6. {
  7. size_t len = 0;
  8. while (*(str++))
  9. ++len;
  10. return len;
  11. }
  12. static constexpr const char* h = "0123456789abcdef";
  13. template<typename PutChFunc>
  14. ALWAYS_INLINE int printHex(PutChFunc putch, char*& bufptr, dword number, byte fields)
  15. {
  16. int ret = 0;
  17. byte shr_count = fields * 4;
  18. while (shr_count) {
  19. shr_count -= 4;
  20. putch(bufptr, h[(number >> shr_count) & 0x0F]);
  21. ++ret;
  22. }
  23. return ret;
  24. }
  25. template<typename PutChFunc>
  26. ALWAYS_INLINE int printNumber(PutChFunc putch, char*& bufptr, dword number, bool leftPad, bool zeroPad, dword fieldWidth)
  27. {
  28. dword divisor = 1000000000;
  29. char ch;
  30. char padding = 1;
  31. char buf[16];
  32. char* p = buf;
  33. for (;;) {
  34. ch = '0' + (number / divisor);
  35. number %= divisor;
  36. if (ch != '0')
  37. padding = 0;
  38. if (!padding || divisor == 1)
  39. *(p++) = ch;
  40. if (divisor == 1)
  41. break;
  42. divisor /= 10;
  43. }
  44. size_t numlen = p - buf;
  45. if (!fieldWidth || fieldWidth < numlen)
  46. fieldWidth = numlen;
  47. if (!leftPad) {
  48. for (unsigned i = 0; i < fieldWidth - numlen; ++i) {
  49. putch(bufptr, zeroPad ? '0' : ' ');
  50. }
  51. }
  52. for (unsigned i = 0; i < numlen; ++i) {
  53. putch(bufptr, buf[i]);
  54. }
  55. if (leftPad) {
  56. for (unsigned i = 0; i < fieldWidth - numlen; ++i) {
  57. putch(bufptr, ' ');
  58. }
  59. }
  60. return fieldWidth;
  61. }
  62. template<typename PutChFunc>
  63. ALWAYS_INLINE int printString(PutChFunc putch, char*& bufptr, const char* str, bool leftPad, dword fieldWidth)
  64. {
  65. size_t len = strlen(str);
  66. if (!fieldWidth || fieldWidth < len)
  67. fieldWidth = len;
  68. if (!leftPad) {
  69. for (unsigned i = 0; i < fieldWidth - len; ++i)
  70. putch(bufptr, ' ');
  71. }
  72. for (unsigned i = 0; i < len; ++i) {
  73. putch(bufptr, str[i]);
  74. }
  75. if (leftPad) {
  76. for (unsigned i = 0; i < fieldWidth - len; ++i)
  77. putch(bufptr, ' ');
  78. }
  79. return fieldWidth;
  80. }
  81. template<typename PutChFunc>
  82. ALWAYS_INLINE int printSignedNumber(PutChFunc putch, char*& bufptr, int number, bool leftPad, bool zeroPad, dword fieldWidth)
  83. {
  84. if (number < 0) {
  85. putch(bufptr, '-');
  86. return printNumber(putch, bufptr, 0 - number, leftPad, zeroPad, fieldWidth) + 1;
  87. }
  88. return printNumber(putch, bufptr, number, leftPad, zeroPad, fieldWidth);
  89. }
  90. template<typename PutChFunc>
  91. ALWAYS_INLINE int printfInternal(PutChFunc putch, char* buffer, const char*& fmt, char*& ap)
  92. {
  93. const char *p;
  94. int ret = 0;
  95. char* bufptr = buffer;
  96. for (p = fmt; *p; ++p) {
  97. bool leftPad = false;
  98. bool zeroPad = false;
  99. unsigned fieldWidth = 0;
  100. if (*p == '%' && *(p + 1)) {
  101. one_more:
  102. ++p;
  103. if (*p == ' ') {
  104. leftPad = true;
  105. if (*(p + 1))
  106. goto one_more;
  107. }
  108. if (!zeroPad && !fieldWidth && *p == '0') {
  109. zeroPad = true;
  110. if (*(p + 1))
  111. goto one_more;
  112. }
  113. if (*p >= '0' && *p <= '9') {
  114. fieldWidth *= 10;
  115. fieldWidth += *p - '0';
  116. if (*(p + 1))
  117. goto one_more;
  118. }
  119. switch( *p )
  120. {
  121. case 's':
  122. {
  123. const char* sp = va_arg(ap, const char*);
  124. ret += printString(putch, bufptr, sp ? sp : "(null)", leftPad, fieldWidth);
  125. }
  126. break;
  127. case 'd':
  128. ret += printSignedNumber(putch, bufptr, va_arg(ap, int), leftPad, zeroPad, fieldWidth);
  129. break;
  130. case 'u':
  131. ret += printNumber(putch, bufptr, va_arg(ap, dword), leftPad, zeroPad, fieldWidth);
  132. break;
  133. case 'x':
  134. ret += printHex(putch, bufptr, va_arg(ap, dword), 8);
  135. break;
  136. case 'w':
  137. ret += printHex(putch, bufptr, va_arg(ap, int), 4);
  138. break;
  139. case 'b':
  140. ret += printHex(putch, bufptr, va_arg(ap, int), 2);
  141. break;
  142. case 'c':
  143. putch(bufptr, (char)va_arg(ap, int));
  144. ++ret;
  145. break;
  146. case 'p':
  147. putch(bufptr, '0');
  148. putch(bufptr, 'x');
  149. ret += 2;
  150. ret += printHex(putch, bufptr, va_arg(ap, dword), 8);
  151. break;
  152. }
  153. }
  154. else {
  155. putch(bufptr, *p);
  156. ++ret;
  157. }
  158. }
  159. return ret;
  160. }