Skip to content

Commit

Permalink
Add a validate_handler macro that checks handlers for the mode enums
Browse files Browse the repository at this point in the history
  • Loading branch information
frmdstryr committed Jan 22, 2025
1 parent 8b32c1b commit 0395936
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 20 deletions.
20 changes: 20 additions & 0 deletions atom/src/behaviors.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions atom/src/defaultvaluebehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,15 +207,15 @@ 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


PyObject*
Member::default_value( CAtom* atom )
{
return handlers[ get_default_value_mode() & 0xf ]( this, atom );
return handlers[ get_default_value_mode() & mask ]( this, atom );
}


Expand Down
4 changes: 2 additions & 2 deletions atom/src/delattrbehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,15 @@ 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


int
Member::delattr( CAtom* atom )
{
return handlers[ get_delattr_mode() & 0x7 ]( this, atom );
return handlers[ get_delattr_mode() & mask ]( this, atom );
}


Expand Down
4 changes: 2 additions & 2 deletions atom/src/getattrbehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,15 @@ 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


PyObject*
Member::getattr( CAtom* atom )
{
return handlers[ get_getattr_mode() & 0xf ]( this, atom );
return handlers[ get_getattr_mode() & mask ]( this, atom );
}

} // namespace atom
4 changes: 2 additions & 2 deletions atom/src/getstatebehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,15 @@ 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


PyObject*
Member::should_getstate( CAtom* atom )
{
return handlers[ get_getstate_mode() & 0x7 ]( this, atom );
return handlers[ get_getstate_mode() & mask ]( this, atom );
}

} // namespace atom
4 changes: 2 additions & 2 deletions atom/src/postgetattrbehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,15 @@ 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


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 );
}


Expand Down
4 changes: 2 additions & 2 deletions atom/src/postsetattrbehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,15 @@ 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


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 );
}


Expand Down
4 changes: 2 additions & 2 deletions atom/src/postvalidatebehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ 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


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
4 changes: 2 additions & 2 deletions atom/src/setattrbehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,15 +383,15 @@ 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


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 );
}


Expand Down
7 changes: 3 additions & 4 deletions atom/src/validatebehavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -997,19 +997,18 @@ handlers[] = {
delegate_handler,
object_method_old_new_handler,
object_method_name_old_new_handler,
member_method_object_old_new_handler
member_method_object_old_new_handler,
};

const auto mask = validate_handlers(handlers, Validate::Mode::Last);

} // namespace


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 );
}


Expand Down

0 comments on commit 0395936

Please sign in to comment.