Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: third_party/protobuf/php/ext/google/protobuf/type_check.c

Issue 2495533002: third_party/protobuf: Update to HEAD (83d681ee2c) (Closed)
Patch Set: Make chrome settings proto generated file a component Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 #include <Zend/zend_operators.h>
32
33 #include "protobuf.h"
34 #include "utf8.h"
35
36 static zend_class_entry* util_type;
37 static const char int64_min_digits[] = "9223372036854775808";
38
39 ZEND_BEGIN_ARG_INFO_EX(arg_check_optional, 0, 0, 1)
40 ZEND_ARG_INFO(1, val)
41 ZEND_END_ARG_INFO()
42
43 ZEND_BEGIN_ARG_INFO_EX(arg_check_message, 0, 0, 2)
44 ZEND_ARG_INFO(1, val)
45 ZEND_ARG_INFO(0, klass)
46 ZEND_END_ARG_INFO()
47
48 ZEND_BEGIN_ARG_INFO_EX(arg_check_repeated, 0, 0, 2)
49 ZEND_ARG_INFO(1, val)
50 ZEND_ARG_INFO(0, type)
51 ZEND_ARG_INFO(0, klass)
52 ZEND_END_ARG_INFO()
53
54 static zend_function_entry util_methods[] = {
55 PHP_ME(Util, checkInt32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
56 PHP_ME(Util, checkUint32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
57 PHP_ME(Util, checkInt64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
58 PHP_ME(Util, checkUint64, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
59 PHP_ME(Util, checkEnum, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
60 PHP_ME(Util, checkFloat, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
61 PHP_ME(Util, checkDouble, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
62 PHP_ME(Util, checkBool, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
63 PHP_ME(Util, checkString, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
64 PHP_ME(Util, checkBytes, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
65 PHP_ME(Util, checkMessage, arg_check_message, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
66 PHP_ME(Util, checkRepeatedField, arg_check_repeated,
67 ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
68 ZEND_FE_END
69 };
70
71 void util_init(TSRMLS_D) {
72 zend_class_entry class_type;
73 INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBUtil",
74 util_methods);
75 util_type = zend_register_internal_class(&class_type TSRMLS_CC);
76 }
77
78 // -----------------------------------------------------------------------------
79 // Type checking/conversion.
80 // -----------------------------------------------------------------------------
81
82 // This is modified from is_numeric_string in zend_operators.h. The behavior of
83 // this function is the same as is_numeric_string, except that this takes
84 // int64_t as input instead of long.
85 static zend_uchar convert_numeric_string(
86 const char *str, int length, int64_t *lval, double *dval) {
87 const char *ptr;
88 int base = 10, digits = 0, dp_or_e = 0;
89 double local_dval = 0.0;
90 zend_uchar type;
91
92 if (length == 0) {
93 return IS_NULL;
94 }
95
96 while (*str == ' ' || *str == '\t' || *str == '\n' ||
97 *str == '\r' || *str == '\v' || *str == '\f') {
98 str++;
99 length--;
100 }
101 ptr = str;
102
103 if (*ptr == '-' || *ptr == '+') {
104 ptr++;
105 }
106
107 if (ZEND_IS_DIGIT(*ptr)) {
108 // Handle hex numbers
109 // str is used instead of ptr to disallow signs and keep old behavior.
110 if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
111 base = 16;
112 ptr += 2;
113 }
114
115 // Skip any leading 0s.
116 while (*ptr == '0') {
117 ptr++;
118 }
119
120 // Count the number of digits. If a decimal point/exponent is found,
121 // it's a double. Otherwise, if there's a dval or no need to check for
122 // a full match, stop when there are too many digits for a int64 */
123 for (type = IS_LONG;
124 !(digits >= MAX_LENGTH_OF_INT64 && dval);
125 digits++, ptr++) {
126 check_digits:
127 if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) {
128 continue;
129 } else if (base == 10) {
130 if (*ptr == '.' && dp_or_e < 1) {
131 goto process_double;
132 } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
133 const char *e = ptr + 1;
134
135 if (*e == '-' || *e == '+') {
136 ptr = e++;
137 }
138 if (ZEND_IS_DIGIT(*e)) {
139 goto process_double;
140 }
141 }
142 }
143 break;
144 }
145
146 if (base == 10) {
147 if (digits >= MAX_LENGTH_OF_INT64) {
148 dp_or_e = -1;
149 goto process_double;
150 }
151 } else if (!(digits < SIZEOF_INT64 * 2 ||
152 (digits == SIZEOF_INT64 * 2 && ptr[-digits] <= '7'))) {
153 if (dval) {
154 local_dval = zend_hex_strtod(str, &ptr);
155 }
156 type = IS_DOUBLE;
157 }
158 } else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {
159 process_double:
160 type = IS_DOUBLE;
161
162 // If there's a dval, do the conversion; else continue checking
163 // the digits if we need to check for a full match.
164 if (dval) {
165 local_dval = zend_strtod(str, &ptr);
166 } else if (dp_or_e != -1) {
167 dp_or_e = (*ptr++ == '.') ? 1 : 2;
168 goto check_digits;
169 }
170 } else {
171 return IS_NULL;
172 }
173 if (ptr != str + length) {
174 zend_error(E_NOTICE, "A non well formed numeric value encountered");
175 return 0;
176 }
177
178 if (type == IS_LONG) {
179 if (digits == MAX_LENGTH_OF_INT64 - 1) {
180 int cmp = strcmp(&ptr[-digits], int64_min_digits);
181
182 if (!(cmp < 0 || (cmp == 0 && *str == '-'))) {
183 if (dval) {
184 *dval = zend_strtod(str, NULL);
185 }
186
187 return IS_DOUBLE;
188 }
189 }
190 if (lval) {
191 *lval = strtoll(str, NULL, base);
192 }
193 return IS_LONG;
194 } else {
195 if (dval) {
196 *dval = local_dval;
197 }
198 return IS_DOUBLE;
199 }
200 }
201
202 #define CONVERT_TO_INTEGER(type) \
203 static bool convert_int64_to_##type(int64_t val, type##_t* type##_value) { \
204 *type##_value = (type##_t)val; \
205 return true; \
206 } \
207 \
208 static bool convert_double_to_##type(double val, type##_t* type##_value) { \
209 *type##_value = (type##_t)zend_dval_to_lval(val); \
210 return true; \
211 } \
212 \
213 static bool convert_string_to_##type(const char* val, int len, \
214 type##_t* type##_value) { \
215 int64_t lval; \
216 double dval; \
217 \
218 switch (convert_numeric_string(val, len, &lval, &dval)) { \
219 case IS_DOUBLE: { \
220 return convert_double_to_##type(dval, type##_value); \
221 } \
222 case IS_LONG: { \
223 return convert_int64_to_##type(lval, type##_value); \
224 } \
225 default: \
226 zend_error(E_USER_ERROR, \
227 "Given string value cannot be converted to integer."); \
228 return false; \
229 } \
230 } \
231 \
232 bool protobuf_convert_to_##type(zval* from, type##_t* to) { \
233 switch (Z_TYPE_P(from)) { \
234 case IS_LONG: { \
235 return convert_int64_to_##type(Z_LVAL_P(from), to); \
236 } \
237 case IS_DOUBLE: { \
238 return convert_double_to_##type(Z_DVAL_P(from), to); \
239 } \
240 case IS_STRING: { \
241 return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \
242 to); \
243 } \
244 default: { \
245 zend_error(E_USER_ERROR, \
246 "Given value cannot be converted to integer."); \
247 return false; \
248 } \
249 } \
250 return false; \
251 }
252
253 CONVERT_TO_INTEGER(int32);
254 CONVERT_TO_INTEGER(uint32);
255 CONVERT_TO_INTEGER(int64);
256 CONVERT_TO_INTEGER(uint64);
257
258 #undef CONVERT_TO_INTEGER
259
260 #define CONVERT_TO_FLOAT(type) \
261 static bool convert_int64_to_##type(int64_t val, type* type##_value) { \
262 *type##_value = (type)val; \
263 return true; \
264 } \
265 \
266 static bool convert_double_to_##type(double val, type* type##_value) { \
267 *type##_value = (type)val; \
268 return true; \
269 } \
270 \
271 static bool convert_string_to_##type(const char* val, int len, \
272 type* type##_value) { \
273 int64_t lval; \
274 double dval; \
275 \
276 switch (convert_numeric_string(val, len, &lval, &dval)) { \
277 case IS_DOUBLE: { \
278 *type##_value = (type)dval; \
279 return true; \
280 } \
281 case IS_LONG: { \
282 *type##_value = (type)lval; \
283 return true; \
284 } \
285 default: \
286 zend_error(E_USER_ERROR, \
287 "Given string value cannot be converted to integer."); \
288 return false; \
289 } \
290 } \
291 \
292 bool protobuf_convert_to_##type(zval* from, type* to) { \
293 switch (Z_TYPE_P(from)) { \
294 case IS_LONG: { \
295 return convert_int64_to_##type(Z_LVAL_P(from), to); \
296 } \
297 case IS_DOUBLE: { \
298 return convert_double_to_##type(Z_DVAL_P(from), to); \
299 } \
300 case IS_STRING: { \
301 return convert_string_to_##type(Z_STRVAL_P(from), Z_STRLEN_P(from), \
302 to); \
303 } \
304 default: { \
305 zend_error(E_USER_ERROR, \
306 "Given value cannot be converted to integer."); \
307 return false; \
308 } \
309 } \
310 return false; \
311 }
312
313 CONVERT_TO_FLOAT(float);
314 CONVERT_TO_FLOAT(double);
315
316 #undef CONVERT_TO_FLOAT
317
318 bool protobuf_convert_to_bool(zval* from, int8_t* to) {
319 switch (Z_TYPE_P(from)) {
320 case IS_BOOL:
321 *to = (int8_t)Z_BVAL_P(from);
322 break;
323 case IS_LONG:
324 *to = (int8_t)(Z_LVAL_P(from) != 0);
325 break;
326 case IS_DOUBLE:
327 *to = (int8_t)(Z_LVAL_P(from) != 0);
328 break;
329 case IS_STRING: {
330 char* strval = Z_STRVAL_P(from);
331
332 if (Z_STRLEN_P(from) == 0 ||
333 (Z_STRLEN_P(from) == 1 && Z_STRVAL_P(from)[0] == '0')) {
334 *to = 0;
335 } else {
336 *to = 1;
337 }
338 } break;
339 default: {
340 zend_error(E_USER_ERROR, "Given value cannot be converted to bool.");
341 return false;
342 }
343 }
344 return true;
345 }
346
347 bool protobuf_convert_to_string(zval* from) {
348 switch (Z_TYPE_P(from)) {
349 case IS_STRING: {
350 return true;
351 }
352 case IS_BOOL:
353 case IS_LONG:
354 case IS_DOUBLE: {
355 int use_copy;
356 zval tmp;
357 zend_make_printable_zval(from, &tmp, &use_copy);
358 ZVAL_COPY_VALUE(from, &tmp);
359 return true;
360 }
361 default:
362 zend_error(E_USER_ERROR, "Given value cannot be converted to string.");
363 return false;
364 }
365 }
366
367 // -----------------------------------------------------------------------------
368 // PHP Functions.
369 // -----------------------------------------------------------------------------
370
371 // The implementation of type checking for primitive fields is empty. This is
372 // because type checking is done when direct assigning message fields (e.g.,
373 // foo->a = 1). Functions defined here are place holders in generated code for
374 // pure PHP implementation (c extension and pure PHP share the same generated
375 // code).
376 #define PHP_TYPE_CHECK(type) \
377 PHP_METHOD(Util, check##type) {}
378
379 PHP_TYPE_CHECK(Int32)
380 PHP_TYPE_CHECK(Uint32)
381 PHP_TYPE_CHECK(Int64)
382 PHP_TYPE_CHECK(Uint64)
383 PHP_TYPE_CHECK(Enum)
384 PHP_TYPE_CHECK(Float)
385 PHP_TYPE_CHECK(Double)
386 PHP_TYPE_CHECK(Bool)
387 PHP_TYPE_CHECK(String)
388 PHP_TYPE_CHECK(Bytes)
389
390 #undef PHP_TYPE_CHECK
391
392 PHP_METHOD(Util, checkMessage) {
393 zval* val;
394 zend_class_entry* klass = NULL;
395 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!C", &val, &klass) ==
396 FAILURE) {
397 return;
398 }
399 if (val == NULL) {
400 RETURN_NULL();
401 }
402 if (!instanceof_function(Z_OBJCE_P(val), klass TSRMLS_CC)) {
403 zend_error(E_USER_ERROR, "Given value is not an instance of %s.",
404 klass->name);
405 return;
406 }
407 RETURN_ZVAL(val, 1, 0);
408 }
409
410 PHP_METHOD(Util, checkRepeatedField) {
411 zval* val;
412 long type;
413 const zend_class_entry* klass = NULL;
414 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|C", &val,
415 repeated_field_type, &type, &klass) == FAILURE) {
416 return;
417 }
418
419 RepeatedField *intern =
420 (RepeatedField *)zend_object_store_get_object(val TSRMLS_CC);
421 if (to_fieldtype(type) != intern->type) {
422 zend_error(E_USER_ERROR, "Incorrect repeated field type.");
423 return;
424 }
425 if (klass != NULL && intern->msg_ce != klass) {
426 zend_error(E_USER_ERROR, "Expect a repeated field of %s, but %s is given.",
427 klass->name, intern->msg_ce->name);
428 return;
429 }
430 }
OLDNEW
« no previous file with comments | « third_party/protobuf/php/ext/google/protobuf/test.php ('k') | third_party/protobuf/php/ext/google/protobuf/upb.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698