diff --git a/atom/src/behaviors.h b/atom/src/behaviors.h index 5c82ec83..3e98bad2 100644 --- a/atom/src/behaviors.h +++ b/atom/src/behaviors.h @@ -205,8 +205,28 @@ enum Mode: uint8_t Property, ObjectMethod_Name, MemberMethod_Object, + Last // sentinel }; } // namespace GetState +constexpr uint8_t _required_handler_size(uint8_t x) { + return ( + (x > 128) ? 255 : + (x > 64) ? 128 : + (x > 32) ? 64 : + (x > 16) ? 32 : + (x > 8) ? 16 : + (x > 4) ? 8 : + (x > 2) ? 4 : + 2 + ); +} + +#define _handlers_size( a ) ( sizeof(a) / sizeof(a[0]) ) +#define validate_handlers( handlers, sentinel ) \ + _handlers_size(handlers) - 1; \ + static_assert(sentinel <= _handlers_size(handlers), "Not enough handlers for all enum values"); \ + static_assert(_required_handler_size(sentinel) == _handlers_size(handlers), "Handlers size does not match enum width") \ + } // namespace atom diff --git a/atom/src/defaultvaluebehavior.cpp b/atom/src/defaultvaluebehavior.cpp index 3e547c48..e8b5a579 100644 --- a/atom/src/defaultvaluebehavior.cpp +++ b/atom/src/defaultvaluebehavior.cpp @@ -207,7 +207,7 @@ handlers[] = { no_op_handler }; -static_assert( sizeof(handlers) / sizeof(handler) == 16, "Must be exactly 16 handlers" ); +const auto mask = validate_handlers(handlers, DefaultValue::Mode::Last); } // namespace @@ -215,7 +215,7 @@ static_assert( sizeof(handlers) / sizeof(handler) == 16, "Must be exactly 16 han PyObject* Member::default_value( CAtom* atom ) { - return handlers[ get_default_value_mode() & 0xf ]( this, atom ); + return handlers[ get_default_value_mode() & mask ]( this, atom ); } diff --git a/atom/src/delattrbehavior.cpp b/atom/src/delattrbehavior.cpp index 651850d6..62091f58 100644 --- a/atom/src/delattrbehavior.cpp +++ b/atom/src/delattrbehavior.cpp @@ -192,7 +192,7 @@ handlers[] = { property_handler }; -static_assert( sizeof(handlers) / sizeof(handler) == 8, "Must be exactly 8 handlers" ); +const auto mask = validate_handlers(handlers, DelAttr::Mode::Last); } // namespace @@ -200,7 +200,7 @@ static_assert( sizeof(handlers) / sizeof(handler) == 8, "Must be exactly 8 handl int Member::delattr( CAtom* atom ) { - return handlers[ get_delattr_mode() & 0x7 ]( this, atom ); + return handlers[ get_delattr_mode() & mask ]( this, atom ); } diff --git a/atom/src/getattrbehavior.cpp b/atom/src/getattrbehavior.cpp index e54a0205..ae6f40b6 100644 --- a/atom/src/getattrbehavior.cpp +++ b/atom/src/getattrbehavior.cpp @@ -263,7 +263,7 @@ handlers[] = { no_op_handler }; -static_assert( sizeof(handlers) / sizeof(handler) == 16, "Must be exactly 16 handlers" ); +const auto mask = validate_handlers(handlers, GetAttr::Mode::Last); } // namespace @@ -271,7 +271,7 @@ static_assert( sizeof(handlers) / sizeof(handler) == 16, "Must be exactly 16 han PyObject* Member::getattr( CAtom* atom ) { - return handlers[ get_getattr_mode() & 0xf ]( this, atom ); + return handlers[ get_getattr_mode() & mask ]( this, atom ); } } // namespace atom diff --git a/atom/src/getstatebehavior.cpp b/atom/src/getstatebehavior.cpp index b7a17e2c..cd06fa19 100644 --- a/atom/src/getstatebehavior.cpp +++ b/atom/src/getstatebehavior.cpp @@ -129,7 +129,7 @@ handlers[] = { include_handler }; -static_assert( sizeof(handlers) / sizeof(handler) == 8, "Must be exactly 8 handlers" ); +const auto mask = validate_handlers(handlers, GetState::Mode::Last); } // namespace @@ -137,7 +137,7 @@ static_assert( sizeof(handlers) / sizeof(handler) == 8, "Must be exactly 8 handl PyObject* Member::should_getstate( CAtom* atom ) { - return handlers[ get_getstate_mode() & 0x7 ]( this, atom ); + return handlers[ get_getstate_mode() & mask ]( this, atom ); } } // namespace atom diff --git a/atom/src/postgetattrbehavior.cpp b/atom/src/postgetattrbehavior.cpp index 919a0998..31d2b94a 100644 --- a/atom/src/postgetattrbehavior.cpp +++ b/atom/src/postgetattrbehavior.cpp @@ -99,7 +99,7 @@ handlers[] = { no_op_handler, }; -static_assert( sizeof(handlers) / sizeof(handler) == 8, "Must be exactly 8 handlers" ); +const auto mask = validate_handlers(handlers, PostGetAttr::Mode::Last); } // namespace @@ -107,7 +107,7 @@ static_assert( sizeof(handlers) / sizeof(handler) == 8, "Must be exactly 8 handl PyObject* Member::post_getattr( CAtom* atom, PyObject* value ) { - return handlers[ get_post_getattr_mode() & 0x7 ]( this, atom, value ); + return handlers[ get_post_getattr_mode() & mask ]( this, atom, value ); } diff --git a/atom/src/postsetattrbehavior.cpp b/atom/src/postsetattrbehavior.cpp index c4af2089..3cbab2a8 100644 --- a/atom/src/postsetattrbehavior.cpp +++ b/atom/src/postsetattrbehavior.cpp @@ -112,7 +112,7 @@ handlers[] = { no_op_handler }; -static_assert( sizeof(handlers) / sizeof(handler) == 8, "Must be exactly 8 handlers" ); +const auto mask = validate_handlers(handlers, PostSetAttr::Mode::Last); } // namespace @@ -120,7 +120,7 @@ static_assert( sizeof(handlers) / sizeof(handler) == 8, "Must be exactly 8 handl int Member::post_setattr( CAtom* atom, PyObject* oldvalue, PyObject* newvalue ) { - return handlers[ get_post_setattr_mode() & 0x7 ]( this, atom, oldvalue, newvalue ); + return handlers[ get_post_setattr_mode() & mask ]( this, atom, oldvalue, newvalue ); } diff --git a/atom/src/postvalidatebehavior.cpp b/atom/src/postvalidatebehavior.cpp index 4f0527e2..274917a0 100644 --- a/atom/src/postvalidatebehavior.cpp +++ b/atom/src/postvalidatebehavior.cpp @@ -103,7 +103,7 @@ handlers[] = { no_op_handler }; -static_assert( sizeof(handlers) / sizeof(handler) == 8, "Must be exactly 8 handlers" ); +const auto mask = validate_handlers(handlers, PostValidate::Mode::Last); } // namespace @@ -111,7 +111,7 @@ static_assert( sizeof(handlers) / sizeof(handler) == 8, "Must be exactly 8 handl PyObject* Member::post_validate( CAtom* atom, PyObject* oldvalue, PyObject* newvalue ) { - return handlers[ get_post_validate_mode() & 0x7 ]( this, atom, oldvalue, newvalue ); + return handlers[ get_post_validate_mode() & mask ]( this, atom, oldvalue, newvalue ); } } // namespace atom diff --git a/atom/src/setattrbehavior.cpp b/atom/src/setattrbehavior.cpp index 0497cf16..dda99b25 100644 --- a/atom/src/setattrbehavior.cpp +++ b/atom/src/setattrbehavior.cpp @@ -383,7 +383,7 @@ handlers[] = { no_op_handler }; -static_assert( sizeof(handlers) / sizeof(handler) == 16, "Must be exactly 16 handlers" ); +const auto mask = validate_handlers(handlers, SetAttr::Mode::Last); } // namespace @@ -391,7 +391,7 @@ static_assert( sizeof(handlers) / sizeof(handler) == 16, "Must be exactly 16 han int Member::setattr( CAtom* atom, PyObject* value ) { - return handlers[ get_setattr_mode() & 0xf ]( this, atom, value ); + return handlers[ get_setattr_mode() & mask ]( this, atom, value ); } diff --git a/atom/src/validatebehavior.cpp b/atom/src/validatebehavior.cpp index 4746f5dd..ea27b818 100644 --- a/atom/src/validatebehavior.cpp +++ b/atom/src/validatebehavior.cpp @@ -1000,6 +1000,7 @@ handlers[] = { member_method_object_old_new_handler }; +const auto mask = validate_handlers(handlers, Validate::Mode::Last); } // namespace @@ -1007,9 +1008,7 @@ handlers[] = { PyObject* Member::validate( CAtom* atom, PyObject* oldvalue, PyObject* newvalue ) { - if( get_validate_mode() >= sizeof( handlers ) / sizeof( handler ) ) - return no_op_handler( this, atom, oldvalue, newvalue ); // LCOV_EXCL_LINE - return handlers[ get_validate_mode() ]( this, atom, oldvalue, newvalue ); + return handlers[ get_validate_mode() & mask ]( this, atom, oldvalue, newvalue ); }