summaryrefslogtreecommitdiff
path: root/ext/satellite/class.h
blob: 7b69e3447d8c94be0640020f6b59e8be5d69b3e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
   +----------------------------------------------------------------------+
   | PHP version 4.0                                                      |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2001 The PHP Group                                |
   +----------------------------------------------------------------------+
   | This source file is subject to version 2.02 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available at through the world-wide-web at                           |
   | http://www.php.net/license/2_02.txt.                                 |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: David Eriksson <david@2good.com>                            |
   +----------------------------------------------------------------------+
 */

/*
 * $Id$
 * vim: syntax=c tabstop=2 shiftwidth=2
 */

/* -----------------------------------------------------------------------
 * 
 * Macros and things to simplify making PHP classes
 *
 * -----------------------------------------------------------------------
 */
#ifndef __orbit_class_h__
#define __orbit_class_h__

#include <zend.h>
#include <zend_API.h>

#define CONSTRUCTOR		1
#define DESTRUCTOR		2
#define CALL_FUNCTION	4
#define PUT_PROPERTY	8
#define GET_PROPERTY	16
#define NO_FUNCTIONS		(CONSTRUCTOR|DESTRUCTOR|PUT_PROPERTY|GET_PROPERTY)
#define NO_PROPERTIES		(CONSTRUCTOR|DESTRUCTOR|CALL_FUNCTION)

/*
 * sorry everyone but the constructor itself has to allocate the data
 * structure for member variables!
 *
 * it also has to deallocate this in the destructor...
 */
typedef zend_bool (*Class_Constructor)
	(void ** ppObject, int parameterCount, zval ** ppParameters);
typedef zend_bool (*Class_Destructor)
	(void * pObject);
typedef zend_bool (*Class_CallFunction)
	(void * pObject, const char * pFunctionName, int parameterCount, zval ** ppParameters, zval * pReturnValue);
typedef zend_bool (*Class_PutProperty)
	(void * pObject, const char * pPropertyName, const zval * pValue);
typedef zend_bool (*Class_GetProperty)
	(void * pObject, const char * pPropertyName, zval * pReturnValue);

	/* put/get data connected to php object */
void orbit_save_data(zval * pPhpObject, int type, void * pData);
void * orbit_retrieve_data(const zval * pPhpObject, int type);

void orbit_class_function_call(
		zend_class_entry * pClass,
		int dataType,
		zend_property_reference *pPropertyReference, 
		Class_Constructor pConstructor, 
		Class_CallFunction pCallFunction,
		INTERNAL_FUNCTION_PARAMETERS);

/*
 * use this macro in the header file
 */
#define DECLARE_CLASS(name) \
typedef struct _##name  name##;	\
zend_bool name##_Init(int module_number);	\
void name##_SaveData(zval * pPhpObject, ##name * pData);\
##name * name##_RetrieveData(const zval * pPhpObject);\
zend_bool name##_PutProperty(##name * pObject, const char * pPropertyName, const zval * pValue);\
zend_bool name##_GetProperty(##name * pObject, const char * pPropertyName, zval * pReturnValue);\
/* end small macro */

/*
 * Wrapper for a function call
 */
#define IMPLEMENT_FUNCTION_CALL(name, flags)\
static void _##name##_FunctionCall(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference * pPropertyReference)	\
{	\
	orbit_class_function_call(	\
			&name##_class_entry,	\
			name##_data_type,	\
			pPropertyReference,	\
			((flags) & CONSTRUCTOR) ? 	(Class_Constructor)name##_Constructor : NULL,	\
			((flags) & CALL_FUNCTION) ? (Class_CallFunction)name##_CallFunction : NULL,	\
			INTERNAL_FUNCTION_PARAM_PASSTHRU\
			);\
}

/*
 * wrapper for PutProperty
 */
#define IMPLEMENT_PUT_PROPERTY(name, flags)\
static int  _##name##_PutProperty(zend_property_reference * pPropertyReference, zval * pValue)\
{\
	int result = 0;\
	if ((flags) & PUT_PROPERTY)\
	{\
		##name * p_data = (##name *)orbit_retrieve_data(pPropertyReference->object, name##_data_type);\
		/* get variable name element */\
		zend_overloaded_element * p_attribute_element = \
			(zend_overloaded_element *)pPropertyReference->elements_list->tail->data;\
		/* get variable name */\
		char * p_attribute_name = p_attribute_element->element.value.str.val;\
		if (p_data)\
			result = ##name##_PutProperty(p_data, p_attribute_name, pValue) ? SUCCESS : FAILURE;\
		else\
			result = FAILURE;\
	}\
	else\
	{\
		zend_error(E_WARNING, "(Satellite) Can't set members in class");\
	}\
	return result;\
}

/*
 * wrapper for GetProperty
 */
#define IMPLEMENT_GET_PROPERTY(name, flags)\
static zval _##name##_GetProperty(zend_property_reference * pPropertyReference)\
{\
	zval value;\
	ZVAL_NULL(&value);\
	if ((flags) & GET_PROPERTY)\
	{\
		##name * p_data = (##name *)orbit_retrieve_data(pPropertyReference->object, name##_data_type);\
		/* get variable name element */\
		zend_overloaded_element * p_attribute_element = \
			(zend_overloaded_element *)pPropertyReference->elements_list->tail->data;\
		/* get variable name */\
		char * p_attribute_name = p_attribute_element->element.value.str.val;\
		if (p_data)\
			##name##_GetProperty(p_data, p_attribute_name, &value);\
	}\
	else\
	{\
		zend_error(E_WARNING, "(Satellite) Can't get members in class");\
	}\
	return value;\
}


#define IMPLEMENT_INIT_EX(name, flags, functions, functioncall, getproperty, putproperty)\
zend_bool name##_Init(int module_number)	\
{	\
	/* register data type */	\
	name##_data_type = register_list_destructors(name##_Destructor, NULL);	\
\
	/* register class */	\
	INIT_OVERLOADED_CLASS_ENTRY(	\
		name##_class_entry,			\
		#name,									\
		functions, 									\
		functioncall,	\
		getproperty, 	\
		putproperty		\
		);	\
\
	zend_register_internal_class(&name##_class_entry TSRMLS_CC);\
	return TRUE;\
}

/*
 * initialize object, must be called from PHP_MINIT_FUNCTION etc
 */
#define IMPLEMENT_INIT(name, flags) \
IMPLEMENT_INIT_EX(name, flags, NULL, _##name##_FunctionCall, _##name##_GetProperty, _##name##_PutProperty)


/* 
 * functions to save and retrieve data for the object
 */
#define IMPLEMENT_DATA_HELPERS(name, flags)\
void name##_SaveData(zval * pPhpObject, ##name * pData)\
{\
	orbit_save_data(pPhpObject, name##_data_type, pData);\
}\
##name * name##_RetrieveData(const zval * pPhpObject)\
{\
	return (##name *)orbit_retrieve_data(pPhpObject, name##_data_type);\
}

/*
 * static declarations for class
 */
#define IMPLEMENT_DECLARATIONS(name, flags)\
static zend_bool name##_Constructor(##name ** ppObject, int parameterCount, const zval ** ppParameters);\
static zend_bool name##_Destructor(##name * pObject);\
static zend_bool name##_CallFunction(##name * pObject, const char * pFunctionName, int parameterCount, const zval ** ppParameters, zval * pResult); \
\
static int name##_data_type = 0;	\
static zend_class_entry name##_class_entry;

/*
 * use this macro in the source file
 */
#define IMPLEMENT_CLASS(name, flags)	\
IMPLEMENT_DECLARATIONS(name, flags)		\
IMPLEMENT_FUNCTION_CALL(name, flags)	\
IMPLEMENT_PUT_PROPERTY(name, flags)		\
IMPLEMENT_GET_PROPERTY(name, flags)		\
IMPLEMENT_INIT(name, flags)						\
IMPLEMENT_DATA_HELPERS(name, flags)	


#endif /* __orbit_class_h__ */