From d9c605c61ff2436e04944acff4275040ea84c087 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Fri, 28 Nov 2014 06:40:57 -0800 Subject: [PATCH 1/3] Initial support for header-only configuration --- format.cc | 24 ++++++++++++++---------- format.h | 4 ++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/format.cc b/format.cc index 76988b49..30c42077 100644 --- a/format.cc +++ b/format.cc @@ -81,6 +81,10 @@ using fmt::internal::Arg; # endif #endif +#ifdef FMT_HEADER_ONLY +# define FMT_FUNC inline +#endif + #if _MSC_VER # pragma warning(push) # pragma warning(disable: 4127) // conditional expression is constant @@ -348,7 +352,7 @@ inline Arg::StringValue ignore_incompatible_str( Arg::StringValue s) { return s; } } // namespace -void fmt::SystemError::init( +FMT_FUNC void fmt::SystemError::init( int error_code, StringRef format_str, ArgList args) { error_code_ = error_code; MemoryWriter w; @@ -413,7 +417,7 @@ const uint64_t fmt::internal::POWERS_OF_10_64[] = { ULongLong(1000000000) * ULongLong(1000000000) * 10 }; -void fmt::internal::report_unknown_type(char code, const char *type) { +FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { if (std::isprint(static_cast(code))) { FMT_THROW(fmt::FormatError( fmt::format("unknown format code '{}' for {}", code, type))); @@ -468,7 +472,7 @@ void fmt::WindowsError::init( #endif -void fmt::internal::format_system_error( +FMT_FUNC void fmt::internal::format_system_error( fmt::Writer &out, int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) { FMT_TRY { @@ -619,7 +623,7 @@ inline Arg fmt::BasicFormatter::parse_arg_index(const Char *&s) { return arg; } -Arg fmt::internal::FormatterBase::do_get_arg( +FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg( unsigned arg_index, const char *&error) { Arg arg = args_[arg_index]; if (arg.type == Arg::NONE) @@ -1042,7 +1046,7 @@ void fmt::BasicFormatter::format( write(writer_, start_, s); } -void fmt::report_system_error( +FMT_FUNC void fmt::report_system_error( int error_code, fmt::StringRef message) FMT_NOEXCEPT(true) { report_error(internal::format_system_error, error_code, message); } @@ -1054,23 +1058,23 @@ void fmt::report_windows_error( } #endif -void fmt::print(std::FILE *f, StringRef format_str, ArgList args) { +FMT_FUNC void fmt::print(std::FILE *f, StringRef format_str, ArgList args) { MemoryWriter w; w.write(format_str, args); std::fwrite(w.data(), 1, w.size(), f); } -void fmt::print(StringRef format_str, ArgList args) { +FMT_FUNC void fmt::print(StringRef format_str, ArgList args) { print(stdout, format_str, args); } -void fmt::print(std::ostream &os, StringRef format_str, ArgList args) { +FMT_FUNC void fmt::print(std::ostream &os, StringRef format_str, ArgList args) { MemoryWriter w; w.write(format_str, args); os.write(w.data(), w.size()); } -void fmt::print_colored(Color c, StringRef format, ArgList args) { +FMT_FUNC void fmt::print_colored(Color c, StringRef format, ArgList args) { char escape[] = "\x1b[30m"; escape[3] = '0' + static_cast(c); std::fputs(escape, stdout); @@ -1078,7 +1082,7 @@ void fmt::print_colored(Color c, StringRef format, ArgList args) { std::fputs(RESET_COLOR, stdout); } -int fmt::fprintf(std::FILE *f, StringRef format, ArgList args) { +FMT_FUNC int fmt::fprintf(std::FILE *f, StringRef format, ArgList args) { MemoryWriter w; printf(w, format, args); std::size_t size = w.size(); diff --git a/format.h b/format.h index 3a2a0439..8ddd26b6 100644 --- a/format.h +++ b/format.h @@ -2427,4 +2427,8 @@ FMT_VARIADIC(int, fprintf, std::FILE *, StringRef) # pragma GCC diagnostic pop #endif +#ifdef FMT_HEADER_ONLY +# include "format.cc" +#endif + #endif // FMT_FORMAT_H_ From c2a6903e19969828905d9a64452ddc2ff2e94b06 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Fri, 28 Nov 2014 15:30:03 -0800 Subject: [PATCH 2/3] Define FMT_FUNC to nothing if FMT_HEADER_ONLY is not defined --- format.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/format.cc b/format.cc index 30c42077..493e115e 100644 --- a/format.cc +++ b/format.cc @@ -83,6 +83,8 @@ using fmt::internal::Arg; #ifdef FMT_HEADER_ONLY # define FMT_FUNC inline +#else +# define FMT_FUNC #endif #if _MSC_VER From 311251eb91b742ea647e830edf562a100c4095f3 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sat, 29 Nov 2014 06:58:00 -0800 Subject: [PATCH 3/3] Complete header-only configuration support --- format.cc | 12 +++++++++--- format.h | 38 ++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/format.cc b/format.cc index 493e115e..bb764f49 100644 --- a/format.cc +++ b/format.cc @@ -391,7 +391,8 @@ int fmt::internal::CharTraits::format_float( swprintf(buffer, size, format, width, precision, value); } -const char fmt::internal::DIGITS[] = +template +const char fmt::internal::BasicData::DIGITS[] = "0001020304050607080910111213141516171819" "2021222324252627282930313233343536373839" "4041424344454647484950515253545556575859" @@ -409,8 +410,13 @@ const char fmt::internal::DIGITS[] = factor * 100000000, \ factor * 1000000000 -const uint32_t fmt::internal::POWERS_OF_10_32[] = {0, FMT_POWERS_OF_10(1)}; -const uint64_t fmt::internal::POWERS_OF_10_64[] = { +template +const uint32_t fmt::internal::BasicData::POWERS_OF_10_32[] = { + 0, FMT_POWERS_OF_10(1) +}; + +template +const uint64_t fmt::internal::BasicData::POWERS_OF_10_64[] = { 0, FMT_POWERS_OF_10(1), FMT_POWERS_OF_10(ULongLong(1000000000)), diff --git a/format.h b/format.h index 8ddd26b6..b728ac7e 100644 --- a/format.h +++ b/format.h @@ -510,8 +510,16 @@ FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong); void report_unknown_type(char code, const char *type); -extern const uint32_t POWERS_OF_10_32[]; -extern const uint64_t POWERS_OF_10_64[]; +// Static data is placed in this class template to allow header-only +// configuration. +template +struct BasicData { + static const uint32_t POWERS_OF_10_32[]; + static const uint64_t POWERS_OF_10_64[]; + static const char DIGITS[]; +}; + +typedef BasicData<> Data; #if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll) // Returns the number of decimal digits in n. Leading zeros are not counted @@ -520,13 +528,13 @@ inline unsigned count_digits(uint64_t n) { // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits. unsigned t = (64 - __builtin_clzll(n | 1)) * 1233 >> 12; - return t - (n < POWERS_OF_10_64[t]) + 1; + return t - (n < Data::POWERS_OF_10_64[t]) + 1; } # if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz) // Optional version of count_digits for better performance on 32-bit platforms. inline unsigned count_digits(uint32_t n) { uint32_t t = (32 - __builtin_clz(n | 1)) * 1233 >> 12; - return t - (n < POWERS_OF_10_32[t]) + 1; + return t - (n < Data::POWERS_OF_10_32[t]) + 1; } # endif #else @@ -547,8 +555,6 @@ inline unsigned count_digits(uint64_t n) { } #endif -extern const char DIGITS[]; - // Formats a decimal unsigned integer value writing into buffer. template inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { @@ -559,8 +565,8 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { // "Three Optimization Tips for C++". See speed-test for a comparison. unsigned index = (value % 100) * 2; value /= 100; - buffer[num_digits] = DIGITS[index + 1]; - buffer[num_digits - 1] = DIGITS[index]; + buffer[num_digits] = Data::DIGITS[index + 1]; + buffer[num_digits - 1] = Data::DIGITS[index]; num_digits -= 2; } if (value < 10) { @@ -568,8 +574,8 @@ inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) { return; } unsigned index = static_cast(value * 2); - buffer[1] = DIGITS[index + 1]; - buffer[0] = DIGITS[index]; + buffer[1] = Data::DIGITS[index + 1]; + buffer[0] = Data::DIGITS[index]; } #ifdef _WIN32 @@ -2222,16 +2228,16 @@ class FormatInt { // "Three Optimization Tips for C++". See speed-test for a comparison. unsigned index = (value % 100) * 2; value /= 100; - *--buffer_end = internal::DIGITS[index + 1]; - *--buffer_end = internal::DIGITS[index]; + *--buffer_end = internal::Data::DIGITS[index + 1]; + *--buffer_end = internal::Data::DIGITS[index]; } if (value < 10) { *--buffer_end = static_cast('0' + value); return buffer_end; } unsigned index = static_cast(value * 2); - *--buffer_end = internal::DIGITS[index + 1]; - *--buffer_end = internal::DIGITS[index]; + *--buffer_end = internal::Data::DIGITS[index + 1]; + *--buffer_end = internal::Data::DIGITS[index]; return buffer_end; } @@ -2295,8 +2301,8 @@ inline void format_decimal(char *&buffer, T value) { return; } unsigned index = static_cast(abs_value * 2); - *buffer++ = internal::DIGITS[index]; - *buffer++ = internal::DIGITS[index + 1]; + *buffer++ = internal::Data::DIGITS[index]; + *buffer++ = internal::Data::DIGITS[index + 1]; return; } unsigned num_digits = internal::count_digits(abs_value);