Skip to content

Latest commit

 

History

History
249 lines (201 loc) · 8.7 KB

003.md

File metadata and controls

249 lines (201 loc) · 8.7 KB

ZVAL

1,创建一个新的扩展

./ext_skel --extname=zval1

2,zval结构

#Zend/zend.h 
typedef union _zvalue_value {
	long lval;					/* long 值 */
	double dval;				/* double 值 */
	struct {                   /* 字符串类型值 */
		char *val;
		int len;
	} str;
	HashTable *ht;				/* hash table value */
	zend_object_value obj;     /* 对像类型值 */
} zvalue_value;

struct _zval_struct {
	/* Variable information */
	zvalue_value value;		/* 值 */
	zend_uint refcount__gc; /* 引用计数 */
	zend_uchar type;	/* 类型 */
	zend_uchar is_ref__gc; /* 是否引用 */
};

3,zval类型

#define IS_NULL		0
#define IS_LONG		1
#define IS_DOUBLE	2
#define IS_BOOL		3
#define IS_ARRAY	4
#define IS_OBJECT	5
#define IS_STRING	6
#define IS_RESOURCE	7
#define IS_CONSTANT	8
#define IS_CONSTANT_ARRAY	9
#define IS_CALLABLE	10

4,宏

#宏的名字的规则,Z_XXXX -> zvale, Z_XXXX_P -> *zval, Z_XXXX_PP -> **zval

#Zend/zend_alloc.h
#define ALLOC_ZVAL(z)	(z) = (zval *) emalloc(sizeof(zval))
#define FREE_ZVAL(z)	efree_rel(z)
#define ALLOC_ZVAL_REL(z)	(z) = (zval *) emalloc_rel(sizeof(zval))
#define FREE_ZVAL_REL(z)	efree_rel(z)

#Zend/zend.h
#define INIT_PZVAL(z) (z)->refcount__gc = 1;(z)->is_ref__gc = 0;
#define INIT_ZVAL(z) z = zval_used_for_init;

#define ZVAL_FALSE(z)                   ZVAL_BOOL(z, 0) //设置zval
#define ZVAL_TRUE(z)                    ZVAL_BOOL(z, 1)

/* struct操作宏 */
#define Z_LVAL(zval)    (zval).value.lval  //获取long值
#define Z_BVAL(zval)    ((zend_bool)(zval).value.lval)  //获取bool值
#define Z_DVAL(zval)    (zval).value.dval //获取double值
#define Z_STRVAL(zval)  (zval).value.str.val //获取string的指针
#define Z_STRLEN(zval)   (zval).value.str.len //获取string的长度
#define Z_ARRVAL(zval)  (zval).value.ht       //获取hashtable值
#define Z_OBJVAL(zval)  (zval).value.obj      //获取object值
#define Z_OBJ_HANDLE(zval)  Z_OBJVAL(zval).handle //
#define Z_OBJ_HT(zval)      Z_OBJVAL(zval).handlers //
#define Z_OBJCE(zval)       zend_get_class_entry(&(zval) TSRMLS_CC) //
#define Z_OBJPROP(zval)     Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC) //
#define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf //
#define Z_RESVAL(zval)      (zval).value.lval //获取long值
#define Z_OBJDEBUG(zval,is_tmp) (Z_OBJ_HANDLER((zval),get_debug_info)?	Z_OBJ_HANDLER((zval),get_debug_info)(&(zval),&is_tmp TSRMLS_CC):	(is_tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL)) //

/* 指针操作宏 */
#define Z_LVAL_P(zval_p)        Z_LVAL(*zval_p)
#define Z_BVAL_P(zval_p)        Z_BVAL(*zval_p)
#define Z_DVAL_P(zval_p)        Z_DVAL(*zval_p)
#define Z_STRVAL_P(zval_p)      Z_STRVAL(*zval_p)
#define Z_STRLEN_P(zval_p)      Z_STRLEN(*zval_p)
#define Z_ARRVAL_P(zval_p)      Z_ARRVAL(*zval_p)
#define Z_OBJPROP_P(zval_p)     Z_OBJPROP(*zval_p)
#define Z_OBJCE_P(zval_p)       Z_OBJCE(*zval_p)
#define Z_RESVAL_P(zval_p)      Z_RESVAL(*zval_p)
#define Z_OBJVAL_P(zval_p)      Z_OBJVAL(*zval_p)
#define Z_OBJ_HANDLE_P(zval_p)  Z_OBJ_HANDLE(*zval_p)
#define Z_OBJ_HT_P(zval_p)      Z_OBJ_HT(*zval_p)
#define Z_OBJ_HANDLER_P(zval_p, h)  Z_OBJ_HANDLER(*zval_p, h)   #define 	Z_OBJDEBUG_P(zval_p,is_tmp) Z_OBJDEBUG(*zval_p,is_tmp)

/*  */
#define Z_LVAL_PP(zval_pp)      Z_LVAL(**zval_pp)
#define Z_BVAL_PP(zval_pp)      Z_BVAL(**zval_pp)
#define Z_DVAL_PP(zval_pp)      Z_DVAL(**zval_pp)
#define Z_STRVAL_PP(zval_pp)    Z_STRVAL(**zval_pp)
#define Z_STRLEN_PP(zval_pp)    Z_STRLEN(**zval_pp)
#define Z_ARRVAL_PP(zval_pp)    Z_ARRVAL(**zval_pp)
#define Z_OBJPROP_PP(zval_pp)   Z_OBJPROP(**zval_pp)
#define Z_OBJCE_PP(zval_pp)     Z_OBJCE(**zval_pp)
#define Z_RESVAL_PP(zval_pp)    Z_RESVAL(**zval_pp)
#define Z_OBJVAL_PP(zval_pp)    Z_OBJVAL(**zval_pp)
#define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p)
#define Z_OBJ_HT_PP(zval_p)     Z_OBJ_HT(**zval_p)
#define Z_OBJ_HANDLER_PP(zval_p, h)     Z_OBJ_HANDLER(**zval_p, h)
#define Z_OBJDEBUG_PP(zval_pp,is_tmp)   Z_OBJDEBUG(**zval_pp,is_tmp)


/* 获取zval的变量类型 */
#define Z_TYPE(zval)        (zval).type
#define Z_TYPE_P(zval_p)    Z_TYPE(*zval_p)
#define Z_TYPE_PP(zval_pp)  Z_TYPE(**zval_pp)

/* zval初始化宏 */
#define ALLOC_ZVAL(z)   (z) = (zval *) emalloc(sizeof(zval)) //初始化zval,分配内存
#define FREE_ZVAL(z)    efree_rel(z)  //释放zvalue内存

#define ALLOC_ZVAL_REL(z)(z) = (zval *) emalloc_rel(sizeof(zval))
#define FREE_ZVAL_REL(z)    efree_rel(z)

/* HashTable初始化宏 */
#define ALLOC_HASHTABLE(ht)  (ht) = (HashTable *) emalloc(sizeof(HashTable)) //初始化HashTable
#define FREE_HASHTABLE(ht)  efree(ht)

#define ALLOC_HASHTABLE_REL(ht)  (ht) = (HashTable *) emalloc_rel(sizeof(HashTable))
#define FREE_HASHTABLE_REL(ht)  efree_rel(ht)


#define INIT_PZVAL(z) (z)->refcount__gc = 1; (z)->is_ref__gc = 0; //设置refcount
#define INIT_ZVAL(z) z = zval_used_for_init;

#define ALLOC_INIT_ZVAL(zp)  ALLOC_ZVAL(zp); INIT_ZVAL(*zp); //分配内存并设置默认值
#define MAKE_STD_ZVAL(zv)   ALLOC_ZVAL(zv); INIT_PZVAL(zv); //分配内存并设置默认值
#define PZVAL_IS_REF(z)     Z_ISREF_P(z)

/* 拷贝zval的值 */
#define ZVAL_COPY_VALUE(z, v)                   \
do {                                        \
	(z)->value = (v)->value;                \
	Z_TYPE_P(z) = Z_TYPE_P(v);              \
} while (0)


#define INIT_PZVAL_COPY(z, v)                   \
do {                                        \
	ZVAL_COPY_VALUE(z, v);                  \
	Z_SET_REFCOUNT_P(z, 1);                 \
	Z_UNSET_ISREF_P(z);                     \
} while (0)




#define ZVAL_IS_NULL(z) (Z_TYPE_P(z)==IS_NULL) //判断zval是否为NULL

/* 设置zval为resource类型值 */
#define ZVAL_RESOURCE(z, l) do {    \
	zval *__z = (z);            \
	Z_LVAL_P(__z) = l;          \
	Z_TYPE_P(__z) = IS_RESOURCE;\
} while (0)

/* 设置zval为bool类型值 */
#define ZVAL_BOOL(z, b) do {        \
	zval *__z = (z);            \
	Z_LVAL_P(__z) = ((b) != 0); \
	Z_TYPE_P(__z) = IS_BOOL;    \
} while (0)

/* 设置zval为NULL */
#define ZVAL_NULL(z) {              \
	Z_TYPE_P(z) = IS_NULL;      \
}

/* 设置zval为long值 */
#define ZVAL_LONG(z, l) {           \
	zval *__z = (z);            \
	Z_LVAL_P(__z) = l;          \
	Z_TYPE_P(__z) = IS_LONG;    \
}

/* 设置zval为double值 */
#define ZVAL_DOUBLE(z, d) {         \
	zval *__z = (z);            \
	Z_DVAL_P(__z) = d;          \
	Z_TYPE_P(__z) = IS_DOUBLE;  \
}

/* 设置zval为string值 */
#define ZVAL_STRING(z, s, duplicate) do {   \
	const char *__s=(s);                \
	zval *__z = (z);                    \
	Z_STRLEN_P(__z) = strlen(__s);      \
	Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\
	Z_TYPE_P(__z) = IS_STRING;          \
} while (0)

/* 设置zval为string值 */
#define ZVAL_STRINGL(z, s, l, duplicate) do {   \
	const char *__s=(s); int __l=l;         \
	zval *__z = (z);                        \
	Z_STRLEN_P(__z) = __l;                  \
	Z_STRVAL_P(__z) = (duplicate?estrndup(__s, __l):(char*)__s);\
	Z_TYPE_P(__z) = IS_STRING;              \
} while (0)

/* 设置zval为empty string值 */
#define ZVAL_EMPTY_STRING(z) do {   \
	zval *__z = (z);            \
	Z_STRLEN_P(__z) = 0;        \
	Z_STRVAL_P(__z) = STR_EMPTY_ALLOC();\
	Z_TYPE_P(__z) = IS_STRING;  \
} while (0)

/* 设置zval为zval值 */
#define ZVAL_ZVAL(z, zv, copy, dtor) {          \
	zend_uchar is_ref = Z_ISREF_P(z);       \
	zend_uint refcount = Z_REFCOUNT_P(z);   \
	ZVAL_COPY_VALUE(z, zv);                 \
	if (copy) {                             \
	    zval_copy_ctor(z);                  \
	}                                       \
	if (dtor) {                             \
    	if (!copy) {                        \
        	ZVAL_NULL(zv);                  \
    	}                                   \
    	zval_ptr_dtor(&zv);                 \
	}                                       \
	Z_SET_ISREF_TO_P(z, is_ref);            \
	Z_SET_REFCOUNT_P(z, refcount);          \
}

5,类型转换

convert_to_long(zval *op);  //zval -> long
convert_to_double(zval *op); //zval -> double
convert_to_null(zval *op); //zval -> null
convert_to_boolean(zval *op); //zval -> boolean
convert_to_array(zval *op); //zval -> array
convert_to_object(zval *op); //zval -> object

#define convert_to_cstring(op) if ((op)->type != IS_STRING) 	{ _convert_to_cstring((op) ZEND_FILE_LINE_CC); }

#define convert_to_string(op) if ((op)->type != IS_STRING) 	{ _convert_to_string((op) ZEND_FILE_LINE_CC); }

ZEND_API double zend_string_to_double(const char *number, zend_uint length);

ZEND_API int zval_is_true(zval *op);