2019-03-14 15:04:34 +00:00
|
|
|
//
|
|
|
|
// php-armadillo/php_arma.hh
|
|
|
|
//
|
|
|
|
// @Author CismonX
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef PHP_ARMA_HH
|
|
|
|
#define PHP_ARMA_HH
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <php.h>
|
|
|
|
#include <zend_exceptions.h>
|
2019-03-17 03:30:03 +00:00
|
|
|
|
2019-03-19 05:28:45 +00:00
|
|
|
#include <functional>
|
2019-03-14 15:04:34 +00:00
|
|
|
|
2019-03-14 15:23:21 +00:00
|
|
|
#define PHP_ARMA_VERSION "0.0.1"
|
|
|
|
|
2019-03-14 15:04:34 +00:00
|
|
|
#if PHP_VERSION_ID >= 70400
|
|
|
|
#define ZEND_ACC_CTOR 0
|
|
|
|
#endif
|
|
|
|
|
2019-06-07 18:59:11 +00:00
|
|
|
#define ARMA_DONT_PRINT_ERRORS
|
|
|
|
|
2019-03-15 15:25:24 +00:00
|
|
|
/// Helper macros for method entry.
|
|
|
|
|
2019-04-13 10:17:01 +00:00
|
|
|
#define PHP_ARMA_START_ME(cls, ...) \
|
|
|
|
zend_function_entry cls<__VA_ARGS__>::me[] = {
|
2019-03-14 15:04:34 +00:00
|
|
|
|
2019-03-20 14:55:19 +00:00
|
|
|
#define PHP_ARMA_END_ME() \
|
|
|
|
PHP_FE_END \
|
|
|
|
}
|
2019-03-15 15:25:24 +00:00
|
|
|
|
2019-03-20 14:55:19 +00:00
|
|
|
#define PHP_ARMA_ME(func, flags) \
|
2019-03-29 12:18:44 +00:00
|
|
|
ZEND_FENTRY(func, zif_##func, nullptr, flags)
|
2019-03-15 15:25:24 +00:00
|
|
|
|
2019-03-31 03:19:04 +00:00
|
|
|
#define PHP_ARMA_METHOD(cls, func, ...) \
|
2019-03-29 12:18:44 +00:00
|
|
|
void ZEND_FASTCALL cls<__VA_ARGS__>::zif_##func(INTERNAL_FUNCTION_PARAMETERS)
|
2019-03-14 15:04:34 +00:00
|
|
|
|
2019-05-25 18:21:48 +00:00
|
|
|
#define PHP_ARMA_FENTRY(fentry) \
|
2019-07-12 16:29:03 +00:00
|
|
|
std::make_tuple(fentry_size(fentry), fentry)
|
2019-05-25 18:21:48 +00:00
|
|
|
|
|
|
|
#define PHP_ARMA_INSTANTIATE(parent, child) \
|
|
|
|
template class parent<double, child<double>>; \
|
|
|
|
template class parent<zend_long, child<zend_long>>; \
|
|
|
|
template class parent<cx_double, child<cx_double>>
|
|
|
|
|
2019-06-12 03:11:27 +00:00
|
|
|
/// Helper macros for class entry and object handlers.
|
2019-03-15 15:25:24 +00:00
|
|
|
|
2019-03-23 16:24:34 +00:00
|
|
|
#define PHP_ARMA_CE_HANDLRES_DECLARE() \
|
|
|
|
static inline zend_class_entry *ce; \
|
2019-03-20 14:55:19 +00:00
|
|
|
static inline zend_object_handlers handlers
|
2019-03-15 15:25:24 +00:00
|
|
|
|
2019-03-20 14:55:19 +00:00
|
|
|
#define PHP_ARMA_CE(cls, ...) \
|
|
|
|
cls<__VA_ARGS__>::ce
|
2019-03-15 15:25:24 +00:00
|
|
|
|
2019-03-20 14:55:19 +00:00
|
|
|
#define PHP_ARMA_HANDLERS(cls, ...) \
|
|
|
|
&cls<__VA_ARGS__>::handlers
|
2019-03-14 15:04:34 +00:00
|
|
|
|
2019-03-23 16:24:34 +00:00
|
|
|
#define Z_OBJNAME_P(zval_p) \
|
|
|
|
ZSTR_VAL(Z_OBJCE_P(zval_p)->name)
|
|
|
|
|
2019-04-13 10:17:01 +00:00
|
|
|
#define PHP_ARMA_COMMON_DECLARE() \
|
|
|
|
struct php_name; \
|
|
|
|
static zend_function_entry me[]
|
|
|
|
|
2019-04-01 06:04:46 +00:00
|
|
|
#define PHP_ARMA_NAME_DECLARE(cls, name, ...) \
|
|
|
|
template <> \
|
|
|
|
struct cls<__VA_ARGS__>::php_name \
|
|
|
|
{ \
|
|
|
|
static constexpr const char val[] = name; \
|
|
|
|
}
|
|
|
|
|
2019-04-16 11:00:50 +00:00
|
|
|
#ifdef PHP_ARMA_OPERATORS
|
|
|
|
|
|
|
|
/// Helper macros for handling operator overloading.
|
|
|
|
|
2019-04-18 10:15:33 +00:00
|
|
|
#define PHP_ARMA_OPERATOR_BEGIN(parent_ce) \
|
|
|
|
{ \
|
|
|
|
if (instanceof_function(ce, parent_ce)) {
|
|
|
|
|
|
|
|
#define PHP_ARMA_OPERATOR_END() \
|
|
|
|
return false; \
|
|
|
|
} \
|
2019-04-16 11:00:50 +00:00
|
|
|
}
|
|
|
|
|
2019-06-07 20:03:21 +00:00
|
|
|
#define PHP_ARMA_OPERATOR_EX2(base, child, func) \
|
|
|
|
if (instanceof_function(ce, child::ce)) { \
|
|
|
|
using base_t = arg_type<void(base)>::type; \
|
|
|
|
return base_t::operators::func(zv1, zv2, rv); \
|
2019-06-06 15:56:10 +00:00
|
|
|
}
|
|
|
|
|
2019-06-07 20:03:21 +00:00
|
|
|
#define PHP_ARMA_OPERATOR_EX(cls, func) \
|
|
|
|
PHP_ARMA_OPERATOR_EX2(cls, cls, func)
|
|
|
|
|
2019-06-09 14:47:33 +00:00
|
|
|
#define PHP_ARMA_ASSIGN_OPERATOR_EX(cls, func) \
|
2019-06-06 15:56:10 +00:00
|
|
|
if (instanceof_function(ce, cls::ce)) { \
|
|
|
|
auto v = cls::operators::func(zv1, zv2, zv1); \
|
|
|
|
if (rv) { \
|
|
|
|
ZVAL_COPY(rv, zv1); \
|
|
|
|
} \
|
|
|
|
return v; \
|
|
|
|
}
|
|
|
|
|
2019-04-16 11:00:50 +00:00
|
|
|
#endif // PHP_ARMA_OPERATORS
|
|
|
|
|
2019-05-27 08:51:46 +00:00
|
|
|
/// Helper macros for handling native objects.
|
|
|
|
|
|
|
|
#define ZOBJ_NATIVE(zobj) \
|
|
|
|
to_native_object<native_t>(zobj)
|
|
|
|
|
|
|
|
#define Z_NATIVE_OBJ_P(zv) ZOBJ_NATIVE(Z_OBJ_P(zv))
|
2019-06-12 03:11:27 +00:00
|
|
|
#define THIS_NATIVE Z_NATIVE_OBJ_P(&EX(This))
|
|
|
|
|
|
|
|
/// Misc helper macros.
|
|
|
|
|
|
|
|
#define RETVAL_THIS() \
|
|
|
|
ZVAL_COPY(return_value, &EX(This))
|
2019-05-27 08:51:46 +00:00
|
|
|
|
2019-03-14 15:04:34 +00:00
|
|
|
namespace php_arma
|
|
|
|
{
|
2019-04-23 09:26:39 +00:00
|
|
|
extern zend_module_entry module_entry;
|
|
|
|
|
2019-04-01 06:04:46 +00:00
|
|
|
/// Helpers for compile-time string concatenation for better module startup performance.
|
|
|
|
namespace str
|
|
|
|
{
|
|
|
|
template <size_t... S>
|
2019-04-13 10:17:01 +00:00
|
|
|
using seq = std::integer_sequence<size_t, S...>;
|
2019-04-01 06:04:46 +00:00
|
|
|
|
|
|
|
template <size_t N>
|
2019-04-13 10:17:01 +00:00
|
|
|
using seq_impl = std::make_integer_sequence<size_t, N>;
|
2019-04-01 06:04:46 +00:00
|
|
|
|
|
|
|
constexpr auto get_len(const char *str)
|
|
|
|
{
|
|
|
|
auto i = 0;
|
|
|
|
for (; *str != 0; ++i, ++str);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <const char*, typename, const char*, typename>
|
|
|
|
struct concat_impl;
|
|
|
|
|
2019-05-26 04:39:35 +00:00
|
|
|
template <const char *Str1, size_t... Len1, const char *Str2, size_t... Len2>
|
2019-04-13 10:17:01 +00:00
|
|
|
struct concat_impl<Str1, seq<Len1...>, Str2, seq<Len2...>>
|
2019-04-01 06:04:46 +00:00
|
|
|
{
|
|
|
|
static constexpr const char value[]
|
|
|
|
{
|
|
|
|
Str1[Len1]..., Str2[Len2]..., 0
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
template <const char *Str1, const char *Str2>
|
|
|
|
constexpr auto concat
|
|
|
|
{
|
2019-04-13 10:17:01 +00:00
|
|
|
concat_impl<Str1, seq_impl<get_len(Str1)>, Str2, seq_impl<get_len(Str2)>>::value
|
2019-04-01 06:04:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
constexpr const char namespace_prefix[] = "Arma\\";
|
2019-04-13 10:17:01 +00:00
|
|
|
constexpr const char internal_prefix[] = "Internal\\";
|
2019-04-01 06:04:46 +00:00
|
|
|
|
|
|
|
template <const char *Str>
|
|
|
|
constexpr auto with_arma_prefix
|
|
|
|
{
|
|
|
|
concat<namespace_prefix, Str>
|
|
|
|
};
|
2019-04-13 10:17:01 +00:00
|
|
|
|
|
|
|
template <const char *Str>
|
|
|
|
constexpr auto with_internal_prefix
|
|
|
|
{
|
|
|
|
concat<internal_prefix, Str>
|
|
|
|
};
|
2019-04-01 06:04:46 +00:00
|
|
|
}
|
2019-06-07 20:03:21 +00:00
|
|
|
|
|
|
|
/// Hack for extracting type from a parentheses-enclosed macro argument.
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct arg_type;
|
|
|
|
|
|
|
|
template <typename T, typename U>
|
|
|
|
struct arg_type<T(U)>
|
|
|
|
{
|
|
|
|
using type = U;
|
|
|
|
};
|
2019-06-11 10:18:40 +00:00
|
|
|
|
|
|
|
/// Helper functions for throwing exceptions when errors occur.
|
|
|
|
|
|
|
|
zend_always_inline
|
|
|
|
void throw_exception_ex(zend_class_entry *ce, const char *message)
|
|
|
|
{
|
|
|
|
zend_throw_exception(ce, message, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename... Ts>
|
|
|
|
zend_always_inline
|
|
|
|
void throw_exception_ex(zend_class_entry *ce, const char *message, Ts&&... args)
|
|
|
|
{
|
|
|
|
zend_throw_exception_ex(ce, 0, message, args...);
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_always_inline
|
|
|
|
void throw_exception(const char *message)
|
|
|
|
{
|
|
|
|
throw_exception_ex(zend_ce_exception, message);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename... Ts>
|
|
|
|
zend_always_inline
|
|
|
|
void throw_exception(const char *message, Ts&&... args)
|
|
|
|
{
|
|
|
|
throw_exception_ex(zend_ce_exception, message, args...);
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_always_inline
|
|
|
|
void throw_error(const char *message)
|
|
|
|
{
|
|
|
|
throw_exception_ex(zend_ce_error, message);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename... Ts>
|
|
|
|
zend_always_inline
|
|
|
|
void throw_error(const char *message, Ts&&... args)
|
|
|
|
{
|
|
|
|
throw_exception_ex(zend_ce_error, message, args...);
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_always_inline
|
|
|
|
void ex_bad_type(const char *expected, const char *got)
|
|
|
|
{
|
|
|
|
throw_exception_ex(zend_ce_type_error, "bad type, expected %s, %s given", expected, got);
|
|
|
|
}
|
2019-04-01 06:04:46 +00:00
|
|
|
|
2019-03-17 03:30:03 +00:00
|
|
|
/// Helper functions for initializing class entry and object handlers.
|
|
|
|
|
2019-04-01 06:04:46 +00:00
|
|
|
template <const char *Name, typename F>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-05-30 06:19:28 +00:00
|
|
|
zend_class_entry *ce_init(const zend_function_entry *methods, F&& init_func)
|
2019-03-14 15:04:34 +00:00
|
|
|
{
|
|
|
|
zend_class_entry tmp_ce;
|
2019-04-01 06:04:46 +00:00
|
|
|
constexpr auto name = str::with_arma_prefix<Name>;
|
|
|
|
constexpr auto name_len = str::get_len(name);
|
|
|
|
INIT_CLASS_ENTRY_EX(tmp_ce, name, name_len, methods);
|
2019-03-14 15:04:34 +00:00
|
|
|
return init_func(&tmp_ce);
|
|
|
|
}
|
|
|
|
|
2019-04-01 06:04:46 +00:00
|
|
|
template <const char *Name, typename F, typename... Ts>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-05-30 06:19:28 +00:00
|
|
|
zend_class_entry *ce_init(const zend_function_entry *methods, F&& init_func, Ts... interfaces)
|
2019-03-14 15:04:34 +00:00
|
|
|
{
|
2019-04-01 06:04:46 +00:00
|
|
|
auto ce = ce_init<Name>(methods, init_func);
|
2019-03-19 05:28:45 +00:00
|
|
|
zend_class_implements(ce, sizeof...(Ts), interfaces...);
|
2019-03-14 15:04:34 +00:00
|
|
|
return ce;
|
|
|
|
}
|
|
|
|
|
2019-04-01 06:04:46 +00:00
|
|
|
template <const char *Name>
|
|
|
|
zend_always_inline
|
|
|
|
zend_class_entry *interface_register()
|
|
|
|
{
|
|
|
|
// Although methods are declared in interfaces as you see in the stubs,
|
|
|
|
// nothing is declared in the internal interface implementation.
|
2019-06-06 15:56:10 +00:00
|
|
|
return ce_init<str::with_internal_prefix<Name>>(nullptr, zend_register_internal_interface);
|
2019-04-01 06:04:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <const char *Name, typename... Ts>
|
|
|
|
zend_always_inline
|
|
|
|
zend_class_entry *interface_register(Ts... parents)
|
|
|
|
{
|
2019-06-06 15:56:10 +00:00
|
|
|
return ce_init<str::with_internal_prefix<Name>>(nullptr, zend_register_internal_interface, parents...);
|
2019-04-01 06:04:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <const char *Name>
|
2019-03-18 14:49:42 +00:00
|
|
|
zend_always_inline
|
2019-04-01 06:04:46 +00:00
|
|
|
zend_class_entry *class_register(zend_class_entry *parent, const zend_function_entry *methods)
|
2019-03-14 15:04:34 +00:00
|
|
|
{
|
2019-04-04 08:07:37 +00:00
|
|
|
auto init_func = std::bind(zend_register_internal_class_ex, std::placeholders::_1, parent);
|
|
|
|
return ce_init<Name>(methods, init_func);
|
2019-03-19 05:28:45 +00:00
|
|
|
}
|
|
|
|
|
2019-04-01 06:04:46 +00:00
|
|
|
template <const char *Name>
|
2019-03-19 05:28:45 +00:00
|
|
|
zend_always_inline
|
2019-04-01 06:04:46 +00:00
|
|
|
zend_class_entry *abstract_class_register()
|
2019-03-19 05:28:45 +00:00
|
|
|
{
|
2019-04-01 06:04:46 +00:00
|
|
|
auto ce = ce_init<Name>(nullptr, zend_register_internal_class);
|
2019-03-19 05:28:45 +00:00
|
|
|
ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
|
|
|
|
return ce;
|
2019-03-14 15:04:34 +00:00
|
|
|
}
|
|
|
|
|
2019-04-01 06:04:46 +00:00
|
|
|
template <const char *Name, typename... Ts>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-04-01 06:04:46 +00:00
|
|
|
zend_class_entry *abstract_class_register(Ts... interfaces)
|
2019-03-14 15:04:34 +00:00
|
|
|
{
|
2019-04-01 06:04:46 +00:00
|
|
|
auto ce = ce_init<Name>(nullptr, zend_register_internal_class, interfaces...);
|
2019-03-19 05:28:45 +00:00
|
|
|
ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
|
|
|
|
return ce;
|
2019-03-14 15:04:34 +00:00
|
|
|
}
|
|
|
|
|
2019-03-15 15:25:24 +00:00
|
|
|
zend_always_inline
|
|
|
|
void object_handlers_init(zend_object_handlers *handlers)
|
|
|
|
{
|
|
|
|
memcpy(handlers, &std_object_handlers, sizeof(zend_object_handlers));
|
|
|
|
}
|
|
|
|
|
2019-03-14 15:04:34 +00:00
|
|
|
template <typename T>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-03-14 15:04:34 +00:00
|
|
|
zend_object *to_zend_object(T *obj)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<zend_object*>(obj + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-03-16 11:49:50 +00:00
|
|
|
T *to_native_object(zend_object *zobj)
|
2019-03-14 15:04:34 +00:00
|
|
|
{
|
|
|
|
return reinterpret_cast<T*>(zobj) - 1;
|
|
|
|
}
|
|
|
|
|
2019-05-25 18:21:48 +00:00
|
|
|
/// Helper functions for function entry.
|
|
|
|
|
|
|
|
zend_always_inline
|
|
|
|
size_t fentry_size(zend_function_entry *fentry)
|
|
|
|
{
|
|
|
|
size_t retval = 0;
|
|
|
|
while ((fentry++)->fname != nullptr) {
|
|
|
|
++retval;
|
|
|
|
}
|
|
|
|
return retval * sizeof(zend_function_entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename... Ts>
|
|
|
|
zend_always_inline
|
2019-05-26 04:39:35 +00:00
|
|
|
zend_function_entry *fentry_list_concat_impl(size_t mem_size, Ts&&... function_entry)
|
2019-05-25 18:21:48 +00:00
|
|
|
{
|
|
|
|
auto retval = reinterpret_cast<zend_function_entry*>(malloc(mem_size));
|
|
|
|
size_t offset = 0;
|
|
|
|
for (auto [size, fentry] : { function_entry... }) {
|
|
|
|
memcpy(retval + offset, fentry, size);
|
2019-05-26 04:39:35 +00:00
|
|
|
offset += size / sizeof(zend_function_entry);
|
2019-05-25 18:21:48 +00:00
|
|
|
}
|
|
|
|
zend_function_entry empty_fentry PHP_FE_END;
|
|
|
|
memcpy(retval + offset, &empty_fentry, sizeof(zend_function_entry));
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename... Ts>
|
|
|
|
zend_always_inline
|
2019-05-26 04:39:35 +00:00
|
|
|
zend_function_entry *fentry_list_concat(Ts&&... function_entry)
|
2019-05-25 18:21:48 +00:00
|
|
|
{
|
|
|
|
size_t mem_size = sizeof(zend_function_entry);
|
|
|
|
for (auto [size, _] : { function_entry... }) {
|
|
|
|
mem_size += size;
|
|
|
|
}
|
|
|
|
return fentry_list_concat_impl(mem_size, function_entry...);
|
|
|
|
}
|
|
|
|
|
2019-03-20 14:55:19 +00:00
|
|
|
/// Helper functions for handling objects.
|
2019-03-17 03:30:03 +00:00
|
|
|
|
2019-03-14 15:04:34 +00:00
|
|
|
template <typename T, typename F>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-05-30 06:19:28 +00:00
|
|
|
zend_object *object_create(zend_class_entry *ce, F&& init)
|
2019-03-14 15:04:34 +00:00
|
|
|
{
|
2019-03-29 12:18:44 +00:00
|
|
|
auto obj = reinterpret_cast<T*>(emalloc(sizeof(T) + sizeof(zend_object) - sizeof(zval)));
|
2019-03-14 15:04:34 +00:00
|
|
|
auto zobj = to_zend_object(obj);
|
2019-03-23 16:24:34 +00:00
|
|
|
zobj->handlers = init(obj);
|
2019-03-14 15:04:34 +00:00
|
|
|
zend_object_std_init(zobj, ce);
|
|
|
|
return zobj;
|
|
|
|
}
|
|
|
|
|
2019-05-26 04:39:35 +00:00
|
|
|
template <typename T, typename... Ts>
|
|
|
|
zend_always_inline
|
|
|
|
zend_object *object_create_ctor(zend_class_entry *ce, zend_object_handlers *handlers, Ts&&... args)
|
|
|
|
{
|
|
|
|
// If only I can use C++20 here...
|
|
|
|
return object_create<T>(ce, [args = std::forward_as_tuple(args...), handlers](auto obj) {
|
|
|
|
std::apply([obj](auto&&... args) {
|
|
|
|
new(obj) T(args...);
|
|
|
|
}, std::move(args));
|
|
|
|
return handlers;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-03-17 03:30:03 +00:00
|
|
|
zend_always_inline
|
2019-03-23 16:24:34 +00:00
|
|
|
zend_object *object_create(zend_class_entry *ce, const zend_object_handlers *handlers)
|
2019-03-14 15:04:34 +00:00
|
|
|
{
|
2019-04-18 10:15:33 +00:00
|
|
|
auto zobj = reinterpret_cast<zend_object*>(emalloc(
|
2019-03-14 15:04:34 +00:00
|
|
|
sizeof(zend_object) + zend_object_properties_size(ce)));
|
2019-03-23 16:24:34 +00:00
|
|
|
zobj->handlers = handlers;
|
2019-03-14 15:04:34 +00:00
|
|
|
zend_object_std_init(zobj, ce);
|
|
|
|
object_properties_init(zobj, ce);
|
|
|
|
return zobj;
|
|
|
|
}
|
|
|
|
|
2019-05-26 04:39:35 +00:00
|
|
|
template <typename T>
|
|
|
|
zend_always_inline
|
|
|
|
void object_destroy(zend_object *zobj)
|
|
|
|
{
|
|
|
|
zend_object_std_dtor(zobj);
|
|
|
|
to_native_object<T>(zobj)->~T();
|
|
|
|
}
|
|
|
|
|
2019-03-20 14:55:19 +00:00
|
|
|
zend_always_inline
|
|
|
|
void object_set_property(zend_object *obj, size_t idx, zval *val)
|
|
|
|
{
|
|
|
|
zval_ptr_dtor(OBJ_PROP_NUM(obj, idx));
|
|
|
|
ZVAL_COPY(OBJ_PROP_NUM(obj, idx), val);
|
|
|
|
}
|
|
|
|
|
2019-03-24 08:59:29 +00:00
|
|
|
zend_always_inline
|
|
|
|
zend_object *object_non_constructible(zend_class_entry *ce)
|
|
|
|
{
|
2019-06-11 10:18:40 +00:00
|
|
|
throw_error("class %s is not explicitly constructible.", ZSTR_VAL(ce->name));
|
2019-04-02 08:16:11 +00:00
|
|
|
return zend_objects_new(ce);
|
2019-03-24 08:59:29 +00:00
|
|
|
}
|
|
|
|
|
2019-03-17 03:30:03 +00:00
|
|
|
/// Helper functions for handling scalar types.
|
2019-03-14 15:04:34 +00:00
|
|
|
|
2019-03-16 11:49:50 +00:00
|
|
|
template <typename>
|
|
|
|
struct false_type : std::false_type {};
|
|
|
|
|
|
|
|
template <typename T>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-04-01 06:04:46 +00:00
|
|
|
constexpr void bad_scalar_type()
|
2019-03-16 11:49:50 +00:00
|
|
|
{
|
2019-06-11 10:18:40 +00:00
|
|
|
static_assert(false_type<T>::value, "type should be zend_long, double or cx_double");
|
2019-03-16 11:49:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-03-14 15:04:34 +00:00
|
|
|
bool zval_is_scalar(zval *zv)
|
|
|
|
{
|
2019-04-01 06:04:46 +00:00
|
|
|
bad_scalar_type<T>();
|
2019-03-14 15:04:34 +00:00
|
|
|
}
|
|
|
|
|
2019-03-22 08:30:44 +00:00
|
|
|
template <>
|
|
|
|
zend_always_inline
|
2019-03-14 15:04:34 +00:00
|
|
|
bool zval_is_scalar<double>(zval *zv)
|
|
|
|
{
|
|
|
|
return Z_TYPE_P(zv) == IS_DOUBLE;
|
|
|
|
}
|
|
|
|
|
2019-03-22 08:30:44 +00:00
|
|
|
template <>
|
|
|
|
zend_always_inline
|
2019-03-14 15:04:34 +00:00
|
|
|
bool zval_is_scalar<zend_long>(zval *zv)
|
|
|
|
{
|
|
|
|
return Z_TYPE_P(zv) == IS_LONG;
|
|
|
|
}
|
|
|
|
|
2019-03-16 11:49:50 +00:00
|
|
|
template <typename T>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-03-14 15:04:34 +00:00
|
|
|
const char *scalar_type_name()
|
|
|
|
{
|
2019-04-01 06:04:46 +00:00
|
|
|
bad_scalar_type<T>();
|
2019-03-14 15:04:34 +00:00
|
|
|
}
|
|
|
|
|
2019-03-22 08:30:44 +00:00
|
|
|
template <>
|
|
|
|
zend_always_inline
|
2019-03-14 15:04:34 +00:00
|
|
|
const char *scalar_type_name<double>()
|
|
|
|
{
|
|
|
|
return zend_get_type_by_const(IS_DOUBLE);
|
|
|
|
}
|
|
|
|
|
2019-03-22 08:30:44 +00:00
|
|
|
template <>
|
|
|
|
zend_always_inline
|
2019-03-14 15:04:34 +00:00
|
|
|
const char *scalar_type_name<zend_long>()
|
|
|
|
{
|
|
|
|
return zend_get_type_by_const(IS_LONG);
|
|
|
|
}
|
|
|
|
|
2019-03-17 03:30:03 +00:00
|
|
|
template <typename T>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-03-17 03:30:03 +00:00
|
|
|
T zval_get_scalar(zval *zv)
|
|
|
|
{
|
2019-04-01 06:04:46 +00:00
|
|
|
bad_scalar_type<T>();
|
2019-03-17 03:30:03 +00:00
|
|
|
}
|
|
|
|
|
2019-03-22 08:30:44 +00:00
|
|
|
template <>
|
|
|
|
zend_always_inline
|
2019-03-17 03:30:03 +00:00
|
|
|
double zval_get_scalar<double>(zval *zv)
|
|
|
|
{
|
|
|
|
return Z_DVAL_P(zv);
|
|
|
|
}
|
|
|
|
|
2019-03-22 08:30:44 +00:00
|
|
|
template <>
|
|
|
|
zend_always_inline
|
2019-03-17 03:30:03 +00:00
|
|
|
zend_long zval_get_scalar<zend_long>(zval *zv)
|
|
|
|
{
|
|
|
|
return Z_LVAL_P(zv);
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_always_inline
|
|
|
|
void zval_set_scalar(zval *zv, double val)
|
|
|
|
{
|
|
|
|
ZVAL_DOUBLE(zv, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_always_inline
|
|
|
|
void zval_set_scalar(zval *zv, zend_long val)
|
|
|
|
{
|
|
|
|
ZVAL_LONG(zv, val);
|
|
|
|
}
|
|
|
|
|
2019-03-14 15:04:34 +00:00
|
|
|
zend_always_inline
|
|
|
|
const char *zval_get_type_name(zval *zv)
|
|
|
|
{
|
|
|
|
if (Z_TYPE_P(zv) == IS_OBJECT) {
|
|
|
|
return ZSTR_VAL(Z_OBJCE_P(zv)->name);
|
|
|
|
} else {
|
|
|
|
return zend_get_type_by_const(Z_TYPE_P(zv));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2019-03-22 08:30:44 +00:00
|
|
|
zend_always_inline
|
2019-03-15 15:25:24 +00:00
|
|
|
bool zval_check_scalar(zval *zv)
|
2019-03-14 15:04:34 +00:00
|
|
|
{
|
2019-03-26 11:54:58 +00:00
|
|
|
if (UNEXPECTED(!zval_is_scalar<T>(zv))) {
|
2019-03-14 15:04:34 +00:00
|
|
|
ex_bad_type(scalar_type_name<T>(), zval_get_type_name(zv));
|
2019-03-15 15:25:24 +00:00
|
|
|
return false;
|
2019-03-14 15:04:34 +00:00
|
|
|
}
|
2019-03-15 15:25:24 +00:00
|
|
|
return true;
|
2019-03-14 15:04:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // !PHP_ARMA_HH
|