From d3e668418f1fbff11c238009f66581f2ace6141f Mon Sep 17 00:00:00 2001 From: Alberto Aguirre Date: Fri, 20 Mar 2020 08:46:31 -0500 Subject: [PATCH] Allow disabling floating point support (#1590) * Allow disabling floating point support Add FMT_USE_FLOAT, FMT_USE_DOUBLE and FMT_USE_LONG_DOUBLE to allow a user of the library to configure the float types they want to allow. This is specially useful in embedded environements where code size is important. * Avoid conditional macros to disable float support * Add is_supported_floating_point constexpr function * Fix empty-body warning --- include/fmt/core.h | 12 ++++++++++++ include/fmt/format.h | 32 +++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index 70647c76..b5c5f252 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -316,6 +316,18 @@ struct int128_t {}; struct uint128_t {}; #endif +#ifndef FMT_USE_FLOAT +# define FMT_USE_FLOAT 1 +#endif + +#ifndef FMT_USE_DOUBLE +# define FMT_USE_DOUBLE 1 +#endif + +#ifndef FMT_USE_LONG_DOUBLE +# define FMT_USE_LONG_DOUBLE 1 +#endif + // Casts a nonnegative integer to unsigned. template FMT_CONSTEXPR typename std::make_unsigned::type to_unsigned(Int value) { diff --git a/include/fmt/format.h b/include/fmt/format.h index 36c30b9f..af589ea3 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -724,6 +724,13 @@ FMT_CONSTEXPR bool is_negative(T) { return false; } +template ::value)> +FMT_CONSTEXPR bool is_supported_floating_point(T) { + return (std::is_same::value && FMT_USE_FLOAT) || + (std::is_same::value && FMT_USE_DOUBLE) || + (std::is_same::value && FMT_USE_LONG_DOUBLE); +} + // Smallest of uint32_t, uint64_t, uint128_t that is large enough to // represent all values of T. template @@ -1685,6 +1692,9 @@ template class basic_writer { template ::value)> void write(T value, format_specs specs = {}) { + if (const_check(!is_supported_floating_point(value))) { + return; + } float_specs fspecs = parse_float_type_spec(specs); fspecs.sign = specs.sign; if (std::signbit(value)) { // value < 0 is false for NaN so use signbit. @@ -1883,6 +1893,10 @@ class arg_formatter_base { template ::value)> iterator operator()(T value) { + if (const_check(!is_supported_floating_point(value))) { + FMT_ASSERT(false, "unsupported float argument type"); + return out(); + } writer_.write(value, specs_ ? *specs_ : format_specs()); return out(); } @@ -2923,9 +2937,25 @@ struct formatter(specs_.type, eh)); break; case internal::type::float_type: + if (internal::const_check(FMT_USE_FLOAT)) { + internal::parse_float_type_spec(specs_, eh); + } else { + FMT_ASSERT(false, "float support disabled"); + } + break; case internal::type::double_type: + if (internal::const_check(FMT_USE_DOUBLE)) { + internal::parse_float_type_spec(specs_, eh); + } else { + FMT_ASSERT(false, "double support disabled"); + } + break; case internal::type::long_double_type: - internal::parse_float_type_spec(specs_, eh); + if (internal::const_check(FMT_USE_LONG_DOUBLE)) { + internal::parse_float_type_spec(specs_, eh); + } else { + FMT_ASSERT(false, "long double support disabled"); + } break; case internal::type::cstring_type: internal::handle_cstring_type_spec(