mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
6c4a8c09db
Define the `mrb_bigint_p()` macro function, which returns false if `MRB_USE_BIGINT` is undefined.
476 lines
12 KiB
C
476 lines
12 KiB
C
/**
|
|
** @file mruby/value.h - mruby value definitions
|
|
**
|
|
** See Copyright Notice in mruby.h
|
|
*/
|
|
|
|
#ifndef MRUBY_VALUE_H
|
|
#define MRUBY_VALUE_H
|
|
|
|
#include "common.h"
|
|
|
|
/*
|
|
* mruby Value definition functions and macros.
|
|
*/
|
|
MRB_BEGIN_DECL
|
|
|
|
/**
|
|
* mruby Symbol.
|
|
* @class mrb_sym
|
|
*
|
|
* You can create an mrb_sym by simply using mrb_str_intern() or mrb_intern_cstr()
|
|
*/
|
|
typedef uint32_t mrb_sym;
|
|
|
|
/**
|
|
* mruby Boolean.
|
|
* @class mrb_bool
|
|
*
|
|
*
|
|
* Used internally to represent boolean. Can be TRUE or FALSE.
|
|
* Not to be confused with Ruby's boolean classes, which can be
|
|
* obtained using mrb_false_value() and mrb_true_value()
|
|
*/
|
|
#if defined(__cplusplus) || (defined(__bool_true_false_are_defined) && __bool_true_false_are_defined)
|
|
typedef bool mrb_bool;
|
|
|
|
# ifndef FALSE
|
|
# define FALSE false
|
|
# endif
|
|
# ifndef TRUE
|
|
# define TRUE true
|
|
# endif
|
|
#else
|
|
# if __STDC_VERSION__ >= 199901L
|
|
typedef _Bool mrb_bool;
|
|
# else
|
|
typedef uint8_t mrb_bool;
|
|
# endif
|
|
|
|
# ifndef FALSE
|
|
# define FALSE 0
|
|
# endif
|
|
# ifndef TRUE
|
|
# define TRUE 1
|
|
# endif
|
|
#endif
|
|
|
|
struct mrb_state;
|
|
|
|
#if defined _MSC_VER && _MSC_VER < 1800
|
|
# define PRIo64 "llo"
|
|
# define PRId64 "lld"
|
|
# define PRIu64 "llu"
|
|
# define PRIx64 "llx"
|
|
# define PRIo16 "ho"
|
|
# define PRId16 "hd"
|
|
# define PRIu16 "hu"
|
|
# define PRIx16 "hx"
|
|
# define PRIo32 "o"
|
|
# define PRId32 "d"
|
|
# define PRIu32 "u"
|
|
# define PRIx32 "x"
|
|
#else
|
|
# include <inttypes.h>
|
|
#endif
|
|
|
|
#if defined(MRB_INT64)
|
|
typedef int64_t mrb_int;
|
|
typedef uint64_t mrb_uint;
|
|
# define MRB_INT_BIT 64
|
|
# define MRB_INT_MIN INT64_MIN
|
|
# define MRB_INT_MAX INT64_MAX
|
|
# define MRB_PRIo PRIo64
|
|
# define MRB_PRId PRId64
|
|
# define MRB_PRIx PRIx64
|
|
#else
|
|
typedef int32_t mrb_int;
|
|
typedef uint32_t mrb_uint;
|
|
# define MRB_INT_BIT 32
|
|
# define MRB_INT_MIN INT32_MIN
|
|
# define MRB_INT_MAX INT32_MAX
|
|
# define MRB_PRIo PRIo32
|
|
# define MRB_PRId PRId32
|
|
# define MRB_PRIx PRIx32
|
|
#endif
|
|
|
|
#define MRB_FLAGS_MASK(shift, width) (~(~0U << (width)) << (shift))
|
|
#define MRB_FLAGS_GET(b, s, w) (((b) >> (s)) & MRB_FLAGS_MASK(0, w))
|
|
#define MRB_FLAGS_SET(b, s, w, n) ((b) = MRB_FLAGS_ZERO(b, s, w) | MRB_FLAGS_MAKE(s, w, n))
|
|
#define MRB_FLAGS_ZERO(b, s, w) ((b) & ~MRB_FLAGS_MASK(s, w))
|
|
#define MRB_FLAGS_MAKE(s, w, n) (((n) & MRB_FLAGS_MASK(0, w)) << (s))
|
|
#define MRB_FLAG_ON(b, s) ((b) |= MRB_FLAGS_MASK(s, 1))
|
|
#define MRB_FLAG_OFF(b, s) ((b) &= ~MRB_FLAGS_MASK(s, 1))
|
|
#define MRB_FLAG_CHECK(b, s) (!!((b) & MRB_FLAGS_MASK(s, 1)))
|
|
|
|
MRB_API mrb_bool mrb_read_int(const char *p, const char *e, char **endp, mrb_int *np);
|
|
/* obsolete; do not use mrb_int_read() */
|
|
MRB_API mrb_int mrb_int_read(const char*, const char*, char**);
|
|
#ifndef MRB_NO_FLOAT
|
|
MRB_API mrb_bool mrb_read_float(const char *p, char **endp, double *fp);
|
|
/* obsolete; do not use mrb_float_read() */
|
|
MRB_API double mrb_float_read(const char *p, char **endp);
|
|
#ifdef MRB_USE_FLOAT32
|
|
typedef float mrb_float;
|
|
#else
|
|
typedef double mrb_float;
|
|
#endif
|
|
#endif
|
|
|
|
#if defined _MSC_VER && _MSC_VER < 1900
|
|
MRB_API int mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg);
|
|
MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...);
|
|
# define vsnprintf(s, n, format, arg) mrb_msvc_vsnprintf(s, n, format, arg)
|
|
# define snprintf(s, n, format, ...) mrb_msvc_snprintf(s, n, format, __VA_ARGS__)
|
|
# if _MSC_VER < 1800 && !defined MRB_NO_FLOAT
|
|
# define isfinite(n) _finite(n)
|
|
# define isnan _isnan
|
|
# define isinf(n) (!_finite(n) && !_isnan(n))
|
|
# define signbit(n) (_copysign(1.0, (n)) < 0.0)
|
|
static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
|
|
# define INFINITY (*(float*)&IEEE754_INFINITY_BITS_SINGLE)
|
|
# define NAN ((float)(INFINITY - INFINITY))
|
|
# endif
|
|
#endif
|
|
|
|
#define MRB_VTYPE_FOREACH(f) \
|
|
/* mrb_vtype */ /* C type */ /* Ruby class */ \
|
|
f(MRB_TT_FALSE, void, "false") \
|
|
f(MRB_TT_TRUE, void, "true") \
|
|
f(MRB_TT_SYMBOL, void, "Symbol") \
|
|
f(MRB_TT_UNDEF, void, "undefined") \
|
|
f(MRB_TT_FREE, void, "free") \
|
|
f(MRB_TT_FLOAT, struct RFloat, "Float") \
|
|
f(MRB_TT_INTEGER, struct RInteger, "Integer") \
|
|
f(MRB_TT_CPTR, struct RCptr, "cptr") \
|
|
f(MRB_TT_OBJECT, struct RObject, "Object") \
|
|
f(MRB_TT_CLASS, struct RClass, "Class") \
|
|
f(MRB_TT_MODULE, struct RClass, "Module") \
|
|
f(MRB_TT_SCLASS, struct RClass, "SClass") \
|
|
f(MRB_TT_HASH, struct RHash, "Hash") \
|
|
f(MRB_TT_CDATA, struct RData, "C data") \
|
|
f(MRB_TT_EXCEPTION, struct RException, "Exception") \
|
|
f(MRB_TT_ICLASS, struct RClass, "iClass") \
|
|
f(MRB_TT_PROC, struct RProc, "Proc") \
|
|
f(MRB_TT_ARRAY, struct RArray, "Array") \
|
|
f(MRB_TT_STRING, struct RString, "String") \
|
|
f(MRB_TT_RANGE, struct RRange, "Range") \
|
|
f(MRB_TT_ENV, struct REnv, "env") \
|
|
f(MRB_TT_FIBER, struct RFiber, "Fiber") \
|
|
f(MRB_TT_STRUCT, struct RArray, "Struct") \
|
|
f(MRB_TT_ISTRUCT, struct RIStruct, "istruct") \
|
|
f(MRB_TT_BREAK, struct RBreak, "break") \
|
|
f(MRB_TT_COMPLEX, struct RComplex, "Complex") \
|
|
f(MRB_TT_RATIONAL, struct RRational, "Rational") \
|
|
f(MRB_TT_BIGINT, struct RBigint, "Integer") \
|
|
f(MRB_TT_BACKTRACE, struct RBacktrace, "backtrace") \
|
|
f(MRB_TT_SET, struct RSet, "Set")
|
|
|
|
enum mrb_vtype {
|
|
#define MRB_VTYPE_DEFINE(tt, type, name) tt,
|
|
MRB_VTYPE_FOREACH(MRB_VTYPE_DEFINE)
|
|
#undef MRB_VTYPE_DEFINE
|
|
MRB_TT_MAXDEFINE
|
|
};
|
|
|
|
/* obsolete name for MRB_TT_CDATA */
|
|
#define MRB_TT_DATA MRB_TT_CDATA
|
|
|
|
#define MRB_VTYPE_TYPEOF(tt) MRB_TYPEOF_##tt
|
|
|
|
#define MRB_VTYPE_TYPEDEF(tt, type, name) typedef type MRB_VTYPE_TYPEOF(tt);
|
|
MRB_VTYPE_FOREACH(MRB_VTYPE_TYPEDEF)
|
|
#undef MRB_VTYPE_TYPEDEF
|
|
|
|
/* for compatibility */
|
|
#define MRB_TT_FIXNUM MRB_TT_INTEGER
|
|
|
|
#include <mruby/object.h>
|
|
|
|
#ifdef MRB_DOCUMENTATION_BLOCK
|
|
|
|
/**
|
|
* @abstract
|
|
* mruby value boxing.
|
|
*
|
|
* Actual implementation depends on configured boxing type.
|
|
*
|
|
* @see mruby/boxing_word.h Word boxing representation (Default)
|
|
* @see mruby/boxing_no.h No boxing representation
|
|
* @see mruby/boxing_nan.h Boxed double representation
|
|
*/
|
|
typedef void mrb_value;
|
|
|
|
#endif
|
|
|
|
#if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT))
|
|
struct RCptr {
|
|
MRB_OBJECT_HEADER;
|
|
void *p;
|
|
};
|
|
#endif
|
|
|
|
#if defined(MRB_NAN_BOXING)
|
|
#include "boxing_nan.h"
|
|
#elif defined(MRB_WORD_BOXING)
|
|
#include "boxing_word.h"
|
|
#else
|
|
#include "boxing_no.h"
|
|
#endif
|
|
|
|
#if INTPTR_MAX < MRB_INT_MAX
|
|
typedef intptr_t mrb_ssize;
|
|
# define MRB_SSIZE_MAX INTPTR_MAX
|
|
#else
|
|
typedef mrb_int mrb_ssize;
|
|
# define MRB_SSIZE_MAX MRB_INT_MAX
|
|
#endif
|
|
|
|
#ifndef mrb_immediate_p
|
|
#define mrb_immediate_p(o) (mrb_type(o) <= MRB_TT_CPTR)
|
|
#endif
|
|
#ifndef mrb_integer_p
|
|
#define mrb_integer_p(o) (mrb_type(o) == MRB_TT_INTEGER)
|
|
#endif
|
|
#ifndef mrb_fixnum_p
|
|
#define mrb_fixnum_p(o) mrb_integer_p(o)
|
|
#endif
|
|
#ifndef mrb_symbol_p
|
|
#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL)
|
|
#endif
|
|
#ifndef mrb_undef_p
|
|
#define mrb_undef_p(o) (mrb_type(o) == MRB_TT_UNDEF)
|
|
#endif
|
|
#ifndef mrb_nil_p
|
|
#define mrb_nil_p(o) (mrb_type(o) == MRB_TT_FALSE && !mrb_fixnum(o))
|
|
#endif
|
|
#ifndef mrb_false_p
|
|
#define mrb_false_p(o) (mrb_type(o) == MRB_TT_FALSE && !!mrb_fixnum(o))
|
|
#endif
|
|
#ifndef mrb_true_p
|
|
#define mrb_true_p(o) (mrb_type(o) == MRB_TT_TRUE)
|
|
#endif
|
|
#ifndef mrb_float_p
|
|
#ifndef MRB_NO_FLOAT
|
|
#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT)
|
|
#else
|
|
#define mrb_float_p(o) FALSE
|
|
#endif
|
|
#endif
|
|
#ifndef mrb_array_p
|
|
#define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY)
|
|
#endif
|
|
#ifndef mrb_string_p
|
|
#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING)
|
|
#endif
|
|
#ifndef mrb_hash_p
|
|
#define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH)
|
|
#endif
|
|
#ifndef mrb_cptr_p
|
|
#define mrb_cptr_p(o) (mrb_type(o) == MRB_TT_CPTR)
|
|
#endif
|
|
#ifndef mrb_exception_p
|
|
#define mrb_exception_p(o) (mrb_type(o) == MRB_TT_EXCEPTION)
|
|
#endif
|
|
#ifndef mrb_free_p
|
|
#define mrb_free_p(o) (mrb_type(o) == MRB_TT_FREE)
|
|
#endif
|
|
#ifndef mrb_object_p
|
|
#define mrb_object_p(o) (mrb_type(o) == MRB_TT_OBJECT)
|
|
#endif
|
|
#ifndef mrb_class_p
|
|
#define mrb_class_p(o) (mrb_type(o) == MRB_TT_CLASS)
|
|
#endif
|
|
#ifndef mrb_module_p
|
|
#define mrb_module_p(o) (mrb_type(o) == MRB_TT_MODULE)
|
|
#endif
|
|
#ifndef mrb_iclass_p
|
|
#define mrb_iclass_p(o) (mrb_type(o) == MRB_TT_ICLASS)
|
|
#endif
|
|
#ifndef mrb_sclass_p
|
|
#define mrb_sclass_p(o) (mrb_type(o) == MRB_TT_SCLASS)
|
|
#endif
|
|
#ifndef mrb_proc_p
|
|
#define mrb_proc_p(o) (mrb_type(o) == MRB_TT_PROC)
|
|
#endif
|
|
#ifndef mrb_range_p
|
|
#define mrb_range_p(o) (mrb_type(o) == MRB_TT_RANGE)
|
|
#endif
|
|
#ifndef mrb_env_p
|
|
#define mrb_env_p(o) (mrb_type(o) == MRB_TT_ENV)
|
|
#endif
|
|
#ifndef mrb_data_p
|
|
#define mrb_data_p(o) (mrb_type(o) == MRB_TT_CDATA)
|
|
#endif
|
|
#ifndef mrb_fiber_p
|
|
#define mrb_fiber_p(o) (mrb_type(o) == MRB_TT_FIBER)
|
|
#endif
|
|
#ifndef mrb_istruct_p
|
|
#define mrb_istruct_p(o) (mrb_type(o) == MRB_TT_ISTRUCT)
|
|
#endif
|
|
#ifndef mrb_break_p
|
|
#define mrb_break_p(o) (mrb_type(o) == MRB_TT_BREAK)
|
|
#endif
|
|
#ifndef mrb_bool
|
|
#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE)
|
|
#endif
|
|
#define mrb_test(o) mrb_bool(o)
|
|
#ifndef mrb_bigint_p
|
|
#ifdef MRB_USE_BIGINT
|
|
#define mrb_bigint_p(o) (mrb_type(o) == MRB_TT_BIGINT)
|
|
#else
|
|
#define mrb_bigint_p(o) FALSE
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Returns a float in Ruby.
|
|
*
|
|
* Takes a float and boxes it into an mrb_value
|
|
*/
|
|
#ifndef MRB_NO_FLOAT
|
|
MRB_INLINE mrb_value
|
|
mrb_float_value(struct mrb_state *mrb, mrb_float f)
|
|
{
|
|
mrb_value v;
|
|
(void) mrb;
|
|
SET_FLOAT_VALUE(mrb, v, f);
|
|
return v;
|
|
}
|
|
#endif
|
|
|
|
MRB_INLINE mrb_value
|
|
mrb_cptr_value(struct mrb_state *mrb, void *p)
|
|
{
|
|
mrb_value v;
|
|
(void) mrb;
|
|
SET_CPTR_VALUE(mrb,v,p);
|
|
return v;
|
|
}
|
|
|
|
/**
|
|
* Returns an integer in Ruby.
|
|
*/
|
|
MRB_INLINE mrb_value
|
|
mrb_int_value(struct mrb_state *mrb, mrb_int i)
|
|
{
|
|
mrb_value v;
|
|
SET_INT_VALUE(mrb, v, i);
|
|
return v;
|
|
}
|
|
|
|
MRB_INLINE mrb_value
|
|
mrb_fixnum_value(mrb_int i)
|
|
{
|
|
mrb_value v;
|
|
SET_FIXNUM_VALUE(v, i);
|
|
return v;
|
|
}
|
|
|
|
MRB_INLINE mrb_value
|
|
mrb_symbol_value(mrb_sym i)
|
|
{
|
|
mrb_value v;
|
|
SET_SYM_VALUE(v, i);
|
|
return v;
|
|
}
|
|
|
|
MRB_INLINE mrb_value
|
|
mrb_obj_value(void *p)
|
|
{
|
|
mrb_value v;
|
|
SET_OBJ_VALUE(v, (struct RBasic*)p);
|
|
return v;
|
|
}
|
|
|
|
/**
|
|
* Get a nil mrb_value object.
|
|
*
|
|
* @return
|
|
* nil mrb_value object reference.
|
|
*/
|
|
MRB_INLINE mrb_value
|
|
mrb_nil_value(void)
|
|
{
|
|
mrb_value v;
|
|
SET_NIL_VALUE(v);
|
|
return v;
|
|
}
|
|
|
|
/**
|
|
* Returns false in Ruby.
|
|
*/
|
|
MRB_INLINE mrb_value
|
|
mrb_false_value(void)
|
|
{
|
|
mrb_value v;
|
|
SET_FALSE_VALUE(v);
|
|
return v;
|
|
}
|
|
|
|
/**
|
|
* Returns true in Ruby.
|
|
*/
|
|
MRB_INLINE mrb_value
|
|
mrb_true_value(void)
|
|
{
|
|
mrb_value v;
|
|
SET_TRUE_VALUE(v);
|
|
return v;
|
|
}
|
|
|
|
MRB_INLINE mrb_value
|
|
mrb_bool_value(mrb_bool boolean)
|
|
{
|
|
mrb_value v;
|
|
SET_BOOL_VALUE(v, boolean);
|
|
return v;
|
|
}
|
|
|
|
MRB_INLINE mrb_value
|
|
mrb_undef_value(void)
|
|
{
|
|
mrb_value v;
|
|
SET_UNDEF_VALUE(v);
|
|
return v;
|
|
}
|
|
|
|
#if defined(MRB_USE_CUSTOM_RO_DATA_P)
|
|
/* If you define `MRB_USE_CUSTOM_RO_DATA_P`, you must implement `mrb_ro_data_p()`. */
|
|
mrb_bool mrb_ro_data_p(const char *p);
|
|
#elif !defined(MRB_NO_DEFAULT_RO_DATA_P)
|
|
#if defined(MRB_USE_ETEXT_RO_DATA_P)
|
|
#define MRB_LINK_TIME_RO_DATA_P
|
|
extern char etext, edata;
|
|
static inline mrb_bool
|
|
mrb_ro_data_p(const char *p)
|
|
{
|
|
return &etext < p && p < &edata;
|
|
}
|
|
#elif defined(__APPLE__)
|
|
#define MRB_LINK_TIME_RO_DATA_P
|
|
#include <mach-o/getsect.h>
|
|
#include <crt_externs.h> // for _NSGetMachExecuteHeader
|
|
static inline mrb_bool
|
|
mrb_ro_data_p(const char *p)
|
|
{
|
|
#ifdef __LP64__
|
|
struct mach_header_64 *mhp;
|
|
#else
|
|
struct mach_header *mhp;
|
|
#endif
|
|
mhp = _NSGetMachExecuteHeader();
|
|
unsigned long textsize;
|
|
char *text = (char*)getsegmentdata(mhp, SEG_TEXT, &textsize);
|
|
return text <= p && p < text + textsize;
|
|
}
|
|
#endif /* Linux or macOS */
|
|
#endif /* MRB_NO_DEFAULT_RO_DATA_P */
|
|
#ifndef MRB_LINK_TIME_RO_DATA_P
|
|
# define mrb_ro_data_p(p) FALSE
|
|
#endif
|
|
|
|
MRB_END_DECL
|
|
|
|
#endif /* MRUBY_VALUE_H */
|