15 int printf(
const char * fmt, ...);
21 extern "C" int sprintf(
char* buffer,
const char* fmt, ...);
29 #define CPPAPE_CONCAT_IMPL( x, y ) x##y
30 #define CPPAPE_MACRO_CONCAT( x, y ) CPPAPE_CONCAT_IMPL( x, y )
40 inline char*
format(
const T& val,
char* b,
char* e)
42 #define __CPPAPE_FORMAT_ERROR "<format error>"
45 auto result = to_chars(b, e, val);
47 if (result.ec != std::errc())
49 memcpy(b, __CPPAPE_FORMAT_ERROR,
sizeof(__CPPAPE_FORMAT_ERROR) - 1);
50 return b +
sizeof(__CPPAPE_FORMAT_ERROR) - 1;
53 #undef __CPPAPE_FORMAT_ERROR
59 inline char*
format(
const std::complex<T>& val,
char* b,
char* e)
61 return b +
std::sprintf(b,
"(%f, %fi)", val.real(), val.imag());
64 inline char*
format(
const long double& val,
char* b,
char* e)
69 inline char*
format(
const double& val,
char* b,
char* e)
74 inline char*
format(
const float& val,
char* b,
char* e)
79 inline char*
format(
const void* val,
char* b,
char* e)
84 inline char*
format(std::string_view val,
char* b,
char* e)
86 assert(e > (b + val.size()));
87 std::memcpy(b, val.data(), val.size());
88 return b + val.size();
91 inline char*
format(
const char* val,
char* b,
char* e)
93 return format(std::string_view(val), b, e);
96 inline char*
format(
const std::string& val,
char* b,
char* e)
98 return format(std::string_view(val), b, e);
103 static constexpr std::size_t size = 4096;
107 if (begin() == end())
119 char* begin() {
return current; }
120 char* end() {
return buffer + size; }
123 char* current = buffer;
127 inline print_buffer&
operator << (print_buffer& left,
const T& value)
129 left.current =
format(value, left.begin(), left.end());
133 inline void safe_printf(print_buffer& buffer, std::string_view view)
135 for (
auto it = view.begin(); it != view.end(); ++it)
141 if (next != view.end() && *next ==
'%')
147 abort(
"too few arguments for print()");
155 template<
typename T,
typename... Args>
156 inline void safe_printf(print_buffer& buffer, std::string_view view,
const T& value, Args&&... args)
158 for (
auto it = view.begin(); it != view.end(); ++it)
164 if (next != view.end() && *next ==
'%')
171 safe_printf(buffer, view.substr(std::distance(view.begin(), next)), std::forward<Args>(args)...);
179 abort(
"too many arguments provided to print()");
199 template<
typename Derived>
202 friend std::to_chars_result
to_chars(
char* begin,
char* end,
const Derived& type)
204 if (!type.format(begin, end, &begin))
205 return { end, std::errc::value_too_large };
207 return { begin, std::errc() };
237 template<
typename... Args>
238 inline void print(std::string_view fmt, Args&&... args)
240 ape::detail::print_buffer stackBuffer;
245 printf(
"%s", stackBuffer.buffer);
255 template<
typename... Args>
256 inline std::string
sprint(std::string_view fmt, Args&&... args)
258 ape::detail::print_buffer stackBuffer;
263 return { stackBuffer.begin(), stackBuffer.end() };
267 #define __CPPAPE_PRINTF_ONCE(cname, ...) \
268 static bool cname = false; \
272 printf(__VA_ARGS__); \
278 #define printf_once(...) __CPPAPE_PRINTF_ONCE(CPPAPE_MACRO_CONCAT(__once_flag, __COUNTER__), __VA_ARGS__)
280 #define __CPPAPE_PRINT_ONCE(cname, ...) \
281 static bool cname = false; \
285 print(__VA_ARGS__); \
291 #define print_once(...) __CPPAPE_PRINT_ONCE(CPPAPE_MACRO_CONCAT(__once_flag, __COUNTER__), __VA_ARGS__)