Allow ruby versions 3.2 and 3.4 for installation

This commit is contained in:
2026-01-28 22:12:37 +00:00
parent 1312c09501
commit 515d5559a7
200 changed files with 40636 additions and 22 deletions

585
libs/libruby/ruby/internal/core/rarray.h vendored Normal file
View File

@@ -0,0 +1,585 @@
#ifndef RBIMPL_RARRAY_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RARRAY_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Defines struct ::RArray.
*/
#include "ruby/internal/arithmetic/long.h"
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/attr/constexpr.h"
#include "ruby/internal/attr/maybe_unused.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/fl_type.h"
#include "ruby/internal/rgengc.h"
#include "ruby/internal/stdbool.h"
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
#include "ruby/assert.h"
/**
* @private
* @warning Do not touch this macro.
* @warning It is an implementation detail.
* @warning The value of this macro must match for ruby itself and all
* extension libraries, otherwise serious memory corruption shall
* occur.
*/
#ifndef USE_TRANSIENT_HEAP
# define USE_TRANSIENT_HEAP 1
#endif
/**
* Convenient casting macro.
*
* @param obj An object, which is in fact an ::RArray.
* @return The passed object casted to ::RArray.
*/
#define RARRAY(obj) RBIMPL_CAST((struct RArray *)(obj))
/** @cond INTERNAL_MACRO */
#define RARRAY_EMBED_FLAG RARRAY_EMBED_FLAG
#define RARRAY_EMBED_LEN_MASK RARRAY_EMBED_LEN_MASK
#define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX
#define RARRAY_EMBED_LEN_SHIFT RARRAY_EMBED_LEN_SHIFT
#if USE_TRANSIENT_HEAP
# define RARRAY_TRANSIENT_FLAG RARRAY_TRANSIENT_FLAG
#else
# define RARRAY_TRANSIENT_FLAG 0
#endif
/** @endcond */
#define RARRAY_LEN rb_array_len /**< @alias{rb_array_len} */
#define RARRAY_CONST_PTR rb_array_const_ptr /**< @alias{rb_array_const_ptr} */
#define RARRAY_CONST_PTR_TRANSIENT rb_array_const_ptr_transient /**< @alias{rb_array_const_ptr_transient} */
/** @cond INTERNAL_MACRO */
#if defined(__fcc__) || defined(__fcc_version) || \
defined(__FCC__) || defined(__FCC_VERSION)
/* workaround for old version of Fujitsu C Compiler (fcc) */
# define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x))
#else
# define FIX_CONST_VALUE_PTR(x) (x)
#endif
#define RARRAY_EMBED_LEN RARRAY_EMBED_LEN
#define RARRAY_LENINT RARRAY_LENINT
#define RARRAY_TRANSIENT_P RARRAY_TRANSIENT_P
#define RARRAY_ASET RARRAY_ASET
#define RARRAY_PTR RARRAY_PTR
/** @endcond */
/**
* @private
*
* Bits that you can set to ::RBasic::flags.
*
* @warning These enums are not the only bits we use for arrays.
*
* @internal
*
* Unlike strings, flag usages for arrays are scattered across the entire
* source codes. @shyouhei doesn't know the complete list. But what is listed
* here is at least incomplete.
*/
enum ruby_rarray_flags {
/**
* This flag has something to do with memory footprint. If the array is
* "small" enough, ruby tries to be creative to abuse padding bits of
* struct ::RArray for storing its contents. This flag denotes that
* situation.
*
* @warning This bit has to be considered read-only. Setting/clearing
* this bit without corresponding fix up must cause immediate
* SEGV. Also, internal structures of an array change
* dynamically and transparently throughout of its lifetime.
* Don't assume it being persistent.
*
* @internal
*
* 3rd parties must not be aware that there even is more than one way to
* store array elements. It was a bad idea to expose this to them.
*/
RARRAY_EMBED_FLAG = RUBY_FL_USER1,
/* RUBY_FL_USER2 is for ELTS_SHARED */
/**
* When an array employs embedded strategy (see ::RARRAY_EMBED_FLAG), these
* bits are used to store the number of elements actually filled into
* ::RArray::ary.
*
* @internal
*
* 3rd parties must not be aware that there even is more than one way to
* store array elements. It was a bad idea to expose this to them.
*/
#if USE_RVARGC
RARRAY_EMBED_LEN_MASK = RUBY_FL_USER9 | RUBY_FL_USER8 | RUBY_FL_USER7 | RUBY_FL_USER6 |
RUBY_FL_USER5 | RUBY_FL_USER4 | RUBY_FL_USER3
#else
RARRAY_EMBED_LEN_MASK = RUBY_FL_USER4 | RUBY_FL_USER3
#endif
#if USE_TRANSIENT_HEAP
,
/**
* This flag has something to do with an array's "transiency". A transient
* array is an array of young generation (of generational GC), who stores
* its elements inside of dedicated memory pages called a transient heap.
* Not every young generation share that storage scheme, but elder
* generations must no join.
*
* @internal
*
* 3rd parties must not be aware that there even is more than one way to
* store array elements. It was a bad idea to expose this to them.
*/
RARRAY_TRANSIENT_FLAG = RUBY_FL_USER13
#endif
};
/**
* This is an enum because GDB wants it (rather than a macro). People need not
* bother.
*/
enum ruby_rarray_consts {
/** Where ::RARRAY_EMBED_LEN_MASK resides. */
RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3
#if !USE_RVARGC
,
/** Max possible number elements that can be embedded. */
RARRAY_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE)
#endif
};
/** Ruby's array. */
struct RArray {
/** Basic part, including flags and class. */
struct RBasic basic;
/** Array's specific fields. */
union {
/**
* Arrays that use separated memory region for elements use this
* pattern.
*/
struct {
/** Number of elements of the array. */
long len;
/** Auxiliary info. */
union {
/**
* Capacity of `*ptr`. A continuous memory region of at least
* `capa` elements is expected to exist at `*ptr`. This can be
* bigger than `len`.
*/
long capa;
/**
* Parent of the array. Nowadays arrays can share their
* backend memory regions each other, constructing gigantic
* nest of objects. This situation is called "shared", and
* this is the field to control such properties.
*/
#if defined(__clang__) /* <- clang++ is sane */ || \
!defined(__cplusplus) /* <- C99 is sane */ || \
(__cplusplus > 199711L) /* <- C++11 is sane */
const
#endif
VALUE shared_root;
} aux;
/**
* Pointer to the C array that holds the elements of the array. In
* the old days each array had dedicated memory regions. That is
* no longer true today, but there still are arrays of such
* properties. This field could be used to point such things.
*/
const VALUE *ptr;
} heap;
/**
* Embedded elements. When an array is short enough, it uses this area
* to store its elements. In this case the length is encoded into the
* flags.
*/
#if USE_RVARGC
/* This is a length 1 array because:
* 1. GCC has a bug that does not optimize C flexible array members
* (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
* 2. Zero length arrays are not supported by all compilers
*/
const VALUE ary[1];
#else
const VALUE ary[RARRAY_EMBED_LEN_MAX];
#endif
} as;
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
* @private
*
* Declares a section of code where raw pointers are used. This is an
* implementation detail of #RARRAY_PTR_USE. People don't use it directly.
*
* @param[in] ary An object of ::RArray.
* @return `ary`'s backend C array.
*/
VALUE *rb_ary_ptr_use_start(VALUE ary);
/**
* @private
*
* Declares an end of a section formerly started by rb_ary_ptr_use_start().
* This is an implementation detail of #RARRAY_PTR_USE. People don't use it
* directly.
*
* @param[in] a An object of ::RArray.
*/
void rb_ary_ptr_use_end(VALUE a);
#if USE_TRANSIENT_HEAP
/**
* Destructively converts an array of transient backend into ordinal one.
*
* @param[out] a An object of ::RArray.
* @pre `a` must be a transient array.
* @post `a` gets out of transient heap, destructively.
*/
void rb_ary_detransient(VALUE a);
#endif
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Queries the length of the array.
*
* @param[in] ary Array in question.
* @return Its number of elements.
* @pre `ary` must be an instance of ::RArray, and must has its
* ::RARRAY_EMBED_FLAG flag set.
*
* @internal
*
* This was a macro before. It was inevitable to be public, since macros are
* global constructs. But should it be forever? Now that it is a function,
* @shyouhei thinks it could just be eliminated, hidden into implementation
* details.
*/
static inline long
RARRAY_EMBED_LEN(VALUE ary)
{
RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
RBIMPL_ASSERT_OR_ASSUME(RB_FL_ANY_RAW(ary, RARRAY_EMBED_FLAG));
VALUE f = RBASIC(ary)->flags;
f &= RARRAY_EMBED_LEN_MASK;
f >>= RARRAY_EMBED_LEN_SHIFT;
return RBIMPL_CAST((long)f);
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
/**
* Queries the length of the array.
*
* @param[in] a Array in question.
* @return Its number of elements.
* @pre `a` must be an instance of ::RArray.
*/
static inline long
rb_array_len(VALUE a)
{
RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) {
return RARRAY_EMBED_LEN(a);
}
else {
return RARRAY(a)->as.heap.len;
}
}
RBIMPL_ATTR_ARTIFICIAL()
/**
* Identical to rb_array_len(), except it differs for the return type.
*
* @param[in] ary Array in question.
* @exception rb_eRangeError Too long.
* @return Its number of elements.
* @pre `ary` must be an instance of ::RArray.
*
* @internal
*
* This API seems redundant but has actual usages.
*/
static inline int
RARRAY_LENINT(VALUE ary)
{
return rb_long2int(RARRAY_LEN(ary));
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Queries if the array is a transient array.
*
* @param[in] ary Array in question.
* @retval true Yes it is.
* @retval false No it isn't.
* @pre `ary` must be an instance of ::RArray.
*
* @internal
*
* @shyouhei doesn't understand the benefit of this function called from
* extension libraries.
*/
static inline bool
RARRAY_TRANSIENT_P(VALUE ary)
{
RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
#if USE_TRANSIENT_HEAP
return RB_FL_ANY_RAW(ary, RARRAY_TRANSIENT_FLAG);
#else
return false;
#endif
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
/**
* @private
*
* This is an implementation detail of RARRAY_PTR(). People do not use it
* directly.
*
* @param[in] a An object of ::RArray.
* @return Its backend storage.
*/
static inline const VALUE *
rb_array_const_ptr_transient(VALUE a)
{
RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) {
return FIX_CONST_VALUE_PTR(RARRAY(a)->as.ary);
}
else {
return FIX_CONST_VALUE_PTR(RARRAY(a)->as.heap.ptr);
}
}
#if ! USE_TRANSIENT_HEAP
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
#endif
/**
* @private
*
* This is an implementation detail of RARRAY_PTR(). People do not use it
* directly.
*
* @param[in] a An object of ::RArray.
* @return Its backend storage.
* @post `a` is not a transient array.
*/
static inline const VALUE *
rb_array_const_ptr(VALUE a)
{
RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
#if USE_TRANSIENT_HEAP
if (RARRAY_TRANSIENT_P(a)) {
rb_ary_detransient(a);
}
#endif
return rb_array_const_ptr_transient(a);
}
/**
* @private
*
* This is an implementation detail of #RARRAY_PTR_USE. People do not use it
* directly.
*
* @param[in] a An object of ::RArray.
* @param[in] allow_transient Whether `a` can be transient or not.
* @return Its backend storage.
* @post `a` is not a transient array unless `allow_transient`.
*/
static inline VALUE *
rb_array_ptr_use_start(VALUE a,
RBIMPL_ATTR_MAYBE_UNUSED()
int allow_transient)
{
RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
#if USE_TRANSIENT_HEAP
if (!allow_transient) {
if (RARRAY_TRANSIENT_P(a)) {
rb_ary_detransient(a);
}
}
#endif
return rb_ary_ptr_use_start(a);
}
/**
* @private
*
* This is an implementation detail of #RARRAY_PTR_USE. People do not use it
* directly.
*
* @param[in] a An object of ::RArray.
* @param[in] allow_transient Whether `a` can be transient or not.
*/
static inline void
rb_array_ptr_use_end(VALUE a,
RBIMPL_ATTR_MAYBE_UNUSED()
int allow_transient)
{
RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
rb_ary_ptr_use_end(a);
}
/**
* @private
*
* This is an implementation detail of #RARRAY_PTR_USE. People do not use it
* directly.
*/
#define RBIMPL_RARRAY_STMT(flag, ary, var, expr) do { \
RBIMPL_ASSERT_TYPE((ary), RUBY_T_ARRAY); \
const VALUE rbimpl_ary = (ary); \
VALUE *var = rb_array_ptr_use_start(rbimpl_ary, (flag)); \
expr; \
rb_array_ptr_use_end(rbimpl_ary, (flag)); \
} while (0)
/**
* @private
*
* This is an implementation detail of #RARRAY_PTR_USE. People do not use it
* directly.
*/
#define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0)
/**
* Declares a section of code where raw pointers are used. In case you need to
* touch the raw C array instead of polite CAPIs, then that operation shall be
* wrapped using this macro.
*
* ```CXX
* const auto ary = rb_eval_string("[...]");
* const auto len = RARRAY_LENINT(ary);
* const auto symwrite = rb_intern("write");
*
* RARRAY_PTR_USE(ary, ptr, {
* rb_funcallv(rb_stdout, symwrite, len, ptr);
* });
* ```
*
* @param ary An object of ::RArray.
* @param ptr_name A variable name which points the C array in `expr`.
* @param expr The expression that touches `ptr_name`.
*
* @internal
*
* For historical reasons use of this macro is not enforced. There are
* extension libraries in the wild which call RARRAY_PTR() without it. We want
* them use it... Maybe some transition path can be implemented later.
*/
#define RARRAY_PTR_USE(ary, ptr_name, expr) \
RBIMPL_RARRAY_STMT(0, ary, ptr_name, expr)
/**
* Identical to #RARRAY_PTR_USE, except the pointer can be a transient one.
*
* @param ary An object of ::RArray.
* @param ptr_name A variable name which points the C array in `expr`.
* @param expr The expression that touches `ptr_name`.
*/
#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) \
RBIMPL_RARRAY_STMT(1, ary, ptr_name, expr)
/**
* Wild use of a C pointer. This function accesses the backend storage
* directly. This is slower than #RARRAY_PTR_USE_TRANSIENT. It exercises
* extra manoeuvres to protect our generational GC. Use of this function is
* considered archaic. Use a modern way instead.
*
* @param[in] ary An object of ::RArray.
* @return The backend C array.
*
* @internal
*
* That said... there are extension libraries in the wild who uses it. We
* cannot but continue supporting.
*/
static inline VALUE *
RARRAY_PTR(VALUE ary)
{
RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
VALUE tmp = RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary);
return RBIMPL_CAST((VALUE *)RARRAY_CONST_PTR(tmp));
}
/**
* Assigns an object in an array.
*
* @param[out] ary Destination array object.
* @param[in] i Index of `ary`.
* @param[in] v Arbitrary ruby object.
* @pre `ary` must be an instance of ::RArray.
* @pre `ary`'s length must be longer than or equal to `i`.
* @pre `i` must be greater than or equal to zero.
* @post `ary`'s `i`th element is set to `v`.
*/
static inline void
RARRAY_ASET(VALUE ary, long i, VALUE v)
{
RARRAY_PTR_USE_TRANSIENT(ary, ptr,
RB_OBJ_WRITE(ary, &ptr[i], v));
}
/**
* @deprecated
*
* :FIXME: we want to convert RARRAY_AREF into an inline function (to add rooms
* for more sanity checks). However there were situations where the address of
* this macro is taken i.e. &RARRAY_AREF(...). They cannot be possible if this
* is not a macro. Such usages are abuse, and we eliminated them internally.
* However we are afraid of similar things to remain in the wild. This macro
* remains as it is due to that. If we could warn such usages we can set a
* transition path, but currently no way is found to do so.
*/
#define RARRAY_AREF(a, i) RARRAY_CONST_PTR_TRANSIENT(a)[i]
#endif /* RBIMPL_RARRAY_H */

158
libs/libruby/ruby/internal/core/rbasic.h vendored Normal file
View File

@@ -0,0 +1,158 @@
#ifndef RBIMPL_RBASIC_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RBASIC_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Defines struct ::RBasic.
*/
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/attr/constexpr.h"
#include "ruby/internal/attr/forceinline.h"
#include "ruby/internal/attr/noalias.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/special_consts.h"
#include "ruby/internal/value.h"
#include "ruby/assert.h"
/**
* Convenient casting macro.
*
* @param obj Arbitrary Ruby object.
* @return The passed object casted to ::RBasic.
*/
#define RBASIC(obj) RBIMPL_CAST((struct RBasic *)(obj))
/** @cond INTERNAL_MACRO */
#define RBASIC_CLASS RBASIC_CLASS
#define RBIMPL_RVALUE_EMBED_LEN_MAX 3
#define RVALUE_EMBED_LEN_MAX RVALUE_EMBED_LEN_MAX
#define RBIMPL_EMBED_LEN_MAX_OF(T) \
RBIMPL_CAST((int)(sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX]) / (sizeof(T))))
/** @endcond */
/**
* This is an enum because GDB wants it (rather than a macro). People need not
* bother.
*/
enum ruby_rvalue_flags {
/** Max possible number of objects that can be embedded. */
RVALUE_EMBED_LEN_MAX = RBIMPL_RVALUE_EMBED_LEN_MAX
};
/**
* Ruby's object's, base components. Every single ruby objects have them in
* common.
*/
struct
RUBY_ALIGNAS(SIZEOF_VALUE)
RBasic {
/**
* Per-object flags. Each ruby objects have their own characteristics
* apart from their classes. For instance whether an object is frozen or
* not is not controlled by its class. This is where such properties are
* stored.
*
* @see enum ::ruby_fl_type
*
* @note This is ::VALUE rather than an enum for alignment purpose. Back
* in the 1990s there were no such thing like `_Alignas` in C.
*/
VALUE flags;
/**
* Class of an object. Every object has its class. Also, everything is an
* object in Ruby. This means classes are also objects. Classes have
* their own classes, classes of classes have their classes, too ... and
* it recursively continues forever.
*
* Also note the `const` qualifier. In ruby an object cannot "change" its
* class.
*/
const VALUE klass;
#ifdef __cplusplus
public:
RBIMPL_ATTR_CONSTEXPR(CXX11)
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_FORCEINLINE()
RBIMPL_ATTR_NOALIAS()
/**
* We need to define this explicit constructor because the field `klass` is
* const-qualified above, which effectively defines the implicit default
* constructor as "deleted" (as of C++11) -- No way but to define one by
* ourselves.
*/
RBasic() :
flags(RBIMPL_VALUE_NULL),
klass(RBIMPL_VALUE_NULL)
{
}
#endif
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
* Make the object invisible from Ruby code.
*
* It is useful to let Ruby's GC manage your internal data structure -- The
* object keeps being managed by GC, but `ObjectSpace.each_object` never yields
* the object.
*
* Note that the object also lose a way to call a method on it.
*
* @param[out] obj A Ruby object.
* @return The passed object.
* @post The object is destructively modified to be invisible.
* @see rb_obj_reveal
*/
VALUE rb_obj_hide(VALUE obj);
/**
* Make a hidden object visible again.
*
* It is the caller's responsibility to pass the right `klass` which `obj`
* originally used to belong to.
*
* @param[out] obj A Ruby object.
* @param[in] klass Class of `obj`.
* @return Passed `obj`.
* @pre `obj` was previously hidden.
* @post `obj`'s class is `klass`.
* @see rb_obj_hide
*/
VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Queries the class of an object.
*
* @param[in] obj An object.
* @return Its class.
*/
static inline VALUE
RBASIC_CLASS(VALUE obj)
{
RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj));
return RBASIC(obj)->klass;
}
#endif /* RBIMPL_RBASIC_H */

View File

@@ -0,0 +1,80 @@
#ifndef RBIMPL_RBIGNUM_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RBIGNUM_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Routines to manipulate struct RBignum.
* @note The struct RBignum itself is opaque.
*/
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
#include "ruby/internal/stdbool.h"
#define RBIGNUM_SIGN rb_big_sign /**< @alias{rb_big_sign} */
/** @cond INTERNAL_MACRO */
#define RBIGNUM_POSITIVE_P RBIGNUM_POSITIVE_P
#define RBIGNUM_NEGATIVE_P RBIGNUM_NEGATIVE_P
/** @endcond */
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
* The "sign" of a bignum.
*
* @param[in] num An object of RBignum.
* @retval 1 It is greater than or equal to zero.
* @retval 0 It is less than zero.
*
* @internal
*
* Implementation wise, unlike fixnums (which are 2's complement), bignums are
* signed magnitude system. Theoretically it could be possible to have
* negative zero instances. But in reality there is no way to create such
* thing. Nobody ever needed that kind of insanity.
*/
int rb_big_sign(VALUE num);
RBIMPL_SYMBOL_EXPORT_END()
/**
* Checks if the bignum is positive.
* @param[in] b An object of RBignum.
* @retval false `b` is less than zero.
* @retval true Otherwise.
*/
static inline bool
RBIGNUM_POSITIVE_P(VALUE b)
{
RBIMPL_ASSERT_TYPE(b, RUBY_T_BIGNUM);
return RBIGNUM_SIGN(b);
}
/**
* Checks if the bignum is negative.
* @param[in] b An object of RBignum.
* @retval true `b` is less than zero.
* @retval false Otherwise.
*/
static inline bool
RBIGNUM_NEGATIVE_P(VALUE b)
{
RBIMPL_ASSERT_TYPE(b, RUBY_T_BIGNUM);
return ! RBIGNUM_POSITIVE_P(b);
}
#endif /* RBIMPL_RBIGNUM_H */

View File

@@ -0,0 +1,93 @@
#ifndef RBIMPL_RCLASS_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RCLASS_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Routines to manipulate struct RClass.
* @note The struct RClass itself is opaque.
*/
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/internal/cast.h"
/** @cond INTERNAL_MACRO */
#define RMODULE_IS_REFINEMENT RMODULE_IS_REFINEMENT
/** @endcond */
/**
* Convenient casting macro.
*
* @param obj An object, which is in fact an RClass.
* @return The passed object casted to RClass.
*/
#define RCLASS(obj) RBIMPL_CAST((struct RClass *)(obj))
/** @alias{RCLASS} */
#define RMODULE RCLASS
/** @alias{rb_class_get_superclass} */
#define RCLASS_SUPER rb_class_get_superclass
/**
* @private
*
* Bits that you can set to ::RBasic::flags.
*
* @internal
*
* Why is it here, given RClass itself is not?
*/
enum ruby_rmodule_flags {
/**
* This flag has something to do with refinements. A module created using
* rb_mod_refine() has this flag set. This is the bit which controls
* difference between normal inclusion versus refinements.
*/
RMODULE_IS_REFINEMENT = RUBY_FL_USER3
};
struct RClass; /* Opaque, declared here for RCLASS() macro. */
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
* Returns the superclass of a class.
* @param[in] klass An object of RClass.
* @retval RUBY_Qfalse `klass` has no super class.
* @retval otherwise Raw superclass of `klass`
* @see rb_class_superclass
*
* ### Q&A ###
*
* - Q: How can a class have no super class?
*
* - A: `klass` could be a module. Or it could be ::rb_cBasicObject.
*
* - Q: What do you mean by "raw" superclass?
*
* - A: This is a really good question. The answer is that this function
* returns something different from what you would normally expect. On
* occasions ruby inserts hidden classes in a hierarchy of class
* inheritance behind-the-scene. Such classes are called "iclass"es and
* distinguished using ::RUBY_T_ICLASS in C level. They are truly
* transparent from Ruby level but can be accessed from C, by using this
* API.
*/
VALUE rb_class_get_superclass(VALUE klass);
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RBIMPL_RCLASS_H */

386
libs/libruby/ruby/internal/core/rdata.h vendored Normal file
View File

@@ -0,0 +1,386 @@
#ifndef RBIMPL_RDATA_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RDATA_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Defines struct ::RData.
*/
#include "ruby/internal/config.h"
#ifdef STDC_HEADERS
# include <stddef.h>
#endif
#include "ruby/internal/attr/deprecated.h"
#include "ruby/internal/attr/warning.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/fl_type.h"
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
#include "ruby/defines.h"
/** @cond INTERNAL_MACRO */
#ifdef RUBY_UNTYPED_DATA_WARNING
# /* Take that. */
#elif defined(RUBY_EXPORT)
# define RUBY_UNTYPED_DATA_WARNING 1
#else
# define RUBY_UNTYPED_DATA_WARNING 0
#endif
#define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f))
#define RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() \
RBIMPL_ATTR_WARNING(("untyped Data is unsafe; use TypedData instead")) \
RBIMPL_ATTR_DEPRECATED(("by TypedData"))
#define RBIMPL_MACRO_SELECT(x, y) x ## y
#define RUBY_MACRO_SELECT(x, y) RBIMPL_MACRO_SELECT(x, y)
/** @endcond */
/**
* Convenient casting macro.
*
* @param obj An object, which is in fact an ::RData.
* @return The passed object casted to ::RData.
*/
#define RDATA(obj) RBIMPL_CAST((struct RData *)(obj))
/**
* Convenient getter macro.
*
* @param obj An object, which is in fact an ::RData.
* @return The passed object's ::RData::data field.
*/
#define DATA_PTR(obj) RDATA(obj)->data
/**
* This is a value you can set to ::RData::dfree. Setting this means the data
* was allocated using ::ruby_xmalloc() (or variants), and shall be freed using
* ::ruby_xfree().
*
* @warning Do not use this if you want to use system malloc, because the
* system and Ruby might or might not share the same malloc
* implementation.
*/
#define RUBY_DEFAULT_FREE RBIMPL_DATA_FUNC(-1)
/**
* This is a value you can set to ::RData::dfree. Setting this means the data
* is managed by someone else, like, statically allocated. Of course you are
* on your own then.
*/
#define RUBY_NEVER_FREE RBIMPL_DATA_FUNC(0)
/**
* @private
*
* @deprecated This macro once was a thing in the old days, but makes no sense
* any longer today. Exists here for backwards compatibility
* only. You can safely forget about it.
*/
#define RUBY_UNTYPED_DATA_FUNC(f) f RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
/*
#define RUBY_DATA_FUNC(func) ((void (*)(void*))(func))
*/
/**
* This is the type of callbacks registered to ::RData. The argument is the
* `data` field.
*/
typedef void (*RUBY_DATA_FUNC)(void*);
/**
* @deprecated
*
* Old "untyped" user data. It has roughly the same usage as struct
* ::RTypedData, but lacked several features such as support for compaction GC.
* Use of this struct is not recommended any longer. If it is dead necessary,
* please inform the core devs about your usage.
*
* @internal
*
* @shyouhei tried to add RBIMPL_ATTR_DEPRECATED for this type but that yielded
* too many warnings in the core. Maybe we want to retry later... Just add
* deprecated document for now.
*/
struct RData {
/** Basic part, including flags and class. */
struct RBasic basic;
/**
* This function is called when the object is experiencing GC marks. If it
* contains references to other Ruby objects, you need to mark them also.
* Otherwise GC will smash your data.
*
* @see rb_gc_mark()
* @warning This is called during GC runs. Object allocations are
* impossible at that moment (that is why GC runs).
*/
RUBY_DATA_FUNC dmark;
/**
* This function is called when the object is no longer used. You need to
* do whatever necessary to avoid memory leaks.
*
* @warning This is called during GC runs. Object allocations are
* impossible at that moment (that is why GC runs).
*/
RUBY_DATA_FUNC dfree;
/** Pointer to the actual C level struct that you want to wrap. */
void *data;
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
* This is the primitive way to wrap an existing C struct into ::RData.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] datap Pointer to the target C struct.
* @param[in] dmark Mark function.
* @param[in] dfree Free function.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return An allocated object that wraps `datap`.
*/
VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree);
/**
* Identical to rb_data_object_wrap(), except it allocates a new data region
* internally instead of taking an existing one. The allocation is done using
* ruby_calloc(). Hence it makes no sense to pass anything other than
* ::RUBY_DEFAULT_FREE to the last argument.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] size Requested size of memory to allocate.
* @param[in] dmark Mark function.
* @param[in] dfree Free function.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return An allocated object that wraps a new `size` byte region.
*/
VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree);
/**
* @private
* Documented in include/ruby/internal/globals.h
*/
RUBY_EXTERN VALUE rb_cObject;
RBIMPL_SYMBOL_EXPORT_END()
/**
* Converts sval, a pointer to your struct, into a Ruby object.
*
* @param klass A ruby level class.
* @param mark Mark function.
* @param free Free function.
* @param sval A pointer to your struct.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return A created Ruby object.
*/
#define Data_Wrap_Struct(klass, mark, free, sval) \
rb_data_object_wrap( \
(klass), \
(sval), \
RBIMPL_DATA_FUNC(mark), \
RBIMPL_DATA_FUNC(free))
/**
* @private
*
* This is an implementation detail of #Data_Make_Struct. People don't use it
* directly.
*
* @param result Variable name of created Ruby object.
* @param klass Ruby level class of the object.
* @param type Type name of the C struct.
* @param size Size of the C struct.
* @param mark Mark function.
* @param free Free function.
* @param sval Variable name of created C struct.
*/
#define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \
VALUE result = rb_data_object_zalloc( \
(klass), \
(size), \
RBIMPL_DATA_FUNC(mark), \
RBIMPL_DATA_FUNC(free)); \
(sval) = RBIMPL_CAST((type *)DATA_PTR(result)); \
RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
/**
* Identical to #Data_Wrap_Struct, except it allocates a new data region
* internally instead of taking an existing one. The allocation is done using
* ruby_calloc(). Hence it makes no sense to pass anything other than
* ::RUBY_DEFAULT_FREE to the `free` argument.
*
* @param klass Ruby level class of the returning object.
* @param type Type name of the C struct.
* @param mark Mark function.
* @param free Free function.
* @param sval Variable name of created C struct.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return A created Ruby object.
*/
#ifdef HAVE_STMT_AND_DECL_IN_EXPR
#define Data_Make_Struct(klass, type, mark, free, sval) \
RB_GNUC_EXTENSION({ \
Data_Make_Struct0( \
data_struct_obj, \
klass, \
type, \
sizeof(type), \
mark, \
free, \
sval); \
data_struct_obj; \
})
#else
#define Data_Make_Struct(klass, type, mark, free, sval) \
rb_data_object_make( \
(klass), \
RBIMPL_DATA_FUNC(mark), \
RBIMPL_DATA_FUNC(free), \
RBIMPL_CAST((void **)&(sval)), \
sizeof(type))
#endif
/**
* Obtains a C struct from inside of a wrapper Ruby object.
*
* @param obj An instance of ::RData.
* @param type Type name of the C struct.
* @param sval Variable name of obtained C struct.
* @return Unwrapped C struct that `obj` holds.
*/
#define Data_Get_Struct(obj, type, sval) \
((sval) = RBIMPL_CAST((type*)rb_data_object_get(obj)))
RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
/**
* @private
*
* This is an implementation detail of rb_data_object_wrap(). People don't use
* it directly.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] ptr Pointer to the target C struct.
* @param[in] mark Mark function.
* @param[in] free Free function.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return An allocated object that wraps `datap`.
*/
static inline VALUE
rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free)
{
return rb_data_object_wrap(klass, ptr, mark, free);
}
/**
* @private
*
* This is an implementation detail of #Data_Get_Struct. People don't use it
* directly.
*
* @param[in] obj An instance of ::RData.
* @return Unwrapped C struct that `obj` holds.
*/
static inline void *
rb_data_object_get(VALUE obj)
{
Check_Type(obj, RUBY_T_DATA);
return DATA_PTR(obj);
}
RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
/**
* @private
*
* This is an implementation detail of #Data_Get_Struct. People don't use it
* directly.
*
* @param[in] obj An instance of ::RData.
* @return Unwrapped C struct that `obj` holds.
*/
static inline void *
rb_data_object_get_warning(VALUE obj)
{
return rb_data_object_get(obj);
}
#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
# define rb_data_object_wrap_warning(klass, ptr, mark, free) \
RB_GNUC_EXTENSION( \
__builtin_choose_expr( \
__builtin_constant_p(klass) && !(klass), \
rb_data_object_wrap(klass, ptr, mark, free), \
(rb_data_object_wrap_warning)(klass, ptr, mark, free)))
#endif
/**
* This is an implementation detail of #Data_Make_Struct. People don't use it
* directly.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] mark_func Mark function.
* @param[in] free_func Free function.
* @param[in] datap Variable of created C struct.
* @param[in] size Requested size of allocation.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return A created Ruby object.
* @post `*datap` holds the created C struct.
*/
static inline VALUE
rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size)
{
Data_Make_Struct0(result, klass, void, size, mark_func, free_func, *datap);
return result;
}
RBIMPL_ATTR_DEPRECATED(("by: rb_data_object_wrap"))
/** @deprecated This function was renamed to rb_data_object_wrap(). */
static inline VALUE
rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
{
return rb_data_object_wrap(klass, data, dmark, dfree);
}
/** @cond INTERNAL_MACRO */
#define rb_data_object_wrap_0 rb_data_object_wrap
#define rb_data_object_wrap_1 rb_data_object_wrap_warning
#define rb_data_object_wrap_2 rb_data_object_wrap_ /* Used here vvvv */
#define rb_data_object_wrap RUBY_MACRO_SELECT(rb_data_object_wrap_2, RUBY_UNTYPED_DATA_WARNING)
#define rb_data_object_get_0 rb_data_object_get
#define rb_data_object_get_1 rb_data_object_get_warning
#define rb_data_object_get_2 rb_data_object_get_ /* Used here vvvv */
#define rb_data_object_get RUBY_MACRO_SELECT(rb_data_object_get_2, RUBY_UNTYPED_DATA_WARNING)
#define rb_data_object_make_0 rb_data_object_make
#define rb_data_object_make_1 rb_data_object_make_warning
#define rb_data_object_make_2 rb_data_object_make_ /* Used here vvvv */
#define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_2, RUBY_UNTYPED_DATA_WARNING)
/** @endcond */
#endif /* RBIMPL_RDATA_H */

51
libs/libruby/ruby/internal/core/rfile.h vendored Normal file
View File

@@ -0,0 +1,51 @@
#ifndef RBIMPL_RFILE_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RFILE_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Defines struct ::RFile.
*/
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/cast.h"
/* rb_io_t is in ruby/io.h. The header file has historically not been included
* into ruby/ruby.h. We follow that tradition. */
struct rb_io_t;
/**
* Ruby's File and IO. Ruby's IO are not just file descriptors. They have
* buffers. They also have encodings. Various information are controlled
* using this struct.
*/
struct RFile {
/** Basic part, including flags and class. */
struct RBasic basic;
/** IO's specific fields. */
struct rb_io_t *fptr;
};
/**
* Convenient casting macro.
*
* @param obj An object, which is in fact an ::RFile.
* @return The passed object casted to ::RFile.
*/
#define RFILE(obj) RBIMPL_CAST((struct RFile *)(obj))
#endif /* RBIMPL_RFILE_H */

144
libs/libruby/ruby/internal/core/rhash.h vendored Normal file
View File

@@ -0,0 +1,144 @@
#ifndef RBIMPL_RHASH_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RHASH_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Routines to manipulate struct RHash.
* @note The struct RHash itself is opaque.
*/
#include "ruby/internal/config.h"
#ifdef STDC_HEADERS
# include <stddef.h>
#endif
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY
# include "ruby/backward.h"
#endif
/**
* Retrieves the internal table.
*
* @param[in] h An instance of RHash.
* @pre `h` must be of ::RUBY_T_HASH.
* @return A struct st_table which has the contents of this hash.
* @note Nowadays as Ruby evolved over ages, RHash has multiple backend
* storage engines. `h`'s backend is not guaranteed to be a
* st_table. This function creates one when necessary.
*/
#define RHASH_TBL(h) rb_hash_tbl(h, __FILE__, __LINE__)
/**
* @private
*
* @deprecated This macro once was a thing in the old days, but makes no sense
* any longer today. Exists here for backwards compatibility
* only. You can safely forget about it.
*
* @internal
*
* Declaration of rb_hash_iter_lev() is at include/ruby/backward.h.
*/
#define RHASH_ITER_LEV(h) rb_hash_iter_lev(h)
/**
* @private
*
* @deprecated This macro once was a thing in the old days, but makes no sense
* any longer today. Exists here for backwards compatibility
* only. You can safely forget about it.
*
* @internal
*
* Declaration of rb_hash_ifnone() is at include/ruby/backward.h.
*/
#define RHASH_IFNONE(h) rb_hash_ifnone(h)
/**
* Queries the size of the hash. Size here means the number of keys that the
* hash stores.
*
* @param[in] h An instance of RHash.
* @pre `h` must be of ::RUBY_T_HASH.
* @return The size of the hash.
*/
#define RHASH_SIZE(h) rb_hash_size_num(h)
/**
* Checks if the hash is empty.
*
* @param[in] h An instance of RHash.
* @pre `h` must be of ::RUBY_T_HASH.
* @retval true It is.
* @retval false It isn't.
*/
#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0)
/**
* Destructively updates the default value of the hash.
*
* @param[out] h An instance of RHash.
* @param[in] ifnone Arbitrary default value.
* @pre `h` must be of ::RUBY_T_HASH.
*
* @internal
*
* But why you can set this, given rb_hash_ifnone() doesn't exist?
*/
#define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone)
struct st_table; /* in ruby/st.h */
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
* This is the implementation detail of #RHASH_SIZE. People don't call this
* directly.
*
* @param[in] hash An instance of RHash.
* @pre `hash` must be of ::RUBY_T_HASH.
* @return The size of the hash.
*/
size_t rb_hash_size_num(VALUE hash);
/**
* This is the implementation detail of #RHASH_TBL. People don't call this
* directly.
*
* @param[in] hash An instance of RHash.
* @param[in] file The `__FILE__`.
* @param[in] line The `__LINE__`.
* @pre `hash` must be of ::RUBY_T_HASH.
* @return Table that has the contents of the hash.
*/
struct st_table *rb_hash_tbl(VALUE hash, const char *file, int line);
/**
* This is the implementation detail of #RHASH_SET_IFNONE. People don't call
* this directly.
*
* @param[out] hash An instance of RHash.
* @param[in] ifnone Arbitrary default value.
* @pre `hash` must be of ::RUBY_T_HASH.
*/
VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone);
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RBIMPL_RHASH_H */

146
libs/libruby/ruby/internal/core/rmatch.h vendored Normal file
View File

@@ -0,0 +1,146 @@
#ifndef RBIMPL_RMATCH_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RMATCH_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Defines struct ::RMatch.
*/
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
#include "ruby/assert.h"
/**
* Convenient casting macro.
*
* @param obj An object, which is in fact an ::RMatch.
* @return The passed object casted to ::RMatch.
*/
#define RMATCH(obj) RBIMPL_CAST((struct RMatch *)(obj))
/** @cond INTERNAL_MACRO */
#define RMATCH_REGS RMATCH_REGS
/** @endcond */
struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */
struct re_registers; /* Also in onigmo.h */
/**
* @old{re_pattern_buffer}
*
* @internal
*
* @shyouhei wonders: is anyone actively using this typedef ...?
*/
typedef struct re_pattern_buffer Regexp;
/**
* Represents the region of a capture group. This is basically for caching
* purpose. re_registers have similar concepts (`beg` and `end`) but they are
* in `ptrdiff_t*`. In order for us to implement `MatchData#offset` that info
* has to be converted to offset integers. This is the struct to hold such
* things.
*
* @internal
*
* But why on earth it has to be visible from extension libraries?
*/
struct rmatch_offset {
long beg; /**< Beginning of a group. */
long end; /**< End of a group. */
};
/** Represents a match. */
struct rmatch {
/**
* "Registers" of a match. This is a quasi-opaque struct that holds
* execution result of a match. Roughly resembles `&~`.
*/
struct re_registers regs;
/** Capture group offsets, in C array. */
struct rmatch_offset *char_offset;
/** Number of ::rmatch_offset that ::rmatch::char_offset holds. */
int char_offset_num_allocated;
};
/**
* Regular expression execution context. When a regular expression "matches"
* to a string, it generates capture groups etc. This struct holds that info.
* Visible from Ruby as an instance of `MatchData`.
*
* @note There is no way for extension libraries to manually generate this
* struct except by actually exercising the match operation of a regular
* expression.
*/
struct RMatch {
/** Basic part, including flags and class. */
struct RBasic basic;
/**
* The target string that the match was made against.
*/
VALUE str;
/**
* The result of this match.
*/
struct rmatch *rmatch;
/**
* The expression of this match.
*/
VALUE regexp; /* RRegexp */
};
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Queries the raw ::re_registers.
*
* @param[in] match A match object
* @pre `match` must be of ::RMatch.
* @return Its execution result.
* @note Good. So you are aware of the fact that it could return NULL.
* Yes. It actually does. This is a really bizarre thing. The
* situation is about `String#gsub` and its family. They take
* strings as arguments, like `"foo".sub("bar", "baz")`. On such
* situations, in order to optimise memory allocations, these
* methods do not involve regular expressions at all. They just
* sequentially scan the receiver. Okay. The story begins here.
* Even when they do not kick our regexp engine, there must be
* backref objects e.g. `$&`. But how? You know what? Ruby fakes
* them. It allocates an empty ::RMatch and behaves as if there
* were execution contexts. In reality there weren't. No
* ::re_registers are allocated then. There is no way for this
* function but to return NULL for those fake ::RMatch. This is
* the reason for the nullability of this function.
*/
static inline struct re_registers *
RMATCH_REGS(VALUE match)
{
RBIMPL_ASSERT_TYPE(match, RUBY_T_MATCH);
RBIMPL_ASSERT_OR_ASSUME(RMATCH(match)->rmatch != NULL);
return &RMATCH(match)->rmatch->regs;
}
#endif /* RBIMPL_RMATCH_H */

View File

@@ -0,0 +1,176 @@
#ifndef RBIMPL_ROBJECT_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_ROBJECT_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Defines struct ::RObject.
*/
#include "ruby/internal/config.h"
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/attr/deprecated.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/fl_type.h"
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
/**
* Convenient casting macro.
*
* @param obj An object, which is in fact an ::RObject.
* @return The passed object casted to ::RObject.
*/
#define ROBJECT(obj) RBIMPL_CAST((struct RObject *)(obj))
/** @cond INTERNAL_MACRO */
#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX
#define ROBJECT_EMBED ROBJECT_EMBED
#define ROBJECT_IV_CAPACITY ROBJECT_IV_CAPACITY
#define ROBJECT_IVPTR ROBJECT_IVPTR
/** @endcond */
/**
* @private
*
* Bits that you can set to ::RBasic::flags.
*/
enum ruby_robject_flags {
/**
* This flag has something to do with memory footprint. If the object is
* "small" enough, ruby tries to be creative to abuse padding bits of
* struct ::RObject for storing instance variables. This flag denotes that
* situation.
*
* @warning This bit has to be considered read-only. Setting/clearing
* this bit without corresponding fix up must cause immediate
* SEGV. Also, internal structures of an object change
* dynamically and transparently throughout of its lifetime.
* Don't assume it being persistent.
*
* @internal
*
* 3rd parties must not be aware that there even is more than one way to
* store instance variables. Might better be hidden.
*/
ROBJECT_EMBED = RUBY_FL_USER1
};
#if !USE_RVARGC
/**
* This is an enum because GDB wants it (rather than a macro). People need not
* bother.
*/
enum ruby_robject_consts {
/** Max possible number of instance variables that can be embedded. */
ROBJECT_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE)
};
#endif
struct st_table;
/**
* Ruby's ordinal objects. Unless otherwise special cased, all predefined and
* user-defined classes share this struct to hold their instances.
*/
struct RObject {
/** Basic part, including flags and class. */
struct RBasic basic;
/** Object's specific fields. */
union {
/**
* Object that use separated memory region for instance variables use
* this pattern.
*/
struct {
/** Pointer to a C array that holds instance variables. */
VALUE *ivptr;
/**
* This is a table that holds instance variable name to index
* mapping. Used when accessing instance variables using names.
*
* @internal
*
* This is a shortcut for `RCLASS_IV_INDEX_TBL(rb_obj_class(obj))`.
*/
struct rb_id_table *iv_index_tbl;
} heap;
#if USE_RVARGC
/* Embedded instance variables. When an object is small enough, it
* uses this area to store the instance variables.
*
* This is a length 1 array because:
* 1. GCC has a bug that does not optimize C flexible array members
* (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
* 2. Zero length arrays are not supported by all compilers
*/
VALUE ary[1];
#else
/**
* Embedded instance variables. When an object is small enough, it
* uses this area to store the instance variables.
*/
VALUE ary[ROBJECT_EMBED_LEN_MAX];
#endif
} as;
};
/* Offsets for YJIT */
#ifndef __cplusplus
static const int32_t ROBJECT_OFFSET_AS_HEAP_IVPTR = offsetof(struct RObject, as.heap.ivptr);
static const int32_t ROBJECT_OFFSET_AS_HEAP_IV_INDEX_TBL = offsetof(struct RObject, as.heap.iv_index_tbl);
static const int32_t ROBJECT_OFFSET_AS_ARY = offsetof(struct RObject, as.ary);
#endif
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Queries the instance variables.
*
* @param[in] obj Object in question.
* @return Its instance variables, in C array.
* @pre `obj` must be an instance of ::RObject.
*
* @internal
*
* @shyouhei finds no reason for this to be visible from extension libraries.
*/
static inline VALUE *
ROBJECT_IVPTR(VALUE obj)
{
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
struct RObject *const ptr = ROBJECT(obj);
if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) {
return ptr->as.ary;
}
else {
return ptr->as.heap.ivptr;
}
}
#endif /* RBIMPL_ROBJECT_H */

View File

@@ -0,0 +1,168 @@
#ifndef RBIMPL_RREGEXP_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RREGEXP_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Defines struct ::RRegexp.
*/
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/core/rstring.h"
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
/**
* Convenient casting macro.
*
* @param obj An object, which is in fact an ::RRegexp.
* @return The passed object casted to ::RRegexp.
*/
#define RREGEXP(obj) RBIMPL_CAST((struct RRegexp *)(obj))
/**
* Convenient accessor macro.
*
* @param obj An object, which is in fact an ::RRegexp.
* @return The passed object's pattern buffer.
*/
#define RREGEXP_PTR(obj) (RREGEXP(obj)->ptr)
/** @cond INTERNAL_MACRO */
#define RREGEXP_SRC RREGEXP_SRC
#define RREGEXP_SRC_PTR RREGEXP_SRC_PTR
#define RREGEXP_SRC_LEN RREGEXP_SRC_LEN
#define RREGEXP_SRC_END RREGEXP_SRC_END
/** @endcond */
struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */
/**
* Ruby's regular expression. A regexp is compiled into its own intermediate
* representation. This one holds that info. Regexp "match" operation then
* executes that IR.
*/
struct RRegexp {
/** Basic part, including flags and class. */
struct RBasic basic;
/**
* The pattern buffer. This is a quasi-opaque struct that holds compiled
* intermediate representation of the regular expression.
*
* @note Compilation of a regexp could be delayed until actual match.
*/
struct re_pattern_buffer *ptr;
/** Source code of this expression. */
const VALUE src;
/**
* Reference count. A regexp match can take extraordinarily long time to
* run. Ruby's regular expression is heavily extended and not a regular
* language any longer; runs in NP-time in practice. Now, Ruby also has
* threads and GVL. In order to prevent long GVL lockup, our regexp engine
* can release it on occasions. This means that multiple threads can touch
* a regular expressions at once. That itself is okay. But their cleanup
* phase shall wait for all the concurrent runs, to prevent use-after-free
* situation. This field is used to count such threads that are executing
* this particular pattern buffer.
*
* @warning Of course, touching this field from extension libraries causes
* catastrophic effects. Just leave it.
*/
unsigned long usecnt;
};
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Convenient getter function.
*
* @param[in] rexp The regular expression in question.
* @return The source code of the regular expression.
* @pre `rexp` must be of ::RRegexp.
*/
static inline VALUE
RREGEXP_SRC(VALUE rexp)
{
RBIMPL_ASSERT_TYPE(rexp, RUBY_T_REGEXP);
VALUE ret = RREGEXP(rexp)->src;
RBIMPL_ASSERT_TYPE(ret, RUBY_T_STRING);
return ret;
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Convenient getter function.
*
* @param[in] rexp The regular expression in question.
* @return The source code of the regular expression, in C's string.
* @pre `rexp` must be of ::RRegexp.
*
* @internal
*
* It seems nobody uses this function in the wild. Subject to hide?
*/
static inline char *
RREGEXP_SRC_PTR(VALUE rexp)
{
return RSTRING_PTR(RREGEXP_SRC(rexp));
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Convenient getter function.
*
* @param[in] rexp The regular expression in question.
* @return The length of the source code of the regular expression.
* @pre `rexp` must be of ::RRegexp.
*
* @internal
*
* It seems nobody uses this function in the wild. Subject to hide?
*/
static inline long
RREGEXP_SRC_LEN(VALUE rexp)
{
return RSTRING_LEN(RREGEXP_SRC(rexp));
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Convenient getter function.
*
* @param[in] rexp The regular expression in question.
* @return The end of the source code of the regular expression.
* @pre `rexp` must be of ::RRegexp.
*
* @internal
*
* It seems nobody uses this function in the wild. Subject to hide?
*/
static inline char *
RREGEXP_SRC_END(VALUE rexp)
{
return RSTRING_END(RREGEXP_SRC(rexp));
}
#endif /* RBIMPL_RREGEXP_H */

View File

@@ -0,0 +1,578 @@
#ifndef RBIMPL_RSTRING_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RSTRING_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Defines struct ::RString.
*/
#include "ruby/internal/config.h"
#include "ruby/internal/arithmetic/long.h"
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/fl_type.h"
#include "ruby/internal/value_type.h"
#include "ruby/internal/warning_push.h"
#include "ruby/assert.h"
/**
* Convenient casting macro.
*
* @param obj An object, which is in fact an ::RString.
* @return The passed object casted to ::RString.
*/
#define RSTRING(obj) RBIMPL_CAST((struct RString *)(obj))
/** @cond INTERNAL_MACRO */
#define RSTRING_NOEMBED RSTRING_NOEMBED
#if !USE_RVARGC
#define RSTRING_EMBED_LEN_MASK RSTRING_EMBED_LEN_MASK
#define RSTRING_EMBED_LEN_SHIFT RSTRING_EMBED_LEN_SHIFT
#define RSTRING_EMBED_LEN_MAX RSTRING_EMBED_LEN_MAX
#endif
#define RSTRING_FSTR RSTRING_FSTR
#define RSTRING_EMBED_LEN RSTRING_EMBED_LEN
#define RSTRING_LEN RSTRING_LEN
#define RSTRING_LENINT RSTRING_LENINT
#define RSTRING_PTR RSTRING_PTR
#define RSTRING_END RSTRING_END
/** @endcond */
/**
* @name Conversion of Ruby strings into C's
*
* @{
*/
/**
* Ensures that the parameter object is a String. This is done by calling its
* `to_str` method.
*
* @param[in,out] v Arbitrary Ruby object.
* @exception rb_eTypeError No implicit conversion defined.
* @post `v` is a String.
*/
#define StringValue(v) rb_string_value(&(v))
/**
* Identical to #StringValue, except it returns a `char*`.
*
* @param[in,out] v Arbitrary Ruby object.
* @exception rb_eTypeError No implicit conversion defined.
* @return Converted Ruby string's backend C string.
* @post `v` is a String.
*/
#define StringValuePtr(v) rb_string_value_ptr(&(v))
/**
* Identical to #StringValuePtr, except it additionally checks for the contents
* for viability as a C string. Ruby can accept wider range of contents as
* strings, compared to C. This function is to check that.
*
* @param[in,out] v Arbitrary Ruby object.
* @exception rb_eTypeError No implicit conversion defined.
* @exception rb_eArgError String is not C-compatible.
* @return Converted Ruby string's backend C string.
* @post `v` is a String.
*/
#define StringValueCStr(v) rb_string_value_cstr(&(v))
/**
* @private
*
* @deprecated This macro once was a thing in the old days, but makes no sense
* any longer today. Exists here for backwards compatibility
* only. You can safely forget about it.
*/
#define SafeStringValue(v) StringValue(v)
/**
* Identical to #StringValue, except it additionally converts the string's
* encoding to default external encoding. Ruby has a concept called encodings.
* A string can have different encoding than the environment expects. Someone
* has to make sure its contents be converted to something suitable. This is
* that routine. Call it when necessary.
*
* @param[in,out] v Arbitrary Ruby object.
* @exception rb_eTypeError No implicit conversion defined.
* @return Converted Ruby string's backend C string.
* @post `v` is a String.
*
* @internal
*
* Not sure but it seems this macro does not raise on encoding
* incompatibilities? Doesn't sound right to @shyouhei.
*/
#define ExportStringValue(v) do { \
StringValue(v); \
(v) = rb_str_export(v); \
} while (0)
/** @} */
/**
* @private
*
* Bits that you can set to ::RBasic::flags.
*
* @warning These enums are not the only bits we use for strings.
*
* @internal
*
* Actually all bits through FL_USER1 to FL_USER19 are used for strings. Why
* only this tiny part of them are made public here? @shyouhei can find no
* reason.
*/
enum ruby_rstring_flags {
/**
* This flag has something to do with memory footprint. If the string is
* short enough, ruby tries to be creative to abuse padding bits of struct
* ::RString for storing contents. If this flag is set that string does
* _not_ do that, to resort to good old fashioned external allocation
* strategy instead.
*
* @warning This bit has to be considered read-only. Setting/clearing
* this bit without corresponding fix up must cause immediate
* SEGV. Also, internal structures of a string change
* dynamically and transparently throughout of its lifetime.
* Don't assume it being persistent.
*
* @internal
*
* 3rd parties must not be aware that there even is more than one way to
* store a string. Might better be hidden.
*/
RSTRING_NOEMBED = RUBY_FL_USER1,
#if !USE_RVARGC
/**
* When a string employs embedded strategy (see ::RSTRING_NOEMBED), these
* bits are used to store the number of bytes actually filled into
* ::RString::ary.
*
* @internal
*
* 3rd parties must not be aware that there even is more than one way to
* store a string. Might better be hidden.
*/
RSTRING_EMBED_LEN_MASK = RUBY_FL_USER2 | RUBY_FL_USER3 | RUBY_FL_USER4 |
RUBY_FL_USER5 | RUBY_FL_USER6,
#endif
/* Actually, string encodings are also encoded into the flags, using
* remaining bits.*/
/**
* This flag has something to do with infamous "f"string. What is a
* fstring? Well it is a special subkind of strings that is immutable,
* deduped globally, and managed by our GC. It is much like a Symbol (in
* fact Symbols are dynamic these days and are backended using fstrings).
* This concept has been silently introduced at some point in 2.x era.
* Since then it gained wider acceptance in the core. But extension
* libraries could not know that until very recently. Strings of this flag
* live in a special Limbo deep inside of the interpreter. Never try to
* manipulate it by hand.
*
* @internal
*
* Fstrings are not the only variant strings that we implement today.
* Other things are behind-the-scene. This is the only one that is visible
* from extension library. There is no clear reason why it has to be.
* Given there are more "polite" ways to create fstrings, it seems this bit
* need not be exposed to extension libraries. Might better be hidden.
*/
RSTRING_FSTR = RUBY_FL_USER17
};
#if !USE_RVARGC
/**
* This is an enum because GDB wants it (rather than a macro). People need not
* bother.
*/
enum ruby_rstring_consts {
/** Where ::RSTRING_EMBED_LEN_MASK resides. */
RSTRING_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 2,
/** Max possible number of characters that can be embedded. */
RSTRING_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(char) - 1
};
#endif
/**
* Ruby's String. A string in ruby conceptually has these information:
*
* - Encoding of the string.
* - Length of the string.
* - Contents of the string.
*
* It is worth noting that a string is _not_ an array of characters in ruby.
* It has never been. In 1.x a string was an array of integers. Since 2.x a
* string is no longer an array of anything. A string is a string -- just like
* a Time is not an integer.
*/
struct RString {
/** Basic part, including flags and class. */
struct RBasic basic;
/** String's specific fields. */
union {
/**
* Strings that use separated memory region for contents use this
* pattern.
*/
struct {
/**
* Length of the string, not including terminating NUL character.
*
* @note This is in bytes.
*/
long len;
/**
* Pointer to the contents of the string. In the old days each
* string had dedicated memory regions. That is no longer true
* today, but there still are strings of such properties. This
* field could be used to point such things.
*/
char *ptr;
/** Auxiliary info. */
union {
/**
* Capacity of `*ptr`. A continuous memory region of at least
* `capa` bytes is expected to exist at `*ptr`. This can be
* bigger than `len`.
*/
long capa;
/**
* Parent of the string. Nowadays strings can share their
* contents each other, constructing gigantic nest of objects.
* This situation is called "shared", and this is the field to
* control such properties.
*/
VALUE shared;
} aux;
} heap;
/** Embedded contents. */
struct {
#if USE_RVARGC
long len;
/* This is a length 1 array because:
* 1. GCC has a bug that does not optimize C flexible array members
* (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
* 2. Zero length arrays are not supported by all compilers
*/
char ary[1];
#else
/**
* When a string is short enough, it uses this area to store the
* contents themselves. This was impractical in the 20th century,
* but these days 64 bit machines can typically hold 24 bytes here.
* Could be sufficiently large. In this case the length is encoded
* into the flags.
*/
char ary[RSTRING_EMBED_LEN_MAX + 1];
#endif
} embed;
} as;
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
* Identical to rb_check_string_type(), except it raises exceptions in case of
* conversion failures.
*
* @param[in] obj Target object.
* @exception rb_eTypeError No implicit conversion to String.
* @return Return value of `obj.to_str`.
* @see rb_io_get_io
* @see rb_ary_to_ary
*/
VALUE rb_str_to_str(VALUE obj);
/**
* Identical to rb_str_to_str(), except it fills the passed pointer with the
* converted object.
*
* @param[in,out] ptr Pointer to a variable of target object.
* @exception rb_eTypeError No implicit conversion to String.
* @return Return value of `obj.to_str`.
* @post `*ptr` is the return value.
*/
VALUE rb_string_value(volatile VALUE *ptr);
/**
* Identical to rb_str_to_str(), except it returns the converted string's
* backend memory region.
*
* @param[in,out] ptr Pointer to a variable of target object.
* @exception rb_eTypeError No implicit conversion to String.
* @post `*ptr` is the return value of `obj.to_str`.
* @return Pointer to the contents of the return value.
*/
char *rb_string_value_ptr(volatile VALUE *ptr);
/**
* Identical to rb_string_value_ptr(), except it additionally checks for the
* contents for viability as a C string. Ruby can accept wider range of
* contents as strings, compared to C. This function is to check that.
*
* @param[in,out] ptr Pointer to a variable of target object.
* @exception rb_eTypeError No implicit conversion to String.
* @exception rb_eArgError String is not C-compatible.
* @post `*ptr` is the return value of `obj.to_str`.
* @return Pointer to the contents of the return value.
*/
char *rb_string_value_cstr(volatile VALUE *ptr);
/**
* Identical to rb_str_to_str(), except it additionally converts the string
* into default external encoding. Ruby has a concept called encodings. A
* string can have different encoding than the environment expects. Someone
* has to make sure its contents be converted to something suitable. This is
* that routine. Call it when necessary.
*
* @param[in] obj Target object.
* @exception rb_eTypeError No implicit conversion to String.
* @return Converted ruby string of default external encoding.
*/
VALUE rb_str_export(VALUE obj);
/**
* Identical to rb_str_export(), except it converts into the locale encoding
* instead.
*
* @param[in] obj Target object.
* @exception rb_eTypeError No implicit conversion to String.
* @return Converted ruby string of locale encoding.
*/
VALUE rb_str_export_locale(VALUE obj);
RBIMPL_ATTR_ERROR(("rb_check_safe_str() and Check_SafeStr() are obsolete; use StringValue() instead"))
/**
* @private
*
* @deprecated This function once was a thing in the old days, but makes no
* sense any longer today. Exists here for backwards
* compatibility only. You can safely forget about it.
*/
void rb_check_safe_str(VALUE);
/**
* @private
*
* @deprecated This macro once was a thing in the old days, but makes no sense
* any longer today. Exists here for backwards compatibility
* only. You can safely forget about it.
*/
#define Check_SafeStr(v) rb_check_safe_str(RBIMPL_CAST((VALUE)(v)))
/**
* @private
*
* Prints diagnostic message to stderr when RSTRING_PTR or RSTRING_END
* is NULL.
*
* @param[in] func The function name where encountered NULL pointer.
*/
void rb_debug_rstring_null_ptr(const char *func);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Queries the length of the string.
*
* @param[in] str String in question.
* @return Its length, in bytes.
* @pre `str` must be an instance of ::RString, and must has its
* ::RSTRING_NOEMBED flag off.
*
* @internal
*
* This was a macro before. It was inevitable to be public, since macros are
* global constructs. But should it be forever? Now that it is a function,
* @shyouhei thinks it could just be eliminated, hidden into implementation
* details.
*/
static inline long
RSTRING_EMBED_LEN(VALUE str)
{
RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING);
RBIMPL_ASSERT_OR_ASSUME(! RB_FL_ANY_RAW(str, RSTRING_NOEMBED));
#if USE_RVARGC
long f = RSTRING(str)->as.embed.len;
return f;
#else
VALUE f = RBASIC(str)->flags;
f &= RSTRING_EMBED_LEN_MASK;
f >>= RSTRING_EMBED_LEN_SHIFT;
return RBIMPL_CAST((long)f);
#endif
}
RBIMPL_WARNING_PUSH()
#if RBIMPL_COMPILER_IS(Intel)
RBIMPL_WARNING_IGNORED(413)
#endif
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* @private
*
* "Expands" an embedded string into an ordinal one. This is a function that
* returns aggregated type. The returned struct always has its `as.heap.len`
* an `as.heap.ptr` fields set appropriately.
*
* This is an implementation detail that 3rd parties should never bother.
*/
static inline struct RString
rbimpl_rstring_getmem(VALUE str)
{
RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING);
if (RB_FL_ANY_RAW(str, RSTRING_NOEMBED)) {
return *RSTRING(str);
}
else {
/* Expecting compilers to optimize this on-stack struct away. */
struct RString retval;
retval.as.heap.len = RSTRING_EMBED_LEN(str);
retval.as.heap.ptr = RSTRING(str)->as.embed.ary;
return retval;
}
}
RBIMPL_WARNING_POP()
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Queries the length of the string.
*
* @param[in] str String in question.
* @return Its length, in bytes.
* @pre `str` must be an instance of ::RString.
*/
static inline long
RSTRING_LEN(VALUE str)
{
return rbimpl_rstring_getmem(str).as.heap.len;
}
RBIMPL_ATTR_ARTIFICIAL()
/**
* Queries the contents pointer of the string.
*
* @param[in] str String in question.
* @return Pointer to its contents.
* @pre `str` must be an instance of ::RString.
*/
static inline char *
RSTRING_PTR(VALUE str)
{
char *ptr = rbimpl_rstring_getmem(str).as.heap.ptr;
if (RB_UNLIKELY(! ptr)) {
/* :BEWARE: @shyouhei thinks that currently, there are rooms for this
* function to return NULL. In the 20th century that was a pointless
* concern. However struct RString can hold fake strings nowadays. It
* seems no check against NULL are exercised around handling of them
* (one of such usages is located in marshal.c, which scares
* @shyouhei). Better check here for maximum safety.
*
* Also, this is not rb_warn() because RSTRING_PTR() can be called
* during GC (see what obj_info() does). rb_warn() needs to allocate
* Ruby objects. That is not possible at this moment. */
rb_debug_rstring_null_ptr("RSTRING_PTR");
}
return ptr;
}
RBIMPL_ATTR_ARTIFICIAL()
/**
* Queries the end of the contents pointer of the string.
*
* @param[in] str String in question.
* @return Pointer to its end of contents.
* @pre `str` must be an instance of ::RString.
*/
static inline char *
RSTRING_END(VALUE str)
{
struct RString buf = rbimpl_rstring_getmem(str);
if (RB_UNLIKELY(! buf.as.heap.ptr)) {
/* Ditto. */
rb_debug_rstring_null_ptr("RSTRING_END");
}
return &buf.as.heap.ptr[buf.as.heap.len];
}
RBIMPL_ATTR_ARTIFICIAL()
/**
* Identical to RSTRING_LEN(), except it differs for the return type.
*
* @param[in] str String in question.
* @exception rb_eRangeError Too long.
* @return Its length, in bytes.
* @pre `str` must be an instance of ::RString.
*
* @internal
*
* This API seems redundant but has actual usages.
*/
static inline int
RSTRING_LENINT(VALUE str)
{
return rb_long2int(RSTRING_LEN(str));
}
/**
* Convenient macro to obtain the contents and length at once.
*
* @param str String in question.
* @param ptrvar Variable where its contents is stored.
* @param lenvar Variable where its length is stored.
*/
#ifdef HAVE_STMT_AND_DECL_IN_EXPR
# define RSTRING_GETMEM(str, ptrvar, lenvar) \
__extension__ ({ \
struct RString rbimpl_str = rbimpl_rstring_getmem(str); \
(ptrvar) = rbimpl_str.as.heap.ptr; \
(lenvar) = rbimpl_str.as.heap.len; \
})
#else
# define RSTRING_GETMEM(str, ptrvar, lenvar) \
((ptrvar) = RSTRING_PTR(str), \
(lenvar) = RSTRING_LEN(str))
#endif /* HAVE_STMT_AND_DECL_IN_EXPR */
#endif /* RBIMPL_RSTRING_H */

View File

@@ -0,0 +1,121 @@
#ifndef RBIMPL_RSTRUCT_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RSTRUCT_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Routines to manipulate struct RStruct.
* @note The struct RStruct itself is opaque.
*/
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/internal/value_type.h"
#include "ruby/internal/arithmetic/long.h"
#include "ruby/internal/arithmetic/int.h"
#if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY
# include "ruby/backward.h"
#endif
/**
* @private
*
* @deprecated This macro once was a thing in the old days, but makes no sense
* any longer today. Exists here for backwards compatibility
* only. You can safely forget about it.
*
* @internal
*
* Declaration of rb_struct_ptr() is at include/ruby/backward.h.
*/
#define RSTRUCT_PTR(st) rb_struct_ptr(st)
/** @cond INTERNAL_MACRO */
#define RSTRUCT_LEN RSTRUCT_LEN
#define RSTRUCT_SET RSTRUCT_SET
#define RSTRUCT_GET RSTRUCT_GET
/** @endcond */
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
* Returns the number of struct members.
*
* @param[in] st An instance of RStruct.
* @return The number of members of `st`.
* @pre `st` must be of ::RUBY_T_STRUCT.
*/
VALUE rb_struct_size(VALUE st);
/**
* Resembles `Struct#[]`.
*
* @param[in] st An instance of RStruct.
* @param[in] k Index a.k.a. key of the struct.
* @exception rb_eTypeError `k` is neither Numeric, Symbol, nor String.
* @exception rb_eIndexError Numerical index out of range.
* @exception rb_eNameError No such key.
* @return The member stored at `k` in `st`.
* @pre `st` must be of ::RUBY_T_STRUCT.
*/
VALUE rb_struct_aref(VALUE st, VALUE k);
/**
* Resembles `Struct#[]=`.
*
* @param[out] st An instance of RStruct.
* @param[in] k Index a.k.a. key of the struct.
* @param[in] v Value to store.
* @exception rb_eTypeError `k` is neither Numeric, Symbol, nor String.
* @exception rb_eIndexError Numerical index out of range.
* @exception rb_eNameError No such key.
* @return Passed `v`.
* @pre `st` must be of ::RUBY_T_STRUCT.
* @post `v` is stored at `k` in `st`.
*/
VALUE rb_struct_aset(VALUE st, VALUE k, VALUE v);
RBIMPL_SYMBOL_EXPORT_END()
RBIMPL_ATTR_ARTIFICIAL()
/** @copydoc rb_struct_size() */
static inline long
RSTRUCT_LEN(VALUE st)
{
RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT);
return RB_NUM2LONG(rb_struct_size(st));
}
RBIMPL_ATTR_ARTIFICIAL()
/** @copydoc rb_struct_aset() */
static inline VALUE
RSTRUCT_SET(VALUE st, int k, VALUE v)
{
RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT);
return rb_struct_aset(st, INT2NUM(k), (v));
}
RBIMPL_ATTR_ARTIFICIAL()
/** @copydoc rb_struct_aref() */
static inline VALUE
RSTRUCT_GET(VALUE st, int k)
{
RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT);
return rb_struct_aref(st, INT2NUM(k));
}
#endif /* RBIMPL_RSTRUCT_H */

View File

@@ -0,0 +1,604 @@
#ifndef RBIMPL_RTYPEDDATA_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_RTYPEDDATA_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
* extension libraries. They could be written in C++98.
* @brief Defines struct ::RTypedData.
*/
#include "ruby/internal/config.h"
#ifdef STDC_HEADERS
# include <stddef.h>
#endif
#include "ruby/internal/assume.h"
#include "ruby/internal/attr/artificial.h"
#include "ruby/internal/attr/flag_enum.h"
#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/cast.h"
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/core/rdata.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/error.h"
#include "ruby/internal/fl_type.h"
#include "ruby/internal/stdbool.h"
#include "ruby/internal/value_type.h"
/**
* @private
*
* @deprecated This macro once was a thing in the old days, but makes no sense
* any longer today. Exists here for backwards compatibility
* only. You can safely forget about it.
*/
#define HAVE_TYPE_RB_DATA_TYPE_T 1
/**
* @private
*
* @deprecated This macro once was a thing in the old days, but makes no sense
* any longer today. Exists here for backwards compatibility
* only. You can safely forget about it.
*/
#define HAVE_RB_DATA_TYPE_T_FUNCTION 1
/**
* @private
*
* @deprecated This macro once was a thing in the old days, but makes no sense
* any longer today. Exists here for backwards compatibility
* only. You can safely forget about it.
*/
#define HAVE_RB_DATA_TYPE_T_PARENT 1
/**
* This is a value you can set to ::rb_data_type_struct::dfree. Setting this
* means the data was allocated using ::ruby_xmalloc() (or variants), and shall
* be freed using ::ruby_xfree().
*
* @warning Do not use this if you want to use system malloc, because the
* system and Ruby might or might not share the same malloc
* implementation.
*/
#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
/**
* This is a value you can set to ::rb_data_type_struct::dfree. Setting this
* means the data is managed by someone else, like, statically allocated. Of
* course you are on your own then.
*/
#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE
/**
* Convenient casting macro.
*
* @param obj An object, which is in fact an ::RTypedData.
* @return The passed object casted to ::RTypedData.
*/
#define RTYPEDDATA(obj) RBIMPL_CAST((struct RTypedData *)(obj))
/**
* Convenient getter macro.
*
* @param v An object, which is in fact an ::RTypedData.
* @return The passed object's ::RTypedData::data field.
*/
#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data)
/** @old{rb_check_typeddata} */
#define Check_TypedStruct(v, t) \
rb_check_typeddata(RBIMPL_CAST((VALUE)(v)), (t))
/** @cond INTERNAL_MACRO */
#define RTYPEDDATA_P RTYPEDDATA_P
#define RTYPEDDATA_TYPE RTYPEDDATA_TYPE
#define RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE
#define RUBY_TYPED_WB_PROTECTED RUBY_TYPED_WB_PROTECTED
#define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1
/** @endcond */
/**
* @private
*
* Bits for rb_data_type_struct::flags.
*/
enum
RBIMPL_ATTR_FLAG_ENUM()
rbimpl_typeddata_flags {
/**
* This flag has something to do with Ruby's global interpreter lock. For
* maximum safety, Ruby locks the entire VM during GC. However your
* callback functions could unintentionally unlock it, for instance when
* they try to flush an IO buffer. Such operations are dangerous (threads
* then run alongside of GC). By default, to prevent those scenario,
* callbacks are deferred until the GC engine is 100% sure threads can run.
* This flag skips that; structs with it are deallocated during the sweep
* phase.
*
* Using this flag needs deep understanding of both GC and threads. You
* would better leave it unspecified.
*/
RUBY_TYPED_FREE_IMMEDIATELY = 1,
/**
* This flag has something to do with Ractor. Multiple Ractors run without
* protecting each other. Sharing an object among Ractors is basically
* dangerous, disabled by default. This flag is used to bypass that
* restriction. but setting it is not enough. In addition to do so, an
* object also has to be frozen, and be passed to
* rb_ractor_make_shareable() before being actually shareable. Of course,
* you have to manually prevent race conditions then.
*
* Using this flag needs deep understanding of multithreaded programming.
* You would better leave it unspecified.
*/
RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE,
/**
* This flag has something to do with our garbage collector. These days
* ruby objects are "generational". There are those who are young and
* those who are old. Young objects are prone to die; monitored relatively
* extensively by the garbage collector. OTOH old objects tend to live
* longer. They are relatively rarely considered. This basically works.
* But there is one tweak that has to be exercised. When an elder object
* has reference(s) to younger one(s), that referenced objects must not
* die. In order to detect additions of such references, old generations
* are protected by write barriers. It is a very difficult hack to
* appropriately insert write barriers everywhere. This mechanism is
* disabled by default for 3rd party extensions (they never get aged). By
* specifying this flag you can enable the generational feature to your
* data structure. Of course, you have to manually insert write barriers
* then.
*
* Using this flag needs deep understanding of GC internals, often at the
* level of source code. You would better leave it unspecified.
*/
RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */
/**
* This flag is mysterious. It seems nobody is currently using it. The
* intention of this flag is also unclear. We need further investigations.
*/
RUBY_TYPED_PROMOTED1 = RUBY_FL_PROMOTED1 /* THIS FLAG DEPENDS ON Ruby version */
};
/**
* This is the struct that holds necessary info for a struct. It roughly
* resembles a Ruby level class; multiple objects can share a ::rb_data_type_t
* instance.
*/
typedef struct rb_data_type_struct rb_data_type_t;
/** @copydoc rb_data_type_t */
struct rb_data_type_struct {
/**
* Name of structs of this kind. This is used for diagnostic purposes.
* This has to be unique in the process, but doesn't has to be a valid
* C/Ruby identifier.
*/
const char *wrap_struct_name;
/** Function pointers. Resembles C++ `vtbl`.*/
struct {
/**
* This function is called when the object is experiencing GC marks.
* If it contains references to other Ruby objects, you need to mark
* them also. Otherwise GC will smash your data.
*
* @see rb_gc_mark()
* @warning This is called during GC runs. Object allocations are
* impossible at that moment (that is why GC runs).
*/
RUBY_DATA_FUNC dmark;
/**
* This function is called when the object is no longer used. You need
* to do whatever necessary to avoid memory leaks.
*
* @warning This is called during GC runs. Object allocations are
* impossible at that moment (that is why GC runs).
*/
RUBY_DATA_FUNC dfree;
/**
* This function is to query the size of the underlying memory regions.
*
* @internal
*
* This function has only one usage, which is form inside of
* `ext/objspace`.
*/
size_t (*dsize)(const void *);
/**
* This function is called when the object is relocated. Like
* ::rb_data_type_struct::dmark, you need to update references to Ruby
* objects inside of your structs.
*
* @see rb_gc_location()
* @warning This is called during GC runs. Object allocations are
* impossible at that moment (that is why GC runs).
*/
RUBY_DATA_FUNC dcompact;
/**
* This field is reserved for future extension. For now, it must be
* filled with zeros.
*/
void *reserved[1]; /* For future extension.
This array *must* be filled with ZERO. */
} function;
/**
* Parent of this class. Sometimes C structs have inheritance-like
* relationships. An example is `struct sockaddr` and its family. If you
* design such things, make ::rb_data_type_t for each of them and connect
* using this field. Ruby can then transparently cast your data back and
* forth when you call #TypedData_Get_Struct().
*
* ```CXX
* struct parent { };
* static inline const rb_data_type_t parent_type = {
* .wrap_struct_name = "parent",
* };
*
* struct child: public parent { };
* static inline const rb_data_type_t child_type = {
* .wrap_struct_name = "child",
* .parent = &parent_type,
* };
*
* // This function can take both parent_class and child_class.
* static inline struct parent *
* get_parent(VALUE v)
* {
* struct parent *p;
* TypedData_Get_Struct(v, parent_type, struct parent, p);
* return p;
* }
* ```
*/
const rb_data_type_t *parent;
/**
* Type-specific static data. This area can be used for any purpose by a
* programmer who define the type. Ruby does not manage this at all.
*/
void *data; /* This area can be used for any purpose
by a programmer who define the type. */
/**
* Type-specific behavioural characteristics. This is a bitfield. It is
* an EXTREMELY WISE IDEA to leave this field blank. It is designed so
* that setting zero is the safest thing to do. If you risk to set any
* bits on, you have to know exactly what you are doing.
*
* @internal
*
* Why it has to be a ::VALUE? @shyouhei doesn't understand the design.
*/
VALUE flags; /* RUBY_FL_WB_PROTECTED */
};
/**
* "Typed" user data. By using this, extension libraries can wrap a C struct
* to make it visible from Ruby. For instance if you have a `struct timeval`,
* and you want users to use it,
*
* ```CXX
* static inline const rb_data_type_t timeval_type = {
* // Note that unspecified fields are 0-filled by default.
* .wrap_struct_name = "timeval",
* .function = {
* .dmark = nullptr, // no need to mark
* .dfree = RUBY_TYPED_DEFAULT_FREE, // use ruby_xfree()
* .dsize = [](auto) {
* return sizeof(struct timeval);
* },
* },
* };
*
* extern "C" void
* Init_timeval(void)
* {
* auto klass = rb_define_class("YourName", rb_cObject);
*
* rb_define_alloc_func(klass, [](auto klass) {
* struct timeval *t;
* auto ret = TypedData_Make_Struct(
* klass, struct timeval, &timeval_type, t);
*
* if (auto i = gettimeofday(t, nullptr); i == -1) {
* rb_sys_fail("gettimeofday(3)");
* }
* else {
* return ret;
* }
* });
* }
* ```
*/
struct RTypedData {
/** The part that all ruby objects have in common. */
struct RBasic basic;
/**
* This field stores various information about how Ruby should handle a
* data. This roughly resembles a Ruby level class (apart from method
* definition etc.)
*/
const rb_data_type_t *type;
/**
* This has to be always 1.
*
* @internal
*
* Why, then, this is not a const ::VALUE?
*/
VALUE typed_flag;
/** Pointer to the actual C level struct that you want to wrap. */
void *data;
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
RBIMPL_ATTR_NONNULL((3))
/**
* This is the primitive way to wrap an existing C struct into ::RTypedData.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] datap Pointer to the target C struct.
* @param[in] type The characteristics of the passed data.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return An allocated object that wraps `datap`.
*/
VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type);
/**
* Identical to rb_data_typed_object_wrap(), except it allocates a new data
* region internally instead of taking an existing one. The allocation is done
* using ruby_calloc(). Hence it makes no sense for `type->function.dfree` to
* be anything other than ::RUBY_TYPED_DEFAULT_FREE.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] size Requested size of memory to allocate.
* @param[in] type The characteristics of the passed data.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return An allocated object that wraps a new `size` byte region.
*/
VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type);
/**
* Checks for the domestic relationship between the two.
*
* @param[in] child A data type supposed to be a child of `parent`.
* @param[in] parent A data type supposed to be a parent of `child`.
* @retval true `child` is a descendent of `parent`.
* @retval false Otherwise.
*
* @internal
*
* You can path NULL to both arguments, don't know what that means though.
*/
int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent);
/**
* Checks if the given object is of given kind.
*
* @param[in] obj An instance of ::RTypedData.
* @param[in] data_type Expected data type of `obj`.
* @retval true `obj` is of `data_type`.
* @retval false Otherwise.
*/
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type);
/**
* Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead
* of returning false.
*
* @param[in] obj An instance of ::RTypedData.
* @param[in] data_type Expected data type of `obj`.
* @exception rb_eTypeError obj is not of `data_type`.
* @return Unwrapped C struct that `obj` holds.
* @post Upon successful return `obj`'s type is guaranteed `data_type`.
*/
void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type);
RBIMPL_SYMBOL_EXPORT_END()
/**
* Converts sval, a pointer to your struct, into a Ruby object.
*
* @param klass A ruby level class.
* @param data_type The type of `sval`.
* @param sval A pointer to your struct.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return A created Ruby object.
*/
#define TypedData_Wrap_Struct(klass,data_type,sval)\
rb_data_typed_object_wrap((klass),(sval),(data_type))
/**
* @private
*
* This is an implementation detail of #TypedData_Make_Struct. People don't
* use it directly.
*
* @param result Variable name of created Ruby object.
* @param klass Ruby level class of the object.
* @param type Type name of the C struct.
* @param size Size of the C struct.
* @param data_type The data type describing `type`.
* @param sval Variable name of created C struct.
*/
#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \
VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \
(sval) = RBIMPL_CAST((type *)RTYPEDDATA_DATA(result)); \
RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
/**
* Identical to #TypedData_Wrap_Struct, except it allocates a new data region
* internally instead of taking an existing one. The allocation is done using
* ruby_calloc(). Hence it makes no sense for `data_type->function.dfree` to
* be anything other than ::RUBY_TYPED_DEFAULT_FREE.
*
* @param klass Ruby level class of the object.
* @param type Type name of the C struct.
* @param data_type The data type describing `type`.
* @param sval Variable name of created C struct.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return A created Ruby object.
*/
#ifdef HAVE_STMT_AND_DECL_IN_EXPR
#define TypedData_Make_Struct(klass, type, data_type, sval) \
RB_GNUC_EXTENSION({ \
TypedData_Make_Struct0( \
data_struct_obj, \
klass, \
type, \
sizeof(type), \
data_type, \
sval); \
data_struct_obj; \
})
#else
#define TypedData_Make_Struct(klass, type, data_type, sval) \
rb_data_typed_object_make( \
(klass), \
(data_type), \
RBIMPL_CAST((void **)&(sval)), \
sizeof(type))
#endif
/**
* Obtains a C struct from inside of a wrapper Ruby object.
*
* @param obj An instance of ::RTypedData.
* @param type Type name of the C struct.
* @param data_type The data type describing `type`.
* @param sval Variable name of obtained C struct.
* @exception rb_eTypeError `obj` is not a kind of `data_type`.
* @return Unwrapped C struct that `obj` holds.
*/
#define TypedData_Get_Struct(obj,type,data_type,sval) \
((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type))))
RBIMPL_ATTR_PURE()
RBIMPL_ATTR_ARTIFICIAL()
/**
* @private
*
* This is an implementation detail of Check_Type(). People don't use it
* directly.
*
* @param[in] obj Object in question
* @retval true `obj` is an instance of ::RTypedData.
* @retval false `obj` is an instance of ::RData.
* @pre `obj` must be a Ruby object of ::RUBY_T_DATA.
*/
static inline bool
rbimpl_rtypeddata_p(VALUE obj)
{
return RTYPEDDATA(obj)->typed_flag == 1;
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/**
* Checks whether the passed object is ::RTypedData or ::RData.
*
* @param[in] obj Object in question
* @retval true `obj` is an instance of ::RTypedData.
* @retval false `obj` is an instance of ::RData.
* @pre `obj` must be a Ruby object of ::RUBY_T_DATA.
*/
static inline bool
RTYPEDDATA_P(VALUE obj)
{
#if RUBY_DEBUG
if (RB_UNLIKELY(! RB_TYPE_P(obj, RUBY_T_DATA))) {
Check_Type(obj, RUBY_T_DATA);
RBIMPL_UNREACHABLE_RETURN(false);
}
#endif
return rbimpl_rtypeddata_p(obj);
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
/**
* Queries for the type of given object.
*
* @param[in] obj Object in question
* @return Data type struct that corresponds to `obj`.
* @pre `obj` must be an instance of ::RTypedData.
*/
static inline const struct rb_data_type_struct *
RTYPEDDATA_TYPE(VALUE obj)
{
#if RUBY_DEBUG
if (RB_UNLIKELY(! RTYPEDDATA_P(obj))) {
rb_unexpected_type(obj, RUBY_T_DATA);
RBIMPL_UNREACHABLE_RETURN(NULL);
}
#endif
return RTYPEDDATA(obj)->type;
}
/**
* While we don't stop you from using this function, it seems to be an
* implementation detail of #TypedData_Make_Struct, which is preferred over
* this one.
*
* @param[in] klass Ruby level class of the returning object.
* @param[in] type The data type
* @param[out] datap Return pointer.
* @param[in] size Size of the C struct.
* @exception rb_eTypeError `klass` is not a class.
* @exception rb_eNoMemError Out of memory.
* @return A created Ruby object.
* @post `*datap` points to the C struct wrapped by the returned object.
*/
static inline VALUE
rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size)
{
TypedData_Make_Struct0(result, klass, void, size, type, *datap);
return result;
}
RBIMPL_ATTR_DEPRECATED(("by: rb_data_typed_object_wrap"))
/** @deprecated This function was renamed to rb_data_typed_object_wrap(). */
static inline VALUE
rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type)
{
return rb_data_typed_object_wrap(klass, datap, type);
}
#endif /* RBIMPL_RTYPEDDATA_H */