From 192bc725290ca4b271bff2bae6123d84c25f7173 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 20 Oct 2022 14:42:08 +0900 Subject: [PATCH] Define `UNDEF_P` and `NIL_OR_UNDEF_P` [EXPERIMENTAL] --- include/ruby/internal/special_consts.h | 58 ++++++++++++++++++++++++++ internal.h | 3 ++ 2 files changed, 61 insertions(+) diff --git a/include/ruby/internal/special_consts.h b/include/ruby/internal/special_consts.h index a8c992ef5e..6943ef9b94 100644 --- a/include/ruby/internal/special_consts.h +++ b/include/ruby/internal/special_consts.h @@ -76,6 +76,8 @@ #define RB_SPECIAL_CONST_P RB_SPECIAL_CONST_P #define RB_STATIC_SYM_P RB_STATIC_SYM_P #define RB_TEST RB_TEST +#define RB_UNDEF_P RB_UNDEF_P +#define RB_NIL_OR_UNDEF_P RB_NIL_OR_UNDEF_P /** @endcond */ /** special constants - i.e. non-zero and non-fixnum constants */ @@ -173,6 +175,62 @@ RB_NIL_P(VALUE obj) return obj == RUBY_Qnil; } +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks if the given object is undef. + * + * @param[in] obj An arbitrary ruby object. + * @retval true `obj` is ::RUBY_Qundef. + * @retval false Anything else. + */ +static inline bool +RB_UNDEF_P(VALUE obj) +{ + return obj == RUBY_Qundef; +} + +RBIMPL_ATTR_CONST() +RBIMPL_ATTR_CONSTEXPR(CXX11) +RBIMPL_ATTR_ARTIFICIAL() +/** + * Checks if the given object is nil or undef. Can be used to see if + * a keyword argument is not given or given `nil`. + * + * @param[in] obj An arbitrary ruby object. + * @retval true `obj` is ::RUBY_Qnil or ::RUBY_Qundef. + * @retval false Anything else. + */ +static inline bool +RB_NIL_OR_UNDEF_P(VALUE obj) +{ + /* + * if USE_FLONUM + * Qundef: ....0010 0100 + * Qnil: ....0000 0100 + * mask: ....1101 1111 + * common_bits: ....0000 0100 + * --------------------------------- + * Qnil & mask ....0000 0100 + * Qundef & mask ....0000 0100 + * + * if ! USE_FLONUM + * Qundef: ....0000 1010 + * Qnil: ....0000 0010 + * mask: ....1111 0111 + * common_bits: ....0000 0010 + * ---------------------------- + * Qnil & mask ....0000 0010 + * Qundef & mask ....0000 0010 + * + * NIL_OR_UNDEF_P(v) can be true only when v is Qundef or Qnil. + */ + const VALUE mask = ~(RUBY_Qundef ^ RUBY_Qnil); + const VALUE common_bits = RUBY_Qundef & RUBY_Qnil; + return (obj & mask) == common_bits; +} + RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() diff --git a/internal.h b/internal.h index 695c9cfb7e..b63af50616 100644 --- a/internal.h +++ b/internal.h @@ -25,6 +25,9 @@ /* Prevent compiler from reordering access */ #define ACCESS_ONCE(type,x) (*((volatile type *)&(x))) +#define UNDEF_P RB_UNDEF_P +#define NIL_OR_UNDEF_P RB_NIL_OR_UNDEF_P + #include "ruby/ruby.h" /* Following macros were formerly defined in this header but moved to somewhere