Print some info on exceptions.
This commit is contained in:
227
targets/_any/include/os/tools/printf_helper.hpp
Normal file
227
targets/_any/include/os/tools/printf_helper.hpp
Normal file
@@ -0,0 +1,227 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BAD_APPLE_OS_OS_TOOLS_PRINTF_HELPER_HPP_INCLUDED)
|
||||
#define BAD_APPLE_OS_OS_TOOLS_PRINTF_HELPER_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
#if !defined(BAOS_IPRINTF_FUNC_ATTRIBUTE)
|
||||
#define BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
namespace baos
|
||||
{
|
||||
template<typename TPrinter>
|
||||
class PrintFHelper
|
||||
{
|
||||
private:
|
||||
TPrinter mPrinter;
|
||||
public:
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
explicit PrintFHelper(TPrinter printer = {}) noexcept : mPrinter(std::move(printer)) {}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printInt(long value)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
mPrinter.putchar('0');
|
||||
return 1;
|
||||
}
|
||||
if (value < 0)
|
||||
{
|
||||
mPrinter.putchar('-');
|
||||
return printInt(-value) + 1;
|
||||
}
|
||||
|
||||
char digits[19]; // 9223372036854775807 has 10 digits
|
||||
char* pos = &digits[0];
|
||||
|
||||
while (value > 0)
|
||||
{
|
||||
*pos = static_cast<char>('0' + (value % 10));
|
||||
value /= 10;
|
||||
++pos;
|
||||
}
|
||||
for (char* chr = pos - 1; chr >= digits; --chr)
|
||||
{
|
||||
mPrinter.putchar(*chr);
|
||||
}
|
||||
return pos - digits;
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printUInt(uint64_t value)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
mPrinter.putchar('0');
|
||||
return 1;
|
||||
}
|
||||
|
||||
char digits[20]; // 18,446,744,073,709,551,615 has 20 digits
|
||||
char* pos = &digits[0];
|
||||
|
||||
while (value > 0)
|
||||
{
|
||||
*pos = static_cast<char>('0' + (value % 10));
|
||||
value /= 10;
|
||||
++pos;
|
||||
}
|
||||
for (char* chr = pos - 1; chr >= digits; --chr)
|
||||
{
|
||||
mPrinter.putchar(*chr);
|
||||
}
|
||||
return pos - digits;
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printHexInt(uint64_t value)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
mPrinter.putchar('0');
|
||||
return 1;
|
||||
}
|
||||
|
||||
char digits[16]; // FFFFFFFFFFFFFFFF has 16 digits
|
||||
char* pos = &digits[0];
|
||||
|
||||
while (value > 0)
|
||||
{
|
||||
const uint64_t digit = (value % 16);
|
||||
if (digit < 10)
|
||||
{
|
||||
*pos = static_cast<char>('0' + digit);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pos = static_cast<char>('A' + digit - 10);
|
||||
}
|
||||
value /= 16;
|
||||
++pos;
|
||||
}
|
||||
for (char* chr = pos - 1; chr >= digits; --chr)
|
||||
{
|
||||
mPrinter.putchar(*chr);
|
||||
}
|
||||
return pos - digits;
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printPointer(void* ptr)
|
||||
{
|
||||
return printHexInt(reinterpret_cast<uint64_t>(ptr));
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printString(const char* str)
|
||||
{
|
||||
int len = 0;
|
||||
while (*str)
|
||||
{
|
||||
mPrinter.putchar(*str);
|
||||
++str;
|
||||
++len;
|
||||
}
|
||||
return static_cast<int>(len);
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int printByteSize(size_t bytes)
|
||||
{
|
||||
const char* suffixes[] = {
|
||||
"B", "KiB", "MiB", "GiB", "TiB"
|
||||
};
|
||||
int suffixIdx = 0;
|
||||
for (; suffixIdx < sizeof(suffixes) / sizeof(suffixes[0]); ++suffixIdx)
|
||||
{
|
||||
if (bytes < 1024) {
|
||||
break;
|
||||
}
|
||||
bytes /= 1024;
|
||||
}
|
||||
return printUInt(bytes) + printString(suffixes[suffixIdx]);
|
||||
}
|
||||
|
||||
BAOS_IPRINTF_FUNC_ATTRIBUTE
|
||||
int vprintf(const char* format, va_list vlist) noexcept
|
||||
{
|
||||
int result = 0;
|
||||
const char* pos = format;
|
||||
while (*pos != '\0')
|
||||
{
|
||||
if (*pos == '%')
|
||||
{
|
||||
++pos;
|
||||
switch (*pos)
|
||||
{
|
||||
case '%':
|
||||
mPrinter.putchar('%');
|
||||
++result;
|
||||
break;
|
||||
case '\0':
|
||||
// TODO: invalid format string, do something
|
||||
assert(!"Invalid format string, ends with %.");
|
||||
return -1;
|
||||
case 'b':
|
||||
result += printByteSize(va_arg(vlist, size_t));
|
||||
break;
|
||||
case 'c':
|
||||
{
|
||||
const char chr = static_cast<char>(va_arg(vlist, int));
|
||||
mPrinter.putchar(chr);
|
||||
++result;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
result += printString(va_arg(vlist, const char*));
|
||||
break;
|
||||
case 'd':
|
||||
result += printInt(va_arg(vlist, int));
|
||||
break;
|
||||
case 'p':
|
||||
result += printPointer(va_arg(vlist, void*));
|
||||
break;
|
||||
case 'X':
|
||||
result += printHexInt(va_arg(vlist, unsigned));
|
||||
break;
|
||||
case 'l':
|
||||
++pos;
|
||||
switch (*pos)
|
||||
{
|
||||
case '\0':
|
||||
assert(!"Invalid format string, ends with %l.");
|
||||
return -1;
|
||||
case 'd':
|
||||
result += printInt(va_arg(vlist, long));
|
||||
break;
|
||||
case 'X':
|
||||
result += printHexInt(va_arg(vlist, unsigned long));
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(!"Invalid format string, unknown format identifier.");
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
{
|
||||
mPrinter.putchar(*pos);
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
++result;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !defined(BAD_APPLE_OS_OS_TOOLS_PRINTF_HELPER_HPP_INCLUDED)
|
||||
@@ -5,6 +5,7 @@
|
||||
#define BAD_APPLE_OS_STDIO_H_INCLUDED
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include "./detail/common.h"
|
||||
|
||||
BA_EXTERN_C_BEGIN
|
||||
@@ -13,6 +14,8 @@ int putchar(int chr) BA_CXX_NOEXCEPT;
|
||||
int puts(const char* str) BA_CXX_NOEXCEPT;
|
||||
int printf(const char* format, ...) BA_CXX_NOEXCEPT __attribute__((format(printf, 1, 2)));
|
||||
int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT;
|
||||
int snprintf(char* buffer, size_t bufferSize, const char* format, ...) BA_CXX_NOEXCEPT __attribute__((format(printf, 3, 4)));
|
||||
int vsnprintf(char* buffer, size_t bufferSize, const char* format, va_list vlist) BA_CXX_NOEXCEPT;
|
||||
|
||||
BA_EXTERN_C_END
|
||||
|
||||
|
||||
Reference in New Issue
Block a user