123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- typedef unsigned char byte;
- typedef unsigned short word;
- typedef unsigned int dword;
- [[gnu::always_inline]] inline size_t strlen(const char* str)
- {
- size_t len = 0;
- while (*(str++))
- ++len;
- return len;
- }
- static constexpr const char* h = "0123456789abcdef";
- template<typename PutChFunc>
- [[gnu::always_inline]] inline int print_hex(PutChFunc putch, char*& bufptr, dword number, byte fields)
- {
- int ret = 0;
- byte shr_count = fields * 4;
- while (shr_count) {
- shr_count -= 4;
- putch(bufptr, h[(number >> shr_count) & 0x0F]);
- ++ret;
- }
- return ret;
- }
- template<typename PutChFunc>
- [[gnu::always_inline]] inline int print_number(PutChFunc putch, char*& bufptr, dword number, bool leftPad, bool zeroPad, dword fieldWidth)
- {
- dword divisor = 1000000000;
- char ch;
- char padding = 1;
- char buf[16];
- char* p = buf;
- for (;;) {
- ch = '0' + (number / divisor);
- number %= divisor;
- if (ch != '0')
- padding = 0;
- if (!padding || divisor == 1)
- *(p++) = ch;
- if (divisor == 1)
- break;
- divisor /= 10;
- }
- size_t numlen = p - buf;
- if (!fieldWidth || fieldWidth < numlen)
- fieldWidth = numlen;
- if (!leftPad) {
- for (unsigned i = 0; i < fieldWidth - numlen; ++i) {
- putch(bufptr, zeroPad ? '0' : ' ');
- }
- }
- for (unsigned i = 0; i < numlen; ++i) {
- putch(bufptr, buf[i]);
- }
- if (leftPad) {
- for (unsigned i = 0; i < fieldWidth - numlen; ++i) {
- putch(bufptr, ' ');
- }
- }
- return fieldWidth;
- }
- template<typename PutChFunc>
- [[gnu::always_inline]] inline int print_octal_number(PutChFunc putch, char*& bufptr, dword number, bool leftPad, bool zeroPad, dword fieldWidth)
- {
- dword divisor = 134217728;
- char ch;
- char padding = 1;
- char buf[32];
- char* p = buf;
- for (;;) {
- ch = '0' + (number / divisor);
- number %= divisor;
- if (ch != '0')
- padding = 0;
- if (!padding || divisor == 1)
- *(p++) = ch;
- if (divisor == 1)
- break;
- divisor /= 8;
- }
- size_t numlen = p - buf;
- if (!fieldWidth || fieldWidth < numlen)
- fieldWidth = numlen;
- if (!leftPad) {
- for (unsigned i = 0; i < fieldWidth - numlen; ++i) {
- putch(bufptr, zeroPad ? '0' : ' ');
- }
- }
- for (unsigned i = 0; i < numlen; ++i) {
- putch(bufptr, buf[i]);
- }
- if (leftPad) {
- for (unsigned i = 0; i < fieldWidth - numlen; ++i) {
- putch(bufptr, ' ');
- }
- }
- return fieldWidth;
- }
- template<typename PutChFunc>
- [[gnu::always_inline]] inline int print_string(PutChFunc putch, char*& bufptr, const char* str, bool leftPad, dword fieldWidth)
- {
- size_t len = strlen(str);
- if (!fieldWidth || fieldWidth < len)
- fieldWidth = len;
- if (!leftPad) {
- for (unsigned i = 0; i < fieldWidth - len; ++i)
- putch(bufptr, ' ');
- }
- for (unsigned i = 0; i < len; ++i) {
- putch(bufptr, str[i]);
- }
- if (leftPad) {
- for (unsigned i = 0; i < fieldWidth - len; ++i)
- putch(bufptr, ' ');
- }
- return fieldWidth;
- }
- template<typename PutChFunc>
- [[gnu::always_inline]] inline int print_signed_number(PutChFunc putch, char*& bufptr, int number, bool leftPad, bool zeroPad, dword fieldWidth)
- {
- if (number < 0) {
- putch(bufptr, '-');
- return print_number(putch, bufptr, 0 - number, leftPad, zeroPad, fieldWidth) + 1;
- }
- return print_number(putch, bufptr, number, leftPad, zeroPad, fieldWidth);
- }
- template<typename PutChFunc>
- [[gnu::always_inline]] inline int printf_internal(PutChFunc putch, char* buffer, const char*& fmt, char*& ap)
- {
- const char *p;
- int ret = 0;
- char* bufptr = buffer;
- for (p = fmt; *p; ++p) {
- bool leftPad = false;
- bool zeroPad = false;
- unsigned fieldWidth = 0;
- if (*p == '%' && *(p + 1)) {
- one_more:
- ++p;
- if (*p == ' ') {
- leftPad = true;
- if (*(p + 1))
- goto one_more;
- }
- if (!zeroPad && !fieldWidth && *p == '0') {
- zeroPad = true;
- if (*(p + 1))
- goto one_more;
- }
- if (*p >= '0' && *p <= '9') {
- fieldWidth *= 10;
- fieldWidth += *p - '0';
- if (*(p + 1))
- goto one_more;
- }
- switch( *p )
- {
- case 's':
- {
- const char* sp = va_arg(ap, const char*);
- ret += print_string(putch, bufptr, sp ? sp : "(null)", leftPad, fieldWidth);
- }
- break;
- case 'd':
- ret += print_signed_number(putch, bufptr, va_arg(ap, int), leftPad, zeroPad, fieldWidth);
- break;
- case 'u':
- ret += print_number(putch, bufptr, va_arg(ap, dword), leftPad, zeroPad, fieldWidth);
- break;
- case 'o':
- ret += print_octal_number(putch, bufptr, va_arg(ap, dword), leftPad, zeroPad, fieldWidth);
- break;
- case 'x':
- ret += print_hex(putch, bufptr, va_arg(ap, dword), 8);
- break;
- case 'w':
- ret += print_hex(putch, bufptr, va_arg(ap, int), 4);
- break;
- case 'b':
- ret += print_hex(putch, bufptr, va_arg(ap, int), 2);
- break;
- case 'c':
- putch(bufptr, (char)va_arg(ap, int));
- ++ret;
- break;
- case 'p':
- putch(bufptr, '0');
- putch(bufptr, 'x');
- ret += 2;
- ret += print_hex(putch, bufptr, va_arg(ap, dword), 8);
- break;
- }
- }
- else {
- putch(bufptr, *p);
- ++ret;
- }
- }
- return ret;
- }
|