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
#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.
#ifndef FMT_EXCEPTIONS
# if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \

View File

@ -32,15 +32,22 @@ FMT_BEGIN_NAMESPACE
namespace detail {
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
// writing to stderr fails
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
// code pass.
std::terminate();
}
FMT_FUNC void throw_format_error(const char* message) {
(void)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;
#endif
#if !FMT_NO_ALLOCATIONS
FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str,
format_args args) {
auto ec = std::error_code(error_code, std::generic_category());
return std::system_error(ec, vformat(format_str, args));
}
#endif
namespace detail {
@ -1449,6 +1458,7 @@ FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
buffer_.push_back(0);
}
#if !FMT_NO_ALLOCATIONS
FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,
const char* message) noexcept {
FMT_TRY {
@ -1464,6 +1474,7 @@ FMT_FUNC void report_system_error(int error_code,
const char* message) noexcept {
report_error(format_system_error, error_code, message);
}
#endif // !FMT_NO_ALLOCATIONS
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

View File

@ -77,6 +77,8 @@
# define FMT_MSC_DEFAULT
#endif
#define FMT_STRINGIZE(T) #T
#ifndef FMT_THROW
# if FMT_EXCEPTIONS
# if FMT_MSC_VERSION || defined(__NVCC__)
@ -94,6 +96,12 @@ FMT_END_NAMESPACE
# else
# define FMT_THROW(x) throw x
# 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
# define FMT_THROW(x) \
do { \
@ -894,6 +902,10 @@ template <typename T, size_t SIZE, typename Allocator>
FMT_CONSTEXPR20 void basic_memory_buffer<T, SIZE, Allocator>::grow(
size_t size) {
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_);
size_t old_capacity = this->capacity();
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) {
case presentation_type::none:
case presentation_type::dec: {
#if FMT_NO_ALLOCATIONS
(void)loc;
#else
if (specs.localized &&
write_int_localized(out, static_cast<uint64_or_128_t<T>>(abs_value),
prefix, specs, loc)) {
return out;
}
#endif
auto num_digits = count_digits(abs_value);
return write_int(
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,
basic_format_specs<Char> specs, locale_ref loc = {})
-> OutputIt {
#if FMT_NO_ALLOCATIONS
(void)value;
(void)specs;
(void)loc;
return out;
#endif
if (const_check(!is_supported_floating_point(value))) return out;
float_specs fspecs = parse_float_type_spec(specs);
fspecs.sign = specs.sign;
@ -3209,6 +3231,10 @@ FMT_CONSTEXPR20 auto write(OutputIt out, T value,
template <typename Char, typename OutputIt, typename T,
FMT_ENABLE_IF(is_fast_float<T>::value)>
FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
#if FMT_NO_ALLOCATIONS
(void)value;
return out;
#endif
if (is_constant_evaluated())
return write(out, value, basic_format_specs<Char>());
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;
FMT_END_DETAIL_NAMESPACE
#if !FMT_NO_ALLOCATIONS
FMT_API auto vsystem_error(int error_code, string_view format_str,
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.
// Can be used to report errors from destructors.
FMT_API void report_system_error(int error_code, const char* message) noexcept;
#endif // !FMT_NO_ALLOCATIONS
/** Fast integer formatter. */
class format_int {