Last active
November 14, 2025 11:08
-
-
Save zeux/86c420e042484cda41cc6510fc19bd7d to your computer and use it in GitHub Desktop.
C++ format library proof of concept - focus here is on minimal header so that compilation time is not affected. Implementation is very bare bones.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "format.h" | |
| namespace fmt { | |
| static void format_bool(std::string& result, bool value) | |
| { | |
| result += value ? "true" : "false"; | |
| } | |
| static void format_char(std::string& result, char value) | |
| { | |
| result += value; | |
| } | |
| static void format_char(std::string& result, wchar_t value) | |
| { | |
| result += char(value); | |
| } | |
| template <typename T> | |
| static void format_integer(std::string& result, T value) | |
| { | |
| char buf[128]; | |
| sprintf(buf, "%d", int(value)); | |
| result += buf; | |
| } | |
| template <typename T> | |
| static void format_fp(std::string& result, T value) | |
| { | |
| char buf[128]; | |
| sprintf(buf, "%f", value); | |
| result += buf; | |
| } | |
| static void format_pointer(std::string& result, const void* value) | |
| { | |
| char buf[128]; | |
| sprintf(buf, "%p", value); | |
| result += buf; | |
| } | |
| static void format_string(std::string& result, const char* value) | |
| { | |
| result += value; | |
| } | |
| static void format_string(std::string& result, const std::string& value) | |
| { | |
| result += value; | |
| } | |
| static void format_dispatch(std::string& result, kind_t kind, const void* value) | |
| { | |
| switch (kind) | |
| { | |
| case kind_bool: return format_bool(result, *static_cast<const bool*>(value)); | |
| case kind_schar: return format_integer(result, *static_cast<const signed char*>(value)); | |
| case kind_uchar: return format_integer(result, *static_cast<const unsigned char*>(value)); | |
| case kind_char: return format_char(result, *static_cast<const char*>(value)); | |
| case kind_wchar_t: return format_char(result, *static_cast<const wchar_t*>(value)); | |
| case kind_short: return format_integer(result, *static_cast<const short*>(value)); | |
| case kind_ushort: return format_integer(result, *static_cast<const unsigned short*>(value)); | |
| case kind_int: return format_integer(result, *static_cast<const int*>(value)); | |
| case kind_uint: return format_integer(result, *static_cast<const unsigned int*>(value)); | |
| case kind_long: return format_integer(result, *static_cast<const long*>(value)); | |
| case kind_ulong: return format_integer(result, *static_cast<const unsigned long*>(value)); | |
| case kind_llong: return format_integer(result, *static_cast<const long long*>(value)); | |
| case kind_ullong: return format_integer(result, *static_cast<const unsigned long long*>(value)); | |
| case kind_float: return format_fp(result, *static_cast<const float*>(value)); | |
| case kind_double: return format_fp(result, *static_cast<const double*>(value)); | |
| case kind_ldouble: return format_fp(result, *static_cast<const long double*>(value)); | |
| case kind_voidptr: return format_pointer(result, *static_cast<const void* const *>(value)); | |
| case kind_charptr: return format_string(result, *static_cast<const char* const *>(value)); | |
| case kind_string: return format_string(result, *static_cast<const std::string*>(value)); | |
| case kind_nullptr: return format_pointer(result, nullptr); | |
| } | |
| } | |
| std::string format_impl(const char* spec, const kind_t kinds[], const void* values[], size_t count) | |
| { | |
| std::string result; | |
| size_t offset = 0; | |
| for (const char* s = spec; *s; ++s) | |
| { | |
| if (s[0] == '{') | |
| { | |
| if (s[1] == '}') | |
| { | |
| if (offset >= count) | |
| throw std::runtime_error("Not enough format arguments"); | |
| format_dispatch(result, kinds[offset], values[offset]); | |
| offset++; | |
| s++; | |
| } | |
| else | |
| { | |
| throw std::runtime_error("Unmatched brace"); | |
| } | |
| } | |
| else | |
| { | |
| result += s[0]; | |
| } | |
| } | |
| return result; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <string> | |
| namespace fmt { | |
| #define KIND(X) \ | |
| X(bool,bool) \ | |
| X(signed char,schar) \ | |
| X(unsigned char,uchar) \ | |
| X(char,char) \ | |
| X(wchar_t,wchar_t) \ | |
| X(short,short) \ | |
| X(unsigned short,ushort) \ | |
| X(int,int) \ | |
| X(unsigned int,uint) \ | |
| X(long,long) \ | |
| X(unsigned long,ulong) \ | |
| X(long long,llong) \ | |
| X(unsigned long long,ullong) \ | |
| X(float,float) \ | |
| X(double,double) \ | |
| X(long double,ldouble) \ | |
| X(const void*,voidptr) \ | |
| X(const char*,charptr) \ | |
| X(std::string,string) \ | |
| X(std::nullptr_t,nullptr) | |
| #define KIND_ENUM(T,V) kind_##V, | |
| enum kind_t { KIND(KIND_ENUM) }; | |
| #undef KIND_ENUM | |
| template <typename T> struct type_kind; | |
| #define KIND_SPEC(T,V) template <> struct type_kind<T> { enum { value = kind_##V }; }; | |
| KIND(KIND_SPEC) | |
| #undef KIND_SPEC | |
| template <typename T> struct type_kind<T&> { enum { value = type_kind<T>::value }; }; | |
| template <typename T> struct type_kind<const T> { enum { value = type_kind<T>::value }; }; | |
| #undef KIND | |
| std::string format_impl(const char* spec, const kind_t kinds[], const void* values[], size_t count); | |
| template <typename... Args> | |
| std::string format(const char* spec, Args&&... args) | |
| { | |
| static constexpr kind_t kinds[] = { kind_t(type_kind<Args>::value)... }; | |
| const void* values[] = { &args... }; | |
| return format_impl(spec, kinds, values, sizeof(kinds) / sizeof(kinds[0])); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment