Eliminated dynamic allocation.

When compile-time stringized constant name trimming is disabled (off by
default), trimming happens "lazily" - the first time the user calls a
function such as _to_string, the function allocates space for trimmed
constant names and trims them there.

With this change, space is reserved statically in a writeable char
array, and trimming happens in that array instead.
This commit is contained in:
Anton Bachin 2015-06-13 16:22:07 -05:00
parent 98232ee4fb
commit 74b3a66284

40
enum.h
View File

@ -436,17 +436,20 @@ _namesMatchNocase(const char *stringizedName, const char *referenceName,
} }
inline void _trim_names(const char * const *raw_names, inline void _trim_names(const char * const *raw_names,
const char **trimmed_names, std::size_t count) const char **trimmed_names,
char *storage, std::size_t count)
{ {
std::size_t offset = 0;
for (std::size_t index = 0; index < count; ++index) { for (std::size_t index = 0; index < count; ++index) {
std::size_t length = trimmed_names[index] = storage + offset;
std::size_t trimmed_length =
std::strcspn(raw_names[index], BETTER_ENUMS__NAME_ENDERS); std::strcspn(raw_names[index], BETTER_ENUMS__NAME_ENDERS);
char *trimmed = new char[length + 1]; storage[offset + trimmed_length] = '\0';
std::strncpy(trimmed, raw_names[index], length); std::size_t raw_length = std::strlen(raw_names[index]);
trimmed[length] = '\0'; offset += raw_length + 1;
trimmed_names[index] = trimmed;
} }
} }
@ -554,6 +557,14 @@ constexpr const char *_final_ ## index = \
BETTER_ENUMS__PP_MAP( \ BETTER_ENUMS__PP_MAP( \
BETTER_ENUMS__STRINGIZE_SINGLE, ignored, __VA_ARGS__)) BETTER_ENUMS__STRINGIZE_SINGLE, ignored, __VA_ARGS__))
#define BETTER_ENUMS__RESERVE_STORAGE_SINGLE(ignored, index, expression) \
#expression ","
#define BETTER_ENUMS__RESERVE_STORAGE(...) \
BETTER_ENUMS__ID( \
BETTER_ENUMS__PP_MAP( \
BETTER_ENUMS__RESERVE_STORAGE_SINGLE, ignored, __VA_ARGS__))
// TODO Convert integral to underlying only at the last possible moment, if the // TODO Convert integral to underlying only at the last possible moment, if the
@ -902,6 +913,13 @@ BETTER_ENUMS__CONSTEXPR inline bool operator !=(const Enum &a, const Enum &b) \
return value; \ return value; \
} \ } \
\ \
inline char* name_storage() \
{ \
static char storage[] = \
BETTER_ENUMS__ID(BETTER_ENUMS__RESERVE_STORAGE(__VA_ARGS__)); \
return storage; \
} \
\
inline const char** name_array() \ inline const char** name_array() \
{ \ { \
static const char *value[Enum::_size]; \ static const char *value[Enum::_size]; \
@ -924,6 +942,13 @@ BETTER_ENUMS__CONSTEXPR inline bool operator !=(const Enum &a, const Enum &b) \
return the_raw_names; \ return the_raw_names; \
} \ } \
\ \
inline char* name_storage() \
{ \
static char storage[] = \
BETTER_ENUMS__ID(BETTER_ENUMS__RESERVE_STORAGE(__VA_ARGS__)); \
return storage; \
} \
\
inline const char** name_array() \ inline const char** name_array() \
{ \ { \
static const char *value[Enum::_size]; \ static const char *value[Enum::_size]; \
@ -976,6 +1001,7 @@ BETTER_ENUMS__CONSTEXPR inline bool operator !=(const Enum &a, const Enum &b) \
\ \
::better_enums::_trim_names(BETTER_ENUMS__NS(Enum)::raw_names(), \ ::better_enums::_trim_names(BETTER_ENUMS__NS(Enum)::raw_names(), \
BETTER_ENUMS__NS(Enum)::name_array(), \ BETTER_ENUMS__NS(Enum)::name_array(), \
BETTER_ENUMS__NS(Enum)::name_storage(), \
_size); \ _size); \
\ \
BETTER_ENUMS__NS(Enum)::initialized() = true; \ BETTER_ENUMS__NS(Enum)::initialized() = true; \