1 
2 /*
3   +------------------------------------------------------------------------+
4   | Zephir Language                                                        |
5   +------------------------------------------------------------------------+
6   | Copyright (c) 2011-2017 Zephir Team (http://www.zephir-lang.com)       |
7   +------------------------------------------------------------------------+
8   | This source file is subject to the New BSD License that is bundled     |
9   | with this package in the file docs/LICENSE.txt.                        |
10   |                                                                        |
11   | If you did not receive a copy of the license and are unable to         |
12   | obtain it through the world-wide-web, please send an email             |
13   | to license@zephir-lang.com so we can send you a copy immediately.      |
14   +------------------------------------------------------------------------+
15   | Authors: Andres Gutierrez <andres@zephir-lang.com>                     |
16   |          Eduar Carvajal <eduar@zephir-lang.com>                        |
17   |          Vladimir Kolesnikov <vladimir@extrememember.com>              |
18   +------------------------------------------------------------------------+
19 */
20 
21 #ifndef ZEPHIR_KERNEL_OBJECT_H
22 #define ZEPHIR_KERNEL_OBJECT_H
23 
24 #include <php.h>
25 #include <Zend/zend.h>
26 
27 #include "kernel/globals.h"
28 #include "kernel/main.h"
29 
30 /** Class Retrieving/Checking */
31 int zephir_class_exists(const zval *class_name, int autoload TSRMLS_DC);
32 int zephir_interface_exists(const zval *interface_name, int autoload TSRMLS_DC);
33 void zephir_get_class(zval *result, zval *object, int lower TSRMLS_DC);
34 void zephir_get_class_ns(zval *result, zval *object, int lower TSRMLS_DC);
35 void zephir_get_ns_class(zval *result, zval *object, int lower TSRMLS_DC);
36 void zephir_get_called_class(zval *return_value TSRMLS_DC);
37 zend_class_entry *zephir_fetch_class(const zval *class_name TSRMLS_DC);
38 zend_class_entry* zephir_fetch_self_class(TSRMLS_D);
39 zend_class_entry* zephir_fetch_parent_class(TSRMLS_D);
40 zend_class_entry* zephir_fetch_static_class(TSRMLS_D);
41 
42 #define ZEPHIR_GET_CLASS_CONSTANT(return_value, ce, const_name) \
43 	do { \
44 		if (FAILURE == zephir_get_class_constant(return_value, ce, const_name, strlen(const_name)+1 TSRMLS_CC)) { \
45 			ZEPHIR_MM_RESTORE(); \
46 			return; \
47 		} \
48 	} while (0)
49 
50 /** Class constants */
51 int zephir_get_class_constant(zval *return_value, zend_class_entry *ce, char *constant_name, unsigned int constant_length TSRMLS_DC);
52 
53 /** Cloning/Instance of*/
54 int zephir_clone(zval *destiny, zval *obj TSRMLS_DC);
55 int zephir_instance_of(zval *result, const zval *object, const zend_class_entry *ce TSRMLS_DC);
56 int zephir_is_instance_of(zval *object, const char *class_name, unsigned int class_length TSRMLS_DC);
57 int zephir_instance_of_ev(const zval *object, const zend_class_entry *ce TSRMLS_DC);
58 int zephir_zval_is_traversable(zval *object TSRMLS_DC);
59 
60 /** Method exists */
61 int zephir_method_exists(const zval *object, const zval *method_name TSRMLS_DC);
62 int zephir_method_exists_ex(const zval *object, const char *method_name, unsigned int method_len TSRMLS_DC);
63 int zephir_method_quick_exists_ex(const zval *object, const char *method_name, unsigned int method_len, unsigned long hash TSRMLS_DC);
64 
65 /** Isset properties */
66 int zephir_isset_property(zval *object, const char *property_name, unsigned int property_length TSRMLS_DC);
67 int zephir_isset_property_quick(zval *object, const char *property_name, unsigned int property_length, unsigned long hash TSRMLS_DC);
68 int zephir_isset_property_zval(zval *object, const zval *property TSRMLS_DC);
69 
70 /** Reading properties */
71 zval* zephir_fetch_property_this_quick(zval *object, const char *property_name, zend_uint property_length, ulong key, int silent TSRMLS_DC);
72 int zephir_read_property(zval **result, zval *object, const char *property_name, zend_uint property_length, int silent TSRMLS_DC);
73 int zephir_read_property_zval(zval **result, zval *object, zval *property, int silent TSRMLS_DC);
74 int zephir_return_property(zval *return_value, zval **return_value_ptr, zval *object, char *property_name, unsigned int property_length TSRMLS_DC);
75 int zephir_return_property_quick(zval *return_value, zval **return_value_ptr, zval *object, char *property_name, unsigned int property_length, unsigned long key TSRMLS_DC);
76 int zephir_fetch_property(zval **result, zval *object, const char *property_name, zend_uint property_length, int silent TSRMLS_DC);
77 int zephir_fetch_property_zval(zval **result, zval *object, zval *property, int silent TSRMLS_DC);
78 
79 /** Updating properties */
80 int zephir_update_property_this(zval *object, char *property_name, unsigned int property_length, zval *value TSRMLS_DC);
81 int zephir_update_property_long(zval *obj, char *property_name, unsigned int property_length, long value TSRMLS_DC);
82 int zephir_update_property_string(zval *object, char *property_name, unsigned int property_length, char *str, unsigned int str_length TSRMLS_DC);
83 int zephir_update_property_bool(zval *obj, char *property_name, unsigned int property_length, int value TSRMLS_DC);
84 int zephir_update_property_null(zval *obj, char *property_name, unsigned int property_length TSRMLS_DC);
85 int zephir_update_property_zval(zval *obj, const char *property_name, unsigned int property_length, zval *value TSRMLS_DC);
86 int zephir_update_property_zval_zval(zval *obj, zval *property, zval *value TSRMLS_DC);
87 int zephir_update_property_empty_array(zend_class_entry *ce, zval *object, char *property, unsigned int property_length TSRMLS_DC);
88 
89 /** Updating array properties */
90 int zephir_update_property_array(zval *object, const char *property, zend_uint property_length, const zval *index, zval *value TSRMLS_DC);
91 int zephir_update_property_array_string(zval *object, char *property, unsigned int property_length, char *index, unsigned int index_length, zval *value TSRMLS_DC);
92 int zephir_update_property_array_append(zval *object, char *property, unsigned int property_length, zval *value TSRMLS_DC);
93 int zephir_update_property_array_multi(zval *object, const char *property, zend_uint property_length, zval **value TSRMLS_DC, const char *types, int types_length, int types_count, ...);
94 
95 /** Increment/Decrement properties */
96 int zephir_property_incr(zval *object, char *property_name, unsigned int property_length TSRMLS_DC);
97 int zephir_property_decr(zval *object, char *property_name, unsigned int property_length TSRMLS_DC);
98 
99 /** Unset properties */
100 int zephir_unset_property(zval* object, const char* name TSRMLS_DC);
101 int zephir_unset_property_array(zval *object, char *property, unsigned int property_length, zval *index TSRMLS_DC);
102 
103 /** Static properties */
104 int zephir_read_static_property(zval **result, const char *class_name, unsigned int class_length, char *property_name, unsigned int property_length TSRMLS_DC);
105 int zephir_update_static_property_ce(zend_class_entry *ce, const char *name, int len, zval **value TSRMLS_DC);
106 int zephir_update_static_property_ce_cache(zend_class_entry *ce, const char *name, int len, zval **value, zend_property_info **property_info TSRMLS_DC);
107 int zephir_update_static_property(const char *class_name, unsigned int class_length, char *name, unsigned int name_length, zval **value TSRMLS_DC);
108 int zephir_read_static_property_ce(zval **result, zend_class_entry *ce, const char *property, int len TSRMLS_DC);
109 int zephir_read_class_property(zval **result, int type, const char *property, int len TSRMLS_DC);
110 zval* zephir_fetch_static_property_ce(zend_class_entry *ce, const char *property, int len TSRMLS_DC);
111 int zephir_update_static_property_array_multi_ce(zend_class_entry *ce, const char *property, zend_uint property_length, zval **value TSRMLS_DC, const char *types, int types_length, int types_count, ...);
112 
113 /** Create instances */
114 int zephir_create_instance(zval *return_value, const zval *class_name TSRMLS_DC);
115 int zephir_create_instance_params(zval *return_value, const zval *class_name, zval *params TSRMLS_DC);
116 
117 /** Create closures */
118 int zephir_create_closure_ex(zval *return_value, zval *this_ptr, zend_class_entry *ce, const char *method_name, zend_uint method_length TSRMLS_DC);
119 
120 void zephir_free_object_storage(void *object TSRMLS_DC);
121 
122 /**
123  * Reads a property from this_ptr (with pre-calculated key)
124  * Variables must be defined in the class definition. This function ignores magic methods or dynamic properties
125  */
zephir_read_property_this_quick(zval ** result,zval * object,const char * property_name,zend_uint property_length,ulong key,int silent TSRMLS_DC)126 ZEPHIR_ATTR_NONNULL static inline int zephir_read_property_this_quick(zval **result, zval *object, const char *property_name, zend_uint property_length, ulong key, int silent TSRMLS_DC)
127 {
128   zval *tmp = zephir_fetch_property_this_quick(object, property_name, property_length, key, silent TSRMLS_CC);
129   if (EXPECTED(tmp != NULL)) {
130 	*result = tmp;
131 	Z_ADDREF_PP(result);
132 	return SUCCESS;
133   }
134 
135   ALLOC_INIT_ZVAL(*result);
136   return FAILURE;
137 }
138 
139 /**
140  * Reads a property from this_ptr
141  * Variables must be defined in the class definition. This function ignores magic methods or dynamic properties
142  */
zephir_read_property_this(zval ** result,zval * object,const char * property_name,zend_uint property_length,int silent TSRMLS_DC)143 ZEPHIR_ATTR_NONNULL static inline int zephir_read_property_this(zval **result, zval *object, const char *property_name, zend_uint property_length, int silent TSRMLS_DC)
144 {
145 #ifdef __GNUC__
146   if (__builtin_constant_p(property_name) && __builtin_constant_p(property_length)) {
147 	return zephir_read_property_this_quick(result, object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
148   }
149 #endif
150 
151   return zephir_read_property_this_quick(result, object, property_name, property_length, zend_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
152 }
153 
zephir_fetch_nproperty_this_quick(zval * object,const char * property_name,zend_uint property_length,ulong key,int silent TSRMLS_DC)154 ZEPHIR_ATTR_NONNULL static inline zval* zephir_fetch_nproperty_this_quick(zval *object, const char *property_name, zend_uint property_length, ulong key, int silent TSRMLS_DC)
155 {
156 #ifdef __GNUC__
157   if (__builtin_constant_p(property_name) && __builtin_constant_p(property_length)) {
158 	zval *result = zephir_fetch_property_this_quick(object, property_name, property_length, key, silent TSRMLS_CC);
159 	return result ? result : EG(uninitialized_zval_ptr);
160   }
161 #endif
162 
163   zval *result = zephir_fetch_property_this_quick(object, property_name, property_length, key, silent TSRMLS_CC);
164   return result ? result : EG(uninitialized_zval_ptr);
165 }
166 
zephir_fetch_nproperty_this(zval * object,const char * property_name,zend_uint property_length,int silent TSRMLS_DC)167 ZEPHIR_ATTR_NONNULL static inline zval* zephir_fetch_nproperty_this(zval *object, const char *property_name, zend_uint property_length, int silent TSRMLS_DC)
168 {
169 #ifdef __GNUC__
170   if (__builtin_constant_p(property_name) && __builtin_constant_p(property_length)) {
171 	return zephir_fetch_nproperty_this_quick(object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
172   }
173 #endif
174 
175   return zephir_fetch_nproperty_this_quick(object, property_name, property_length, zend_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
176 }
177 
zephir_fetch_property_this(zval * object,const char * property_name,zend_uint property_length,int silent TSRMLS_DC)178 ZEPHIR_ATTR_NONNULL static inline zval* zephir_fetch_property_this(zval *object, const char *property_name, zend_uint property_length, int silent TSRMLS_DC)
179 {
180 #ifdef __GNUC__
181   if (__builtin_constant_p(property_name) && __builtin_constant_p(property_length)) {
182 	return zephir_fetch_property_this_quick(object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
183   }
184 #endif
185 
186   return zephir_fetch_property_this_quick(object, property_name, property_length, zend_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
187 }
188 
189 #endif
190 
191 #define zephir_fetch_safe_class(destination, var) \
192   	{ \
193 		if (Z_TYPE_P(var) == IS_STRING) { \
194 			ZEPHIR_CPY_WRT(destination, var); \
195 		} else { \
196 			ZEPHIR_INIT_NVAR(destination); \
197 			ZVAL_STRING(destination, "<undefined class>", 1); \
198 		} \
199 	}
200