Add flag to disable dynamic memory allocations

-DFMT_NO_ALLOCATIONS=1

This will turn off some functionality:
 - exceptions
 - locales
 - float/double support
This commit is contained in:
cocasema 2022-07-21 23:41:44 -07:00
parent c48be439f1
commit d7534aabd2
3 changed files with 51 additions and 0 deletions

View File

@ -130,6 +130,18 @@
# define FMT_CONSTEXPR_CHAR_TRAITS # define FMT_CONSTEXPR_CHAR_TRAITS
#endif #endif
#ifndef FMT_NO_ALLOCATIONS
# define FMT_NO_ALLOCATIONS 0
#endif
#if FMT_NO_ALLOCATIONS
# define FMT_EXCEPTIONS 0
# define FMT_STATIC_THOUSANDS_SEPARATOR 1
# define FMT_USE_FLOAT 0
# define FMT_USE_DOUBLE 0
# define FMT_USE_LONG_DOUBLE 0
#endif
// Check if exceptions are disabled. // Check if exceptions are disabled.
#ifndef FMT_EXCEPTIONS #ifndef FMT_EXCEPTIONS
# if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ # if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \

View File

@ -32,15 +32,22 @@ FMT_BEGIN_NAMESPACE
namespace detail { namespace detail {
FMT_FUNC void assert_fail(const char* file, int line, const char* message) { FMT_FUNC void assert_fail(const char* file, int line, const char* message) {
#if FMT_NO_ALLOCATIONS
(void)file;
(void)line;
(void)message;
#else
// Use unchecked std::fprintf to avoid triggering another assertion when // Use unchecked std::fprintf to avoid triggering another assertion when
// writing to stderr fails // writing to stderr fails
std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message); std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message);
#endif
// Chosen instead of std::abort to satisfy Clang in CUDA mode during device // Chosen instead of std::abort to satisfy Clang in CUDA mode during device
// code pass. // code pass.
std::terminate(); std::terminate();
} }
FMT_FUNC void throw_format_error(const char* message) { FMT_FUNC void throw_format_error(const char* message) {
(void)message;
FMT_THROW(format_error(message)); FMT_THROW(format_error(message));
} }
@ -121,11 +128,13 @@ template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
FMT_API FMT_FUNC format_error::~format_error() noexcept = default; FMT_API FMT_FUNC format_error::~format_error() noexcept = default;
#endif #endif
#if !FMT_NO_ALLOCATIONS
FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str, FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str,
format_args args) { format_args args) {
auto ec = std::error_code(error_code, std::generic_category()); auto ec = std::error_code(error_code, std::generic_category());
return std::system_error(ec, vformat(format_str, args)); return std::system_error(ec, vformat(format_str, args));
} }
#endif
namespace detail { namespace detail {
@ -1449,6 +1458,7 @@ FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
buffer_.push_back(0); buffer_.push_back(0);
} }
#if !FMT_NO_ALLOCATIONS
FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code, FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,
const char* message) noexcept { const char* message) noexcept {
FMT_TRY { FMT_TRY {
@ -1464,6 +1474,7 @@ FMT_FUNC void report_system_error(int error_code,
const char* message) noexcept { const char* message) noexcept {
report_error(format_system_error, error_code, message); report_error(format_system_error, error_code, message);
} }
#endif // !FMT_NO_ALLOCATIONS
FMT_FUNC std::string vformat(string_view fmt, format_args args) { FMT_FUNC std::string vformat(string_view fmt, format_args args) {
// Don't optimize the "{}" case to keep the binary size small and because it // Don't optimize the "{}" case to keep the binary size small and because it

View File

@ -77,6 +77,8 @@
# define FMT_MSC_DEFAULT # define FMT_MSC_DEFAULT
#endif #endif
#define FMT_STRINGIZE(T) #T
#ifndef FMT_THROW #ifndef FMT_THROW
# if FMT_EXCEPTIONS # if FMT_EXCEPTIONS
# if FMT_MSC_VERSION || defined(__NVCC__) # if FMT_MSC_VERSION || defined(__NVCC__)
@ -94,6 +96,12 @@ FMT_END_NAMESPACE
# else # else
# define FMT_THROW(x) throw x # define FMT_THROW(x) throw x
# endif # endif
# elif FMT_NO_ALLOCATIONS
# define FMT_THROW(x) \
do { \
FMT_ASSERT(false, "ERROR THROWN AT " FMT_STRINGIZE( \
__FILE__) " : " FMT_STRINGIZE(__LINE__)); \
} while (false)
# else # else
# define FMT_THROW(x) \ # define FMT_THROW(x) \
do { \ do { \
@ -894,6 +902,10 @@ template <typename T, size_t SIZE, typename Allocator>
FMT_CONSTEXPR20 void basic_memory_buffer<T, SIZE, Allocator>::grow( FMT_CONSTEXPR20 void basic_memory_buffer<T, SIZE, Allocator>::grow(
size_t size) { size_t size) {
detail::abort_fuzzing_if(size > 5000); detail::abort_fuzzing_if(size > 5000);
#if FMT_NO_ALLOCATIONS
detail::assert_fail(__FILE__, __LINE__, "dynamic allocations disabled");
return;
#endif
const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_); const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);
size_t old_capacity = this->capacity(); size_t old_capacity = this->capacity();
size_t new_capacity = old_capacity + old_capacity / 2; size_t new_capacity = old_capacity + old_capacity / 2;
@ -2029,11 +2041,15 @@ FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg<T> arg,
switch (specs.type) { switch (specs.type) {
case presentation_type::none: case presentation_type::none:
case presentation_type::dec: { case presentation_type::dec: {
#if FMT_NO_ALLOCATIONS
(void)loc;
#else
if (specs.localized && if (specs.localized &&
write_int_localized(out, static_cast<uint64_or_128_t<T>>(abs_value), write_int_localized(out, static_cast<uint64_or_128_t<T>>(abs_value),
prefix, specs, loc)) { prefix, specs, loc)) {
return out; return out;
} }
#endif
auto num_digits = count_digits(abs_value); auto num_digits = count_digits(abs_value);
return write_int( return write_int(
out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) { out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
@ -3160,6 +3176,12 @@ template <typename Char, typename OutputIt, typename T,
FMT_CONSTEXPR20 auto write(OutputIt out, T value, FMT_CONSTEXPR20 auto write(OutputIt out, T value,
basic_format_specs<Char> specs, locale_ref loc = {}) basic_format_specs<Char> specs, locale_ref loc = {})
-> OutputIt { -> OutputIt {
#if FMT_NO_ALLOCATIONS
(void)value;
(void)specs;
(void)loc;
return out;
#endif
if (const_check(!is_supported_floating_point(value))) return out; if (const_check(!is_supported_floating_point(value))) return out;
float_specs fspecs = parse_float_type_spec(specs); float_specs fspecs = parse_float_type_spec(specs);
fspecs.sign = specs.sign; fspecs.sign = specs.sign;
@ -3209,6 +3231,10 @@ FMT_CONSTEXPR20 auto write(OutputIt out, T value,
template <typename Char, typename OutputIt, typename T, template <typename Char, typename OutputIt, typename T,
FMT_ENABLE_IF(is_fast_float<T>::value)> FMT_ENABLE_IF(is_fast_float<T>::value)>
FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt { FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
#if FMT_NO_ALLOCATIONS
(void)value;
return out;
#endif
if (is_constant_evaluated()) if (is_constant_evaluated())
return write(out, value, basic_format_specs<Char>()); return write(out, value, basic_format_specs<Char>());
if (const_check(!is_supported_floating_point(value))) return out; if (const_check(!is_supported_floating_point(value))) return out;
@ -3571,6 +3597,7 @@ FMT_API void report_error(format_func func, int error_code,
const char* message) noexcept; const char* message) noexcept;
FMT_END_DETAIL_NAMESPACE FMT_END_DETAIL_NAMESPACE
#if !FMT_NO_ALLOCATIONS
FMT_API auto vsystem_error(int error_code, string_view format_str, FMT_API auto vsystem_error(int error_code, string_view format_str,
format_args args) -> std::system_error; format_args args) -> std::system_error;
@ -3619,6 +3646,7 @@ FMT_API void format_system_error(detail::buffer<char>& out, int error_code,
// Reports a system error without throwing an exception. // Reports a system error without throwing an exception.
// Can be used to report errors from destructors. // Can be used to report errors from destructors.
FMT_API void report_system_error(int error_code, const char* message) noexcept; FMT_API void report_system_error(int error_code, const char* message) noexcept;
#endif // !FMT_NO_ALLOCATIONS
/** Fast integer formatter. */ /** Fast integer formatter. */
class format_int { class format_int {