diff options
Diffstat (limited to 'php/ext/google/protobuf/type_check.c')
-rw-r--r-- | php/ext/google/protobuf/type_check.c | 169 |
1 files changed, 157 insertions, 12 deletions
diff --git a/php/ext/google/protobuf/type_check.c b/php/ext/google/protobuf/type_check.c index d12d0025..85f5051e 100644 --- a/php/ext/google/protobuf/type_check.c +++ b/php/ext/google/protobuf/type_check.c @@ -51,6 +51,13 @@ ZEND_BEGIN_ARG_INFO_EX(arg_check_repeated, 0, 0, 2) ZEND_ARG_INFO(0, klass) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arg_check_map, 0, 0, 3) + ZEND_ARG_INFO(1, val) + ZEND_ARG_INFO(0, key_type) + ZEND_ARG_INFO(0, value_type) + ZEND_ARG_INFO(0, klass) +ZEND_END_ARG_INFO() + static zend_function_entry util_methods[] = { PHP_ME(Util, checkInt32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(Util, checkUint32, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) @@ -63,6 +70,7 @@ static zend_function_entry util_methods[] = { PHP_ME(Util, checkString, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(Util, checkBytes, arg_check_optional, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(Util, checkMessage, arg_check_message, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkMapField, arg_check_map, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME(Util, checkRepeatedField, arg_check_repeated, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_FE_END @@ -317,9 +325,18 @@ CONVERT_TO_FLOAT(double); bool protobuf_convert_to_bool(zval* from, int8_t* to) { switch (Z_TYPE_P(from)) { +#if PHP_MAJOR_VERSION < 7 case IS_BOOL: *to = (int8_t)Z_BVAL_P(from); break; +#else + case IS_TRUE: + *to = 1; + break; + case IS_FALSE: + *to = 0; + break; +#endif case IS_LONG: *to = (int8_t)(Z_LVAL_P(from) != 0); break; @@ -349,12 +366,16 @@ bool protobuf_convert_to_string(zval* from) { case IS_STRING: { return true; } +#if PHP_MAJOR_VERSION < 7 case IS_BOOL: +#else + case IS_TRUE: + case IS_FALSE: +#endif case IS_LONG: case IS_DOUBLE: { - int use_copy; zval tmp; - zend_make_printable_zval(from, &tmp, &use_copy); + php_proto_zend_make_printable_zval(from, &tmp); ZVAL_COPY_VALUE(from, &tmp); return true; } @@ -407,24 +428,148 @@ PHP_METHOD(Util, checkMessage) { RETURN_ZVAL(val, 1, 0); } +void check_repeated_field(const zend_class_entry* klass, PHP_PROTO_LONG type, + zval* val, zval* return_value) { +#if PHP_MAJOR_VERSION >= 7 + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); + } +#endif + + TSRMLS_FETCH(); + if (Z_TYPE_P(val) == IS_ARRAY) { + HashTable* table = HASH_OF(val); + HashPosition pointer; + void* memory; + +#if PHP_MAJOR_VERSION < 7 + zval* repeated_field; + MAKE_STD_ZVAL(repeated_field); +#else + zval repeated_field; +#endif + + repeated_field_create_with_type(repeated_field_type, to_fieldtype(type), + klass, &repeated_field TSRMLS_CC); + + for (zend_hash_internal_pointer_reset_ex(table, &pointer); + php_proto_zend_hash_get_current_data_ex(table, (void**)&memory, + &pointer) == SUCCESS; + zend_hash_move_forward_ex(table, &pointer)) { + repeated_field_handlers->write_dimension( + CACHED_TO_ZVAL_PTR(repeated_field), NULL, + CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory) TSRMLS_CC); + } + + RETURN_ZVAL(CACHED_TO_ZVAL_PTR(repeated_field), 1, 1); + + } else if (Z_TYPE_P(val) == IS_OBJECT) { + if (!instanceof_function(Z_OBJCE_P(val), repeated_field_type TSRMLS_CC)) { + zend_error(E_USER_ERROR, "Given value is not an instance of %s.", + repeated_field_type->name); + return; + } + RepeatedField* intern = UNBOX(RepeatedField, val); + if (to_fieldtype(type) != intern->type) { + zend_error(E_USER_ERROR, "Incorrect repeated field type."); + return; + } + if (klass != NULL && intern->msg_ce != klass) { + zend_error(E_USER_ERROR, + "Expect a repeated field of %s, but %s is given.", klass->name, + intern->msg_ce->name); + return; + } + RETURN_ZVAL(val, 1, 0); + } else { + zend_error(E_USER_ERROR, "Incorrect repeated field type."); + return; + } +} + PHP_METHOD(Util, checkRepeatedField) { zval* val; - long type; + PHP_PROTO_LONG type; const zend_class_entry* klass = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol|C", &val, - repeated_field_type, &type, &klass) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl|C", &val, &type, + &klass) == FAILURE) { return; } + RETURN_ZVAL(val, 1, 0); +} - RepeatedField *intern = - (RepeatedField *)zend_object_store_get_object(val TSRMLS_CC); - if (to_fieldtype(type) != intern->type) { - zend_error(E_USER_ERROR, "Incorrect repeated field type."); +void check_map_field(const zend_class_entry* klass, PHP_PROTO_LONG key_type, + PHP_PROTO_LONG value_type, zval* val, zval* return_value) { +#if PHP_MAJOR_VERSION >= 7 + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); + } +#endif + + TSRMLS_FETCH(); + if (Z_TYPE_P(val) == IS_ARRAY) { + HashTable* table = Z_ARRVAL_P(val); + HashPosition pointer; + zval key; + void* value; + +#if PHP_MAJOR_VERSION < 7 + zval* map_field; + MAKE_STD_ZVAL(map_field); +#else + zval map_field; +#endif + + map_field_create_with_type(map_field_type, to_fieldtype(key_type), + to_fieldtype(value_type), klass, + &map_field TSRMLS_CC); + + for (zend_hash_internal_pointer_reset_ex(table, &pointer); + php_proto_zend_hash_get_current_data_ex(table, (void**)&value, + &pointer) == SUCCESS; + zend_hash_move_forward_ex(table, &pointer)) { + zend_hash_get_current_key_zval_ex(table, &key, &pointer); + map_field_handlers->write_dimension( + CACHED_TO_ZVAL_PTR(map_field), &key, + CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)value) TSRMLS_CC); + zval_dtor(&key); + } + + RETURN_ZVAL(CACHED_TO_ZVAL_PTR(map_field), 1, 1); + } else if (Z_TYPE_P(val) == IS_OBJECT) { + if (!instanceof_function(Z_OBJCE_P(val), map_field_type TSRMLS_CC)) { + zend_error(E_USER_ERROR, "Given value is not an instance of %s.", + map_field_type->name); + return; + } + Map* intern = UNBOX(Map, val); + if (to_fieldtype(key_type) != intern->key_type) { + zend_error(E_USER_ERROR, "Incorrect map field key type."); + return; + } + if (to_fieldtype(value_type) != intern->value_type) { + zend_error(E_USER_ERROR, "Incorrect map field value type."); + return; + } + if (klass != NULL && intern->msg_ce != klass) { + zend_error(E_USER_ERROR, "Expect a map field of %s, but %s is given.", + klass->name, intern->msg_ce->name); + return; + } + RETURN_ZVAL(val, 1, 0); + } else { + zend_error(E_USER_ERROR, "Incorrect map field type."); return; } - if (klass != NULL && intern->msg_ce != klass) { - zend_error(E_USER_ERROR, "Expect a repeated field of %s, but %s is given.", - klass->name, intern->msg_ce->name); +} + +PHP_METHOD(Util, checkMapField) { + zval* val; + PHP_PROTO_LONG key_type, value_type; + const zend_class_entry* klass = NULL; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zll|C", &val, &key_type, + &value_type, &klass) == FAILURE) { return; } + RETURN_ZVAL(val, 1, 0); } |