summaryrefslogtreecommitdiffstats
path: root/zend_resource.h
blob: 65a0e1dd3f7d232e600d963f575fd1d4a4a68bff (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
/*
  +----------------------------------------------------------------------+
  | Compatibility macros for different PHP versions                      |
  +----------------------------------------------------------------------+
  | Copyright (c) 2016 The PHP Group                                     |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.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: Adam Harvey <aharvey@php.net>                                |
  +----------------------------------------------------------------------+
*/

#ifndef _COMPAT_ZEND_RESOURCE_H
#define _COMPAT_ZEND_RESOURCE_H

/*
 * The PHP 5 and PHP 7 resource APIs use the same function names for mutually
 * incompatible functions, which is unfortunate. A simple version of the PHP 5
 * macro API can be implemented on top of the PHP 7 API, but not vice versa
 * (since, for example, zend_register_resource() in PHP 5 also sets the zval,
 * which is a separate action in PHP 7).
 *
 * Instead of using preprocessor trickery to try to mangle things into a sane
 * API, I've implemented a minimal API that supports basic resource handling
 * and delegates appropriately on both versions.
 *
 * Destructors should be registered using the normal
 * zend_register_list_destructors() or zend_register_list_destructors_ex()
 * functions. The destructor function should take a "zend_resource *" (there is
 * an appropriate typedef in the PHP 5 section to make this work); as only a
 * subset of fields are available across PHP versions, this should be treated
 * as this struct in effect:
 *
 * typedef struct {
 *   void *ptr;
 *   int   type;
 * } zend_resource;
 *
 * Accessing other fields will likely result in compilation errors and/or
 * segfaults.
 */

#include "zend_list.h"

/**
 * Deletes the resource.
 *
 * On PHP 5, this is equivalent to zend_list_delete(Z_LVAL_P(zv)).
 * On PHP 7, this is equivalent to zend_list_close(Z_RES_P(zv)).
 *
 * @param zv The IS_RESOURCE zval to delete.
 */
static zend_always_inline void compat_zend_delete_resource(const zval *zv TSRMLS_DC);

/**
 * Fetches the resource.
 *
 * This API does not support the default ID that's possible with the PHP 5
 * zend_fetch_resource() API, and will always set that value to -1.
 *
 * @param zv             The IS_RESOURCE zval to fetch.
 * @param rsrc_type_name The type name to use in error messages.
 * @param rsrc_type      The resource type ID.
 * @return A void pointer to the resource, which needs to be typecast, or NULL
 *         on error.
 */
static zend_always_inline void *compat_zend_fetch_resource(zval *zv, const char *rsrc_type_name, int rsrc_type TSRMLS_DC);

/**
 * Registers a new resource.
 *
 * @param zv        The zval to set to IS_RESOURCE with the new resource value.
 * @param ptr       A void pointer to the resource.
 * @param rsrc_type The resource type ID.
 */
static zend_always_inline void compat_zend_register_resource(zval *zv, void *ptr, int rsrc_type TSRMLS_DC);

#ifdef PHP_7
/*============================================================================*/

static zend_always_inline void compat_zend_delete_resource(const zval *zv TSRMLS_DC)
{
	if (IS_RESOURCE != Z_TYPE_P(zv)) {
		return;
	}

	zend_list_close(Z_RES_P(zv));
}

/*---------*/

static zend_always_inline void *compat_zend_fetch_resource(zval *zv, const char *rsrc_type_name, int rsrc_type TSRMLS_DC)
{
	if (IS_RESOURCE != Z_TYPE_P(zv)) {
		return NULL;
	}

	return zend_fetch_resource(Z_RES_P(zv), rsrc_type_name, rsrc_type);
}

/*---------*/

static zend_always_inline void compat_zend_register_resource(zval *zv, void *ptr, int rsrc_type TSRMLS_DC)
{
	ZVAL_RES(zv, zend_register_resource(ptr, rsrc_type));
}

#else
/*== PHP 5 ===================================================================*/

/* Used for destructors. */
typedef zend_rsrc_list_entry zend_resource;

/*---------*/

static zend_always_inline void compat_zend_delete_resource(const zval *zv TSRMLS_DC)
{
	if (IS_RESOURCE != Z_TYPE_P(zv)) {
		return;
	}

	zend_list_delete(Z_LVAL_P(zv));
}

/*---------*/

static zend_always_inline void *compat_zend_fetch_resource(zval *zv, const char *rsrc_type_name, int rsrc_type TSRMLS_DC)
{
#if ZEND_MODULE_API_NO >= 20100412
	return zend_fetch_resource(&zv TSRMLS_CC, -1, rsrc_type_name, NULL, 1, rsrc_type);
#else
	return zend_fetch_resource(&zv TSRMLS_CC, -1, (char *)rsrc_type_name, NULL, 1, rsrc_type);
#endif
}

/*---------*/

static zend_always_inline void compat_zend_register_resource(zval *zv, void *ptr, int rsrc_type TSRMLS_DC)
{
	ZEND_REGISTER_RESOURCE(zv, ptr, rsrc_type);
}

#endif /* PHP_7 */
/*============================================================================*/

#endif /* _COMPAT_ZEND_RESOURCE_H */