summaryrefslogtreecommitdiff
path: root/src/sp_php_compat.h
blob: 992c3e2243535512bbaf5633d8eba89fcca1cce1 (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
#if PHP_VERSION_ID < 80000

// copied from PHP 8.0.9 sources
ZEND_API zend_string *zend_string_concat2(
	const char *str1, size_t str1_len,
	const char *str2, size_t str2_len);

#define ZEND_HASH_REVERSE_FOREACH_KEY_PTR(ht, _h, _key, _ptr) \
	ZEND_HASH_REVERSE_FOREACH(ht, 0); \
	_h = _p->h; \
	_key = _p->key; \
	_ptr = Z_PTR_P(_z);

#endif

#if PHP_VERSION_ID < 70300

// copied from PHP 7.4.22 sources

static zend_always_inline uint32_t zend_gc_delref(zend_refcounted_h *p) {
	ZEND_ASSERT(p->refcount > 0);
	// ZEND_RC_MOD_CHECK(p);
	return --(p->refcount);
}
#define GC_DELREF(p)				zend_gc_delref(&(p)->gc)

static zend_always_inline void zend_string_release_ex(zend_string *s, int persistent)
{
	if (!ZSTR_IS_INTERNED(s)) {
		if (GC_DELREF(s) == 0) {
			if (persistent) {
				ZEND_ASSERT(GC_FLAGS(s) & IS_STR_PERSISTENT);
				free(s);
			} else {
				ZEND_ASSERT(!(GC_FLAGS(s) & IS_STR_PERSISTENT));
				efree(s);
			}
		}
	}
}

static zend_always_inline void zend_string_efree(zend_string *s)
{
	ZEND_ASSERT(!ZSTR_IS_INTERNED(s));
	ZEND_ASSERT(GC_REFCOUNT(s) <= 1);
	ZEND_ASSERT(!(GC_FLAGS(s) & IS_STR_PERSISTENT));
	efree(s);
}

#endif

#if PHP_VERSION_ID < 70200

#undef ZEND_HASH_REVERSE_FOREACH

// copied from PHP 7.4.22 sources

#define ZEND_HASH_REVERSE_FOREACH(_ht, indirect) do { \
	HashTable *__ht = (_ht); \
	uint32_t _idx = __ht->nNumUsed; \
	Bucket *_p = __ht->arData + _idx; \
	zval *_z; \
	for (_idx = __ht->nNumUsed; _idx > 0; _idx--) { \
		_p--; \
		_z = &_p->val; \
		if (indirect && Z_TYPE_P(_z) == IS_INDIRECT) { \
			_z = Z_INDIRECT_P(_z); \
		} \
		if (UNEXPECTED(Z_TYPE_P(_z) == IS_UNDEF)) continue;


#define ZEND_HASH_FOREACH_END_DEL() \
			__ht->nNumOfElements--; \
			do { \
				uint32_t j = HT_IDX_TO_HASH(_idx - 1); \
				uint32_t nIndex = _p->h | __ht->nTableMask; \
				uint32_t i = HT_HASH(__ht, nIndex); \
				if (UNEXPECTED(j != i)) { \
					Bucket *prev = HT_HASH_TO_BUCKET(__ht, i); \
					while (Z_NEXT(prev->val) != j) { \
						i = Z_NEXT(prev->val); \
						prev = HT_HASH_TO_BUCKET(__ht, i); \
					} \
					Z_NEXT(prev->val) = Z_NEXT(_p->val); \
				} else { \
					HT_HASH(__ht, nIndex) = Z_NEXT(_p->val); \
				} \
			} while (0); \
		} \
		__ht->nNumUsed = _idx; \
	} while (0)

#endif