-
Notifications
You must be signed in to change notification settings - Fork 112
Expand file tree
/
Copy pathphp-functions.h
More file actions
248 lines (211 loc) · 5.91 KB
/
php-functions.h
File metadata and controls
248 lines (211 loc) · 5.91 KB
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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
// Compiler for PHP (aka KPHP)
// Copyright (c) 2020 LLC «V Kontakte»
// Distributed under the GPL v3 License, see LICENSE.notice.txt
#pragma once
#include <cctype>
#include <climits>
#include <cstdint>
#include <cstring>
#include <limits>
#include <type_traits>
#include "common/sanitizer.h"
constexpr int STRLEN_WARNING_FLAG = 1 << 30;
constexpr int STRLEN_OBJECT = -3;
constexpr int STRLEN_ERROR = -2;
constexpr int STRLEN_DYNAMIC = -1;
constexpr int STRLEN_UNKNOWN = STRLEN_ERROR;
constexpr int STRLEN_EMPTY = 0;
constexpr int STRLEN_BOOL = 1;
constexpr int STRLEN_BOOL_ = STRLEN_BOOL;
constexpr int STRLEN_INT32 = 11;
constexpr int STRLEN_INT64 = 20;
constexpr int STRLEN_INT = STRLEN_INT64;
constexpr int STRLEN_FLOAT = 21;
constexpr int STRLEN_ARRAY = 5;
constexpr int STRLEN_ARRAY_ = STRLEN_ARRAY | STRLEN_WARNING_FLAG;
constexpr int STRLEN_STRING = STRLEN_DYNAMIC;
constexpr int STRLEN_VAR = STRLEN_DYNAMIC;
constexpr int STRLEN_CLASS = STRLEN_DYNAMIC;
constexpr int STRLEN_VOID = STRLEN_ERROR;
constexpr int STRLEN_FUTURE = STRLEN_ERROR;
constexpr int STRLEN_FUTURE_QUEUE = STRLEN_ERROR;
constexpr int SIZEOF_STRING = 8;
constexpr int SIZEOF_ARRAY_ANY = 8;
constexpr int SIZEOF_MIXED = 16;
constexpr int SIZEOF_INSTANCE_ANY = 8;
constexpr int SIZEOF_OPTIONAL = 8;
constexpr int SIZEOF_FUTURE = 8;
constexpr int SIZEOF_FUTURE_QUEUE = 8;
constexpr int SIZEOF_REGEXP = 48;
constexpr int SIZEOF_UNKNOWN = 1;
class ExtraRefCnt {
public:
enum extra_ref_cnt_value {
// used as a reference counter for global constants,
// which are usually used as a default initialization of various variables;
// data is located in heap or data section and is readonly
for_global_const = 0x7ffffff0,
// used as a reference counter for instance_cache variables;
// data is located in shared memory;
// recursive array deletion is implied
for_instance_cache,
// used as a reference counter for the confdata variables;
// data is located in shared memory;
// either recursive or non-recursive array deletion is implied (depends on the context)
for_confdata,
// used as a reference counter for communication with job workers
// data is located in shared memory;
// hard reset without the destructor calls is implied
for_job_worker_communication
};
// wrapping this into a class helps avoid the global namespace pollution
ExtraRefCnt(extra_ref_cnt_value value) noexcept
: value_(value) {}
operator int() const noexcept {
return static_cast<int>(value_);
}
private:
extra_ref_cnt_value value_;
};
inline int64_t string_hash(const char* p, size_t l) __attribute__((always_inline)) ubsan_supp("alignment");
int64_t string_hash(const char* p, size_t l) {
constexpr uint64_t HASH_MUL = 1915239017;
uint64_t hash = 2147483648U;
size_t prev = (l & 3);
for (size_t i = 0; i < prev; i++) {
hash = hash * HASH_MUL + p[i];
}
const auto* p_uint = reinterpret_cast<const uint32_t*>(p + prev);
l >>= 2;
while (l-- > 0) {
hash = hash * HASH_MUL + *p_uint++;
}
const auto result = static_cast<int64_t>(hash);
// to ensure that there is no way to get the -9223372036854775808L during code generation
return (result != std::numeric_limits<int64_t>::min()) * result;
}
inline bool php_is_numeric(const char* s) {
while (isspace(*s)) {
s++;
}
if (*s == '+' || *s == '-') {
s++;
}
int l = 0;
while (*s >= '0' && *s <= '9') {
l++;
s++;
}
if (*s == '.') {
s++;
while (*s >= '0' && *s <= '9') {
l++;
s++;
}
}
if (l == 0) {
return false;
}
if (*s == 'e' || *s == 'E') {
s++;
if (*s == '+' || *s == '-') {
s++;
}
if (*s == '\0') {
return false;
}
while (*s >= '0' && *s <= '9') {
s++;
}
}
return *s == '\0';
}
inline bool php_is_int(const char* s, size_t l) __attribute__((always_inline));
bool php_is_int(const char* s, size_t l) {
if (l == 0) {
return false;
}
const uint8_t has_minus = s[0] == '-';
if (has_minus || s[0] == '+') {
s++;
l--;
if (s[0] < '1' || s[0] > '9') {
return false;
}
} else {
if (s[0] < '1' || s[0] > '9') {
return l == 1 && s[0] == '0';
}
}
constexpr size_t max_digits = std::numeric_limits<int64_t>::digits10 + 1;
if (l == 0 || l > max_digits) {
return false;
}
if (l == max_digits) {
uint64_t val = s[0] - '0';
for (size_t j = 1; j < l; j++) {
if (s[j] > '9' || s[j] < '0') {
return false;
}
val = val * 10 + s[j] - '0';
}
return val <= static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + has_minus;
}
for (size_t j = 1; j < l; j++) {
if (s[j] > '9' || s[j] < '0') {
return false;
}
}
return true;
}
inline bool php_try_to_int(const char* s, size_t l, int64_t* val) __attribute__((always_inline));
bool php_try_to_int(const char* s, size_t l, int64_t* val) {
int64_t mul = 1;
if (l == 0) {
return false;
}
if (s[0] == '-') {
mul = -1;
s++;
l--;
if (s[0] < '1' || s[0] > '9') {
return false;
}
} else {
if (s[0] < '1' || s[0] > '9') {
*val = 0;
return l == 1 && s[0] == '0';
}
}
constexpr size_t max_digits = std::numeric_limits<int64_t>::digits10 + 1;
if (l == 0 || l > max_digits) {
return false;
}
if (l == max_digits) {
*val = s[0] - '0';
for (size_t j = 1; j < l; j++) {
if (s[j] > '9' || s[j] < '0') {
return false;
}
*val = *val * 10 + s[j] - '0';
}
if (*val > 0 || (*val == std::numeric_limits<int64_t>::min() && mul == -1)) {
*val = *val * mul;
return true;
}
return false;
}
*val = s[0] - '0';
for (size_t j = 1; j < l; j++) {
if (s[j] > '9' || s[j] < '0') {
return false;
}
*val = *val * 10 + s[j] - '0';
}
*val *= mul;
return true;
}
template<class T>
inline constexpr int three_way_comparison(const T& lhs, const T& rhs) {
return lhs < rhs ? -1 : (rhs < lhs ? 1 : 0);
}