From ecca6ea95d56a6f70ff7b223ec3f904758acc8b1 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Fri, 30 Jun 2017 12:14:09 -0700 Subject: Add json encode/decode for php. (#3226) * Add json encode/decode for php. * Fix php conformance test on 32-bit machines. * Fix conformance test for c extension. * Fix comments --- php/tests/map_field_test.php | 277 +------------------------------------------ 1 file changed, 1 insertion(+), 276 deletions(-) (limited to 'php/tests/map_field_test.php') diff --git a/php/tests/map_field_test.php b/php/tests/map_field_test.php index 2fda9135..c5d21264 100644 --- a/php/tests/map_field_test.php +++ b/php/tests/map_field_test.php @@ -58,42 +58,6 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { $this->assertEquals(0, count($arr)); } - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testInt32SetStringKeyFail() - { - $arr = new MapField(GPBType::INT32, GPBType::INT32); - $arr ['abc']= 0; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testInt32SetStringValueFail() - { - $arr = new MapField(GPBType::INT32, GPBType::INT32); - $arr [0]= 'abc'; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testInt32SetMessageKeyFail() - { - $arr = new MapField(GPBType::INT32, GPBType::INT32); - $arr [new TestMessage_Sub()]= 0; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testInt32SetMessageValueFail() - { - $arr = new MapField(GPBType::INT32, GPBType::INT32); - $arr [0]= new TestMessage_Sub(); - } - ######################################################### # Test uint32 field. ######################################################### @@ -159,42 +123,6 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { $this->assertEquals(0, count($arr)); } - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testUint32SetStringKeyFail() - { - $arr = new MapField(GPBType::UINT32, GPBType::UINT32); - $arr ['abc']= 0; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testUint32SetStringValueFail() - { - $arr = new MapField(GPBType::UINT32, GPBType::UINT32); - $arr [0]= 'abc'; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testUint32SetMessageKeyFail() - { - $arr = new MapField(GPBType::UINT32, GPBType::UINT32); - $arr [new TestMessage_Sub()]= 0; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testUint32SetMessageValueFail() - { - $arr = new MapField(GPBType::UINT32, GPBType::UINT32); - $arr [0]= new TestMessage_Sub(); - } - ######################################################### # Test int64 field. ######################################################### @@ -252,42 +180,6 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { $this->assertEquals(0, count($arr)); } - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testInt64SetStringKeyFail() - { - $arr = new MapField(GPBType::INT64, GPBType::INT64); - $arr ['abc']= 0; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testInt64SetStringValueFail() - { - $arr = new MapField(GPBType::INT64, GPBType::INT64); - $arr [0]= 'abc'; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testInt64SetMessageKeyFail() - { - $arr = new MapField(GPBType::INT64, GPBType::INT64); - $arr [new TestMessage_Sub()]= 0; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testInt64SetMessageValueFail() - { - $arr = new MapField(GPBType::INT64, GPBType::INT64); - $arr [0]= new TestMessage_Sub(); - } - ######################################################### # Test uint64 field. ######################################################### @@ -339,42 +231,6 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { $this->assertEquals(0, count($arr)); } - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testUint64SetStringKeyFail() - { - $arr = new MapField(GPBType::UINT64, GPBType::UINT64); - $arr ['abc']= 0; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testUint64SetStringValueFail() - { - $arr = new MapField(GPBType::UINT64, GPBType::UINT64); - $arr [0]= 'abc'; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testUint64SetMessageKeyFail() - { - $arr = new MapField(GPBType::UINT64, GPBType::UINT64); - $arr [new TestMessage_Sub()]= 0; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testUint64SetMessageValueFail() - { - $arr = new MapField(GPBType::UINT64, GPBType::UINT64); - $arr [0]= new TestMessage_Sub(); - } - ######################################################### # Test float field. ######################################################### @@ -397,24 +253,6 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { $this->assertEquals(4, count($arr)); } - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testFloatSetStringValueFail() - { - $arr = new MapField(GPBType::INT64, GPBType::FLOAT); - $arr [0]= 'abc'; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testFloatSetMessageValueFail() - { - $arr = new MapField(GPBType::INT64, GPBType::FLOAT); - $arr [0]= new TestMessage_Sub(); - } - ######################################################### # Test double field. ######################################################### @@ -437,24 +275,6 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { $this->assertEquals(4, count($arr)); } - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testDoubleSetStringValueFail() - { - $arr = new MapField(GPBType::INT64, GPBType::DOUBLE); - $arr [0]= 'abc'; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testDoubleSetMessageValueFail() - { - $arr = new MapField(GPBType::INT64, GPBType::DOUBLE); - $arr [0]= new TestMessage_Sub(); - } - ######################################################### # Test bool field. ######################################################### @@ -515,24 +335,6 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { $this->assertEquals(0, count($arr)); } - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testBoolSetMessageKeyFail() - { - $arr = new MapField(GPBType::BOOL, GPBType::BOOL); - $arr [new TestMessage_Sub()]= true; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testBoolSetMessageValueFail() - { - $arr = new MapField(GPBType::BOOL, GPBType::BOOL); - $arr [true]= new TestMessage_Sub(); - } - ######################################################### # Test string field. ######################################################### @@ -566,42 +368,6 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { $this->assertEquals(0, count($arr)); } - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testStringSetInvalidUTF8KeyFail() - { - $arr = new MapField(GPBType::STRING, GPBType::STRING); - $arr[hex2bin("ff")]= 'abc'; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testStringSetInvalidUTF8ValueFail() - { - $arr = new MapField(GPBType::STRING, GPBType::STRING); - $arr ['abc']= hex2bin("ff"); - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testStringSetMessageKeyFail() - { - $arr = new MapField(GPBType::STRING, GPBType::STRING); - $arr [new TestMessage_Sub()]= 'abc'; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testStringSetMessageValueFail() - { - $arr = new MapField(GPBType::STRING, GPBType::STRING); - $arr ['abc']= new TestMessage_Sub(); - } - ######################################################### # Test message field. ######################################################### @@ -619,47 +385,6 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { $this->assertEquals(1, count($arr)); } - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testMessageSetIntValueFail() - { - $arr = - new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class); - $arr[0] = 0; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testMessageSetStringValueFail() - { - $arr = - new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class); - $arr[0] = 'abc'; - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testMessageSetOtherMessageValueFail() - { - $arr = - new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class); - $arr[0] = new TestMessage_Sub(); - } - - /** - * @expectedException PHPUnit_Framework_Error - */ - public function testMessageSetNullFail() - { - $arr = - new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class); - $null = NULL; - $arr[0] = $null; - } - ######################################################### # Test memory leak ######################################################### @@ -669,7 +394,7 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { // { // $arr = new MapField(GPBType::INT32, // GPBType::MESSAGE, TestMessage::class); - // $arr [0]= new TestMessage; + // $arr[0] = new TestMessage; // $arr[0]->SetMapRecursive($arr); // // Clean up memory before test. -- cgit v1.2.3 From 3a0382e9076bdbb7c764080c92f3c2324d852be7 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Thu, 13 Jul 2017 11:21:03 -0700 Subject: Add map iterator for c extension (#3350) --- php/ext/google/protobuf/map.c | 93 ++++++++++++++++++++++- php/ext/google/protobuf/protobuf.c | 2 + php/ext/google/protobuf/protobuf.h | 15 +++- php/ext/google/protobuf/storage.c | 13 ++++ php/src/Google/Protobuf/Internal/MapFieldIter.php | 5 +- php/tests/map_field_test.php | 34 +++++++++ 6 files changed, 157 insertions(+), 5 deletions(-) (limited to 'php/tests/map_field_test.php') diff --git a/php/ext/google/protobuf/map.c b/php/ext/google/protobuf/map.c index a5d48446..4a524864 100644 --- a/php/ext/google/protobuf/map.c +++ b/php/ext/google/protobuf/map.c @@ -143,6 +143,7 @@ static zend_function_entry map_field_methods[] = { PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) PHP_ME(MapField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC) PHP_ME(MapField, count, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapField, getIterator, arginfo_void, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -156,7 +157,10 @@ static void map_field_write_dimension(zval *object, zval *key, // ----------------------------------------------------------------------------- zend_class_entry* map_field_type; +zend_class_entry* map_field_iter_type; + zend_object_handlers* map_field_handlers; +zend_object_handlers* map_field_iter_handlers; static void map_begin_internal(Map *map, MapIter *iter) { iter->self = map; @@ -231,8 +235,8 @@ PHP_PROTO_OBJECT_CREATE_END(Map, map_field) // Init class entry. PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\MapField", Map, map_field) -zend_class_implements(map_field_type TSRMLS_CC, 2, spl_ce_ArrayAccess, - spl_ce_Countable); +zend_class_implements(map_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess, + zend_ce_aggregate, spl_ce_Countable); map_field_handlers->write_dimension = map_field_write_dimension; map_field_handlers->get_gc = map_field_get_gc; PHP_PROTO_INIT_CLASS_END @@ -444,6 +448,15 @@ PHP_METHOD(MapField, count) { RETURN_LONG(upb_strtable_count(&intern->table)); } +PHP_METHOD(MapField, getIterator) { + CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(return_value, + map_field_iter_type); + + Map *intern = UNBOX(Map, getThis()); + MapIter *iter = UNBOX(MapIter, return_value); + map_begin(getThis(), iter TSRMLS_CC); +} + // ----------------------------------------------------------------------------- // Map Iterator // ----------------------------------------------------------------------------- @@ -470,3 +483,79 @@ upb_value map_iter_value(MapIter *iter, int *len) { *len = native_slot_size(iter->self->value_type); return upb_strtable_iter_value(&iter->it); } + +// ----------------------------------------------------------------------------- +// MapFieldIter methods +// ----------------------------------------------------------------------------- +static zend_function_entry map_field_iter_methods[] = { + PHP_ME(MapFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// MapFieldIter creation/desctruction +// ----------------------------------------------------------------------------- + +// Define object free method. +PHP_PROTO_OBJECT_FREE_START(MapIter, map_field_iter) +PHP_PROTO_OBJECT_FREE_END + +PHP_PROTO_OBJECT_DTOR_START(MapIter, map_field_iter) +PHP_PROTO_OBJECT_DTOR_END + +// Define object create method. +PHP_PROTO_OBJECT_CREATE_START(MapIter, map_field_iter) +intern->self = NULL; +PHP_PROTO_OBJECT_CREATE_END(MapIter, map_field_iter) + +// Init class entry. +PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\MapFieldIter", + MapIter, map_field_iter) +zend_class_implements(map_field_iter_type TSRMLS_CC, 1, zend_ce_iterator); +PHP_PROTO_INIT_CLASS_END + +// ----------------------------------------------------------------------------- +// PHP MapFieldIter Methods +// ----------------------------------------------------------------------------- + +PHP_METHOD(MapFieldIter, rewind) { + MapIter *intern = UNBOX(MapIter, getThis()); + map_begin_internal(intern->self, intern); +} + +PHP_METHOD(MapFieldIter, current) { + MapIter *intern = UNBOX(MapIter, getThis()); + Map *map_field = intern->self; + + int value_length = 0; + upb_value value = map_iter_value(intern, &value_length); + + void* mem = upb_value_memory(&value); + native_slot_get_by_array(map_field->value_type, mem, + ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC); +} + +PHP_METHOD(MapFieldIter, key) { + MapIter *intern = UNBOX(MapIter, getThis()); + Map *map_field = intern->self; + + int key_length = 0; + const char* key = map_iter_key(intern, &key_length); + + native_slot_get_by_map_key(map_field->key_type, key, key_length, + ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC); +} + +PHP_METHOD(MapFieldIter, next) { + MapIter *intern = UNBOX(MapIter, getThis()); + map_next(intern); +} + +PHP_METHOD(MapFieldIter, valid) { + MapIter *intern = UNBOX(MapIter, getThis()); + RETURN_BOOL(!map_done(intern)); +} diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c index 6a848b27..5de9cfe9 100644 --- a/php/ext/google/protobuf/protobuf.c +++ b/php/ext/google/protobuf/protobuf.c @@ -189,6 +189,7 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) { static PHP_MINIT_FUNCTION(protobuf) { map_field_init(TSRMLS_C); + map_field_iter_init(TSRMLS_C); repeated_field_init(TSRMLS_C); repeated_field_iter_init(TSRMLS_C); gpb_type_init(TSRMLS_C); @@ -206,6 +207,7 @@ static PHP_MSHUTDOWN_FUNCTION(protobuf) { PEFREE(repeated_field_handlers); PEFREE(repeated_field_iter_handlers); PEFREE(map_field_handlers); + PEFREE(map_field_iter_handlers); return 0; } diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index 406a09a5..684a9c50 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -373,6 +373,7 @@ struct MessageLayout; struct RepeatedField; struct RepeatedFieldIter; struct Map; +struct MapIter; struct Oneof; typedef struct DescriptorPool DescriptorPool; @@ -385,6 +386,7 @@ typedef struct MessageLayout MessageLayout; typedef struct RepeatedField RepeatedField; typedef struct RepeatedFieldIter RepeatedFieldIter; typedef struct Map Map; +typedef struct MapIter MapIter; typedef struct Oneof Oneof; // ----------------------------------------------------------------------------- @@ -400,6 +402,7 @@ void enum_descriptor_init(TSRMLS_D); void descriptor_pool_init(TSRMLS_D); void gpb_type_init(TSRMLS_D); void map_field_init(TSRMLS_D); +void map_field_iter_init(TSRMLS_D); void repeated_field_init(TSRMLS_D); void repeated_field_iter_init(TSRMLS_D); void util_init(TSRMLS_D); @@ -659,6 +662,7 @@ void native_slot_get_default(upb_fieldtype_t type, // ----------------------------------------------------------------------------- extern zend_object_handlers* map_field_handlers; +extern zend_object_handlers* map_field_iter_handlers; PHP_PROTO_WRAP_OBJECT_START(Map) upb_fieldtype_t key_type; @@ -667,10 +671,10 @@ PHP_PROTO_WRAP_OBJECT_START(Map) upb_strtable table; PHP_PROTO_WRAP_OBJECT_END -typedef struct { +PHP_PROTO_WRAP_OBJECT_START(MapIter) Map* self; upb_strtable_iter it; -} MapIter; +PHP_PROTO_WRAP_OBJECT_END void map_begin(zval* self, MapIter* iter TSRMLS_DC); void map_next(MapIter* iter); @@ -709,6 +713,13 @@ PHP_METHOD(MapField, offsetGet); PHP_METHOD(MapField, offsetSet); PHP_METHOD(MapField, offsetUnset); PHP_METHOD(MapField, count); +PHP_METHOD(MapField, getIterator); + +PHP_METHOD(MapFieldIter, rewind); +PHP_METHOD(MapFieldIter, current); +PHP_METHOD(MapFieldIter, key); +PHP_METHOD(MapFieldIter, next); +PHP_METHOD(MapFieldIter, valid); // ----------------------------------------------------------------------------- // Repeated Field. diff --git a/php/ext/google/protobuf/storage.c b/php/ext/google/protobuf/storage.c index 6318f88c..29a3db86 100644 --- a/php/ext/google/protobuf/storage.c +++ b/php/ext/google/protobuf/storage.c @@ -355,6 +355,19 @@ void native_slot_get_by_array(upb_fieldtype_t type, const void* memory, } } +void native_slot_get_by_map_key(upb_fieldtype_t type, const void* memory, + int length, CACHED_VALUE* cache TSRMLS_DC) { + switch (type) { + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: { + PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), memory, length, 1); + return; + } + default: + native_slot_get(type, memory, cache TSRMLS_CC); + } +} + void native_slot_get_default(upb_fieldtype_t type, CACHED_VALUE* cache TSRMLS_DC) { switch (type) { diff --git a/php/src/Google/Protobuf/Internal/MapFieldIter.php b/php/src/Google/Protobuf/Internal/MapFieldIter.php index cb707955..88e6c8b2 100644 --- a/php/src/Google/Protobuf/Internal/MapFieldIter.php +++ b/php/src/Google/Protobuf/Internal/MapFieldIter.php @@ -91,9 +91,12 @@ class MapFieldIter implements \Iterator public function key() { $key = key($this->container); - // PHP associative array stores bool as integer for key. if ($this->key_type === GPBType::BOOL) { + // PHP associative array stores bool as integer for key. return boolval($key); + } elseif ($this->key_type === GPBType::STRING) { + // PHP associative array stores int string as int for key. + return strval($key); } else { return $key; } diff --git a/php/tests/map_field_test.php b/php/tests/map_field_test.php index c5d21264..120b1bde 100644 --- a/php/tests/map_field_test.php +++ b/php/tests/map_field_test.php @@ -56,6 +56,23 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { unset($arr['3.1']); unset($arr[MAX_INT32_STRING]); $this->assertEquals(0, count($arr)); + + // Test foreach. + $arr = new MapField(GPBType::INT32, GPBType::INT32); + for ($i = 0; $i < 3; $i++) { + $arr[$i] = $i; + } + $i = 0; + $arr_test = []; + foreach ($arr as $key => $val) { + $this->assertSame($key, $val); + $arr_test[] = $key; + $i++; + } + $this->assertTrue(isset($arr_test[0])); + $this->assertTrue(isset($arr_test[1])); + $this->assertTrue(isset($arr_test[2])); + $this->assertSame(3, $i); } ######################################################### @@ -366,6 +383,23 @@ class MapFieldTest extends PHPUnit_Framework_TestCase { $this->assertEquals(1, count($arr)); unset($arr[True]); $this->assertEquals(0, count($arr)); + + // Test foreach. + $arr = new MapField(GPBType::STRING, GPBType::STRING); + for ($i = 0; $i < 3; $i++) { + $arr[$i] = $i; + } + $i = 0; + $arr_test = []; + foreach ($arr as $key => $val) { + $this->assertSame($key, $val); + $arr_test[] = $key; + $i++; + } + $this->assertTrue(isset($arr_test['0'])); + $this->assertTrue(isset($arr_test['1'])); + $this->assertTrue(isset($arr_test['2'])); + $this->assertSame(3, $i); } ######################################################### -- cgit v1.2.3