Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
190b5270
Commit
190b5270
authored
Apr 19, 2017
by
Paul Yang
Committed by
GitHub
Apr 19, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make PHP c extension work with PHP7 (#2951)
parent
43234828
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
1829 additions
and
1125 deletions
+1829
-1125
.gitignore
.gitignore
+3
-0
.travis.yml
.travis.yml
+1
-0
failure_list_php_c.txt
conformance/failure_list_php_c.txt
+10
-18
pull_request_32.sh
jenkins/buildcmds/pull_request_32.sh
+1
-1
Dockerfile
jenkins/docker/Dockerfile
+24
-7
Dockerfile
jenkins/docker32/Dockerfile
+18
-1
array.c
php/ext/google/protobuf/array.c
+156
-155
def.c
php/ext/google/protobuf/def.c
+161
-168
encode_decode.c
php/ext/google/protobuf/encode_decode.c
+329
-164
map.c
php/ext/google/protobuf/map.c
+78
-93
message.c
php/ext/google/protobuf/message.c
+103
-111
protobuf.c
php/ext/google/protobuf/protobuf.c
+46
-11
protobuf.h
php/ext/google/protobuf/protobuf.h
+398
-78
storage.c
php/ext/google/protobuf/storage.c
+323
-203
type_check.c
php/ext/google/protobuf/type_check.c
+60
-25
MapField.php
php/src/Google/Protobuf/Internal/MapField.php
+3
-0
RepeatedField.php
php/src/Google/Protobuf/Internal/RepeatedField.php
+4
-0
array_test.php
php/tests/array_test.php
+25
-14
gdb_test.sh
php/tests/gdb_test.sh
+3
-5
map_field_test.php
php/tests/map_field_test.php
+12
-5
memory_leak_test.php
php/tests/memory_leak_test.php
+5
-4
test_util.php
php/tests/test_util.php
+1
-2
tests.sh
tests.sh
+65
-60
No files found.
.gitignore
View file @
190b5270
...
...
@@ -65,6 +65,9 @@ src/js_embed
src/protoc
src/unittest_proto_middleman
# vim generated
*.swp
# Generated test scaffolding
src/no_warning_test.cc
src/no-warning-test
...
...
.travis.yml
View file @
190b5270
...
...
@@ -32,6 +32,7 @@ env:
-
CONFIG=ruby22
-
CONFIG=jruby
-
CONFIG=php5.6_mac
-
CONFIG=php7.0_mac
matrix
:
exclude
:
# It's nontrivial to programmatically install a new JDK from the command
...
...
conformance/failure_list_php_c.txt
View file @
190b5270
...
...
@@ -8,6 +8,7 @@ Recommended.JsonInput.DurationHas6FractionalDigits.Validator
Recommended.JsonInput.DurationHas9FractionalDigits.Validator
Recommended.JsonInput.DurationHasZeroFractionalDigit.Validator
Recommended.JsonInput.Int64FieldBeString.Validator
Recommended.JsonInput.MapFieldValueIsNull
Recommended.JsonInput.OneofZeroBool.JsonOutput
Recommended.JsonInput.OneofZeroBool.ProtobufOutput
Recommended.JsonInput.OneofZeroBytes.JsonOutput
...
...
@@ -24,6 +25,8 @@ Recommended.JsonInput.OneofZeroUint32.JsonOutput
Recommended.JsonInput.OneofZeroUint32.ProtobufOutput
Recommended.JsonInput.OneofZeroUint64.JsonOutput
Recommended.JsonInput.OneofZeroUint64.ProtobufOutput
Recommended.JsonInput.RepeatedFieldMessageElementIsNull
Recommended.JsonInput.RepeatedFieldPrimitiveElementIsNull
Recommended.JsonInput.StringEndsWithEscapeChar
Recommended.JsonInput.StringFieldSurrogateInWrongOrder
Recommended.JsonInput.StringFieldUnpairedHighSurrogate
...
...
@@ -127,24 +130,12 @@ Required.JsonInput.Int32FieldStringValue.JsonOutput
Required.JsonInput.Int32FieldStringValue.ProtobufOutput
Required.JsonInput.Int32FieldStringValueEscaped.JsonOutput
Required.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
Required.JsonInput.Int32MapEscapedKey.JsonOutput
Required.JsonInput.Int32MapEscapedKey.ProtobufOutput
Required.JsonInput.Int32MapField.JsonOutput
Required.JsonInput.Int32MapField.ProtobufOutput
Required.JsonInput.Int64FieldMaxValue.JsonOutput
Required.JsonInput.Int64FieldMaxValue.ProtobufOutput
Required.JsonInput.Int64FieldMinValue.JsonOutput
Required.JsonInput.Int64FieldMinValue.ProtobufOutput
Required.JsonInput.Int64MapEscapedKey.JsonOutput
Required.JsonInput.Int64MapEscapedKey.ProtobufOutput
Required.JsonInput.Int64MapField.JsonOutput
Required.JsonInput.Int64MapField.ProtobufOutput
Required.JsonInput.MessageField.JsonOutput
Required.JsonInput.MessageField.ProtobufOutput
Required.JsonInput.MessageMapField.JsonOutput
Required.JsonInput.MessageMapField.ProtobufOutput
Required.JsonInput.MessageRepeatedField.JsonOutput
Required.JsonInput.MessageRepeatedField.ProtobufOutput
Required.JsonInput.OptionalBoolWrapper.JsonOutput
Required.JsonInput.OptionalBoolWrapper.ProtobufOutput
Required.JsonInput.OptionalBytesWrapper.JsonOutput
...
...
@@ -165,14 +156,13 @@ Required.JsonInput.OptionalUint64Wrapper.JsonOutput
Required.JsonInput.OptionalUint64Wrapper.ProtobufOutput
Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
Required.JsonInput.PrimitiveRepeatedField.JsonOutput
Required.JsonInput.PrimitiveRepeatedField.ProtobufOutput
Required.JsonInput.RepeatedBoolWrapper.JsonOutput
Required.JsonInput.RepeatedBoolWrapper.ProtobufOutput
Required.JsonInput.RepeatedBytesWrapper.JsonOutput
Required.JsonInput.RepeatedBytesWrapper.ProtobufOutput
Required.JsonInput.RepeatedDoubleWrapper.JsonOutput
Required.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
Required.JsonInput.RepeatedFloatWrapper.JsonOutput
Required.JsonInput.RepeatedFloatWrapper.ProtobufOutput
...
...
@@ -186,9 +176,15 @@ Required.JsonInput.RepeatedUint32Wrapper.JsonOutput
Required.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
Required.JsonInput.RepeatedUint64Wrapper.JsonOutput
Required.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
Required.JsonInput.StringFieldEscape.JsonOutput
Required.JsonInput.StringFieldEscape.ProtobufOutput
Required.JsonInput.StringFieldNotAString
Required.JsonInput.StringFieldSurrogatePair.JsonOutput
Required.JsonInput.StringFieldSurrogatePair.ProtobufOutput
Required.JsonInput.StringFieldUnicodeEscape.JsonOutput
Required.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
Required.JsonInput.Struct.JsonOutput
Required.JsonInput.Struct.ProtobufOutput
Required.JsonInput.TimestampMaxValue.JsonOutput
...
...
@@ -203,12 +199,8 @@ Required.JsonInput.TimestampWithPositiveOffset.JsonOutput
Required.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
Required.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
Required.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
Required.JsonInput.Uint32MapField.JsonOutput
Required.JsonInput.Uint32MapField.ProtobufOutput
Required.JsonInput.Uint64FieldMaxValue.JsonOutput
Required.JsonInput.Uint64FieldMaxValue.ProtobufOutput
Required.JsonInput.Uint64MapField.JsonOutput
Required.JsonInput.Uint64MapField.ProtobufOutput
Required.JsonInput.ValueAcceptBool.JsonOutput
Required.JsonInput.ValueAcceptBool.ProtobufOutput
Required.JsonInput.ValueAcceptFloat.JsonOutput
...
...
jenkins/buildcmds/pull_request_32.sh
View file @
190b5270
...
...
@@ -12,5 +12,5 @@
export
DOCKERFILE_DIR
=
jenkins/docker32
export
DOCKER_RUN_SCRIPT
=
jenkins/pull_request_in_docker.sh
export
OUTPUT_DIR
=
testoutput
export
TEST_SET
=
"php_all
_32
"
export
TEST_SET
=
"php_all"
./jenkins/build_and_run_docker.sh
jenkins/docker/Dockerfile
View file @
190b5270
...
...
@@ -147,6 +147,23 @@ RUN cd php-5.5.38 && ./configure --enable-maintainer-zts --prefix=/usr/local/php
make
&&
make
install
&&
cd
..
RUN
cd
php-5.5.38
&&
make clean
&&
./configure
--prefix
=
/usr/local/php-5.5
&&
\
make
&&
make
install
&&
cd
..
RUN
wget http://am1.php.net/get/php-5.6.30.tar.bz2/from/this/mirror
RUN
mv
mirror php-5.6.30.tar.bz2
RUN
tar
-xvf
php-5.6.30.tar.bz2
RUN
cd
php-5.6.30
&&
./configure
--enable-maintainer-zts
--prefix
=
/usr/local/php-5.6-zts
&&
\
make
&&
make
install
&&
cd
..
RUN
cd
php-5.6.30
&&
make clean
&&
./configure
--prefix
=
/usr/local/php-5.6
&&
\
make
&&
make
install
&&
cd
..
RUN
wget http://am1.php.net/get/php-7.0.18.tar.bz2/from/this/mirror
RUN
mv
mirror php-7.0.18.tar.bz2
RUN
tar
-xvf
php-7.0.18.tar.bz2
RUN
cd
php-7.0.18
&&
./configure
--enable-maintainer-zts
--prefix
=
/usr/local/php-7.0-zts
&&
\
make
&&
make
install
&&
cd
..
RUN
cd
php-7.0.18
&&
make clean
&&
./configure
--prefix
=
/usr/local/php-7.0
&&
\
make
&&
make
install
&&
cd
..
RUN
php
-r
"copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN
php composer-setup.php
RUN
mv
composer.phar /usr/bin/composer
...
...
@@ -157,21 +174,21 @@ RUN cd /tmp && \
rm
-rf
protobuf
&&
\
git clone https://github.com/google/protobuf.git
&&
\
cd
protobuf
&&
\
git reset
--hard
46ae90dc5e145b12fffa7e053a908a9f3e066286
&&
\
git reset
--hard
6b27c1f981a9a93918e4039f236ead27165a8e91
&&
\
cd
php
&&
\
ln
-sfn
/usr/local/php-5.5/bin/php /usr/bin/php
&&
\
ln
-sfn
/usr/local/php-5.5/bin/php-config /usr/bin/php-config
&&
\
ln
-sfn
/usr/local/php-5.5/bin/phpize /usr/bin/phpize
&&
\
composer
install
&&
\
mv
vendor /usr/local/vendor-5.5
&&
\
ln
-sfn
/usr/
bin/php5.6
/usr/bin/php
&&
\
ln
-sfn
/usr/
bin/php-config5.6
/usr/bin/php-config
&&
\
ln
-sfn
/usr/
bin/phpize5.6
/usr/bin/phpize
&&
\
ln
-sfn
/usr/
local/php-5.6/bin/php
/usr/bin/php
&&
\
ln
-sfn
/usr/
local/php-5.6/bin/php-config
/usr/bin/php-config
&&
\
ln
-sfn
/usr/
local/php-5.6/bin/phpize
/usr/bin/phpize
&&
\
composer
install
&&
\
mv
vendor /usr/local/vendor-5.6
&&
\
ln
-sfn
/usr/
bin/php7.0
/usr/bin/php
&&
\
ln
-sfn
/usr/
bin/php-config7.0
/usr/bin/php-config
&&
\
ln
-sfn
/usr/
bin/phpize7.0
/usr/bin/phpize
&&
\
ln
-sfn
/usr/
local/php-7.0/bin/php
/usr/bin/php
&&
\
ln
-sfn
/usr/
local/php-7.0/bin/php-config
/usr/bin/php-config
&&
\
ln
-sfn
/usr/
local/php-7.0/bin/phpize
/usr/bin/phpize
&&
\
composer
install
&&
\
mv
vendor /usr/local/vendor-7.0
...
...
jenkins/docker32/Dockerfile
View file @
190b5270
...
...
@@ -80,14 +80,31 @@ RUN cd /tmp && \
ln
-sfn
/usr/bin/phpize7.0 /usr/bin/phpize
&&
\
composer
install
&&
\
mv
vendor /usr/local/vendor-7.0
RUN
wget http://am1.php.net/get/php-5.5.38.tar.bz2/from/this/mirror
RUN
mv
mirror php-5.5.38.tar.bz2
RUN
tar
-xvf
php-5.5.38.tar.bz2
RUN
cd
php-5.5.38
&&
./configure
--enable-maintainer-zts
--prefix
=
/usr/local/php-5.5-zts
&&
\
make
&&
make
install
&&
make clean
&&
cd
..
RUN
cd
php-5.5.38
&&
./configure
--enable-bcmath
--prefix
=
/usr/local/php-5.5-bc
&&
\
RUN
cd
php-5.5.38
&&
make clean
&&
./configure
--enable-bcmath
--prefix
=
/usr/local/php-5.5
&&
\
make
&&
make
install
&&
make clean
&&
cd
..
RUN
wget http://am1.php.net/get/php-5.6.30.tar.bz2/from/this/mirror
RUN
mv
mirror php-5.6.30.tar.bz2
RUN
tar
-xvf
php-5.6.30.tar.bz2
RUN
cd
php-5.6.30
&&
./configure
--enable-maintainer-zts
--prefix
=
/usr/local/php-5.6-zts
&&
\
make
&&
make
install
&&
cd
..
RUN
cd
php-5.6.30
&&
make clean
&&
./configure
--enable-bcmath
--prefix
=
/usr/local/php-5.6
&&
\
make
&&
make
install
&&
cd
..
RUN
wget http://am1.php.net/get/php-7.0.18.tar.bz2/from/this/mirror
RUN
mv
mirror php-7.0.18.tar.bz2
RUN
tar
-xvf
php-7.0.18.tar.bz2
RUN
cd
php-7.0.18
&&
./configure
--enable-maintainer-zts
--prefix
=
/usr/local/php-7.0-zts
&&
\
make
&&
make
install
&&
cd
..
RUN
cd
php-7.0.18
&&
make clean
&&
./configure
--enable-bcmath
--prefix
=
/usr/local/php-7.0
&&
\
make
&&
make
install
&&
cd
..
##################
# Python dependencies
...
...
php/ext/google/protobuf/array.c
View file @
190b5270
...
...
@@ -69,19 +69,20 @@ static zend_function_entry repeated_field_iter_methods[] = {
// Forward declare static functions.
static
zend_object_value
repeated_field_create
(
zend_class_entry
*
ce
TSRMLS_DC
);
static
void
repeated_field_free
(
void
*
object
TSRMLS_DC
);
static
int
repeated_field_array_init
(
zval
*
array
,
upb_fieldtype_t
type
,
uint
size
ZEND_FILE_LINE_DC
);
static
void
repeated_field_free_element
(
void
*
object
);
static
void
repeated_field_write_dimension
(
zval
*
object
,
zval
*
offset
,
zval
*
value
TSRMLS_DC
);
static
int
repeated_field_has_dimension
(
zval
*
object
,
zval
*
offset
TSRMLS_DC
);
static
HashTable
*
repeated_field_get_gc
(
zval
*
object
,
zval
*
**
table
,
static
HashTable
*
repeated_field_get_gc
(
zval
*
object
,
CACHED_VALUE
**
table
,
int
*
n
TSRMLS_DC
);
#if PHP_MAJOR_VERSION < 7
static
zend_object_value
repeated_field_create
(
zend_class_entry
*
ce
TSRMLS_DC
);
static
zend_object_value
repeated_field_iter_create
(
zend_class_entry
*
ce
TSRMLS_DC
);
static
void
repeated_field_iter_free
(
void
*
object
TSRMLS_DC
);
#else
static
zend_object
*
repeated_field_create
(
zend_class_entry
*
ce
TSRMLS_DC
);
static
zend_object
*
repeated_field_iter_create
(
zend_class_entry
*
ce
TSRMLS_DC
);
#endif
// -----------------------------------------------------------------------------
// RepeatedField creation/desctruction
...
...
@@ -90,76 +91,91 @@ static void repeated_field_iter_free(void *object TSRMLS_DC);
zend_class_entry
*
repeated_field_type
;
zend_class_entry
*
repeated_field_iter_type
;
zend_object_handlers
*
repeated_field_handlers
;
void
repeated_field_init
(
TSRMLS_D
)
{
zend_class_entry
class_type
;
const
char
*
class_name
=
"Google
\\
Protobuf
\\
Internal
\\
RepeatedField"
;
INIT_CLASS_ENTRY_EX
(
class_type
,
class_name
,
strlen
(
class_name
),
repeated_field_methods
);
repeated_field_type
=
zend_register_internal_class
(
&
class_type
TSRMLS_CC
);
repeated_field_type
->
create_object
=
repeated_field_create
;
zend_class_implements
(
repeated_field_type
TSRMLS_CC
,
3
,
spl_ce_ArrayAccess
,
zend_object_handlers
*
repeated_field_iter_handlers
;
// Define object free method.
PHP_PROTO_OBJECT_FREE_START
(
RepeatedField
,
repeated_field
)
#if PHP_MAJOR_VERSION < 7
php_proto_zval_ptr_dtor
(
intern
->
array
);
#else
php_proto_zval_ptr_dtor
(
&
intern
->
array
);
#endif
PHP_PROTO_OBJECT_FREE_END
PHP_PROTO_OBJECT_DTOR_START
(
RepeatedField
,
repeated_field
)
PHP_PROTO_OBJECT_DTOR_END
// Define object create method.
PHP_PROTO_OBJECT_CREATE_START
(
RepeatedField
,
repeated_field
)
#if PHP_MAJOR_VERSION < 7
intern
->
array
=
NULL
;
#endif
intern
->
type
=
0
;
intern
->
msg_ce
=
NULL
;
PHP_PROTO_OBJECT_CREATE_END
(
RepeatedField
,
repeated_field
)
// Init class entry.
PHP_PROTO_INIT_CLASS_START
(
"Google
\\
Protobuf
\\
Internal
\\
RepeatedField"
,
RepeatedField
,
repeated_field
)
zend_class_implements
(
repeated_field_type
TSRMLS_CC
,
3
,
spl_ce_ArrayAccess
,
zend_ce_aggregate
,
spl_ce_Countable
);
repeated_field_handlers
=
PEMALLOC
(
zend_object_handlers
);
memcpy
(
repeated_field_handlers
,
zend_get_std_object_handlers
(),
sizeof
(
zend_object_handlers
));
repeated_field_handlers
->
write_dimension
=
repeated_field_write_dimension
;
repeated_field_handlers
->
get_gc
=
repeated_field_get_gc
;
repeated_field_handlers
->
write_dimension
=
repeated_field_write_dimension
;
repeated_field_handlers
->
get_gc
=
repeated_field_get_gc
;
PHP_PROTO_INIT_CLASS_END
// Define array element free function.
#if PHP_MAJOR_VERSION < 7
static
inline
void
php_proto_array_string_release
(
void
*
value
)
{
zval_ptr_dtor
(
value
);
}
static
zend_object_value
repeated_field_create
(
zend_class_entry
*
ce
TSRMLS_DC
)
{
zend_object_value
retval
=
{
0
};
RepeatedField
*
intern
;
intern
=
emalloc
(
sizeof
(
RepeatedField
));
memset
(
intern
,
0
,
sizeof
(
RepeatedField
));
zend_object_std_init
(
&
intern
->
std
,
ce
TSRMLS_CC
);
object_properties_init
(
&
intern
->
std
,
ce
);
intern
->
array
=
NULL
;
intern
->
type
=
0
;
intern
->
msg_ce
=
NULL
;
retval
.
handle
=
zend_objects_store_put
(
intern
,
(
zend_objects_store_dtor_t
)
zend_objects_destroy_object
,
(
zend_objects_free_object_storage_t
)
repeated_field_free
,
NULL
TSRMLS_CC
);
retval
.
handlers
=
repeated_field_handlers
;
return
retval
;
static
inline
void
php_proto_array_object_release
(
void
*
value
)
{
zval_ptr_dtor
(
value
);
}
static
void
repeated_field_free
(
void
*
object
TSRMLS_DC
)
{
RepeatedField
*
intern
=
object
;
zend_object_std_dtor
(
&
intern
->
std
TSRMLS_CC
);
zval_ptr_dtor
(
&
intern
->
array
);
efree
(
object
);
static
inline
void
php_proto_array_default_release
(
void
*
value
)
{
}
#else
static
inline
void
php_proto_array_string_release
(
zval
*
value
)
{
void
*
ptr
=
Z_PTR_P
(
value
);
zend_string
*
object
=
*
(
zend_string
**
)
ptr
;
zend_string_release
(
object
);
efree
(
ptr
);
}
static
inline
void
php_proto_array_object_release
(
zval
*
value
)
{
void
*
ptr
=
Z_PTR_P
(
value
);
zend_object
*
object
=
*
(
zend_object
**
)
ptr
;
if
(
--
GC_REFCOUNT
(
object
)
==
0
)
{
zend_objects_store_del
(
object
);
}
efree
(
ptr
);
}
static
void
php_proto_array_default_release
(
zval
*
value
)
{
void
*
ptr
=
Z_PTR_P
(
value
);
efree
(
ptr
);
}
#endif
static
int
repeated_field_array_init
(
zval
*
array
,
upb_fieldtype_t
type
,
uint
size
ZEND_FILE_LINE_DC
)
{
ALLOC_HASHTABLE
(
Z_ARRVAL_P
(
array
)
);
PHP_PROTO_ALLOC_ARRAY
(
array
);
switch
(
type
)
{
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
zend_hash_init
(
Z_ARRVAL_P
(
array
),
size
,
NULL
,
php_proto_array_string_release
,
0
);
break
;
case
UPB_TYPE_MESSAGE
:
zend_hash_init
(
Z_ARRVAL_P
(
array
),
size
,
NULL
,
ZVAL_PTR_DTOR
,
0
);
zend_hash_init
(
Z_ARRVAL_P
(
array
),
size
,
NULL
,
php_proto_array_object_release
,
0
);
break
;
default
:
zend_hash_init
(
Z_ARRVAL_P
(
array
),
size
,
NULL
,
repeated_field_free_element
,
0
);
zend_hash_init
(
Z_ARRVAL_P
(
array
),
size
,
NULL
,
php_proto_array_default_release
,
0
);
}
Z_TYPE_P
(
array
)
=
IS_ARRAY
;
return
SUCCESS
;
}
static
void
repeated_field_free_element
(
void
*
object
)
{
}
// -----------------------------------------------------------------------------
// RepeatedField Handlers
// -----------------------------------------------------------------------------
...
...
@@ -168,23 +184,25 @@ static void repeated_field_write_dimension(zval *object, zval *offset,
zval
*
value
TSRMLS_DC
)
{
uint64_t
index
;
RepeatedField
*
intern
=
zend_object_store_get_object
(
object
TSRMLS_CC
);
HashTable
*
ht
=
HASH_OF
(
intern
->
array
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
object
);
HashTable
*
ht
=
PHP_PROTO_
HASH_OF
(
intern
->
array
);
int
size
=
native_slot_size
(
intern
->
type
);
unsigned
char
memory
[
NATIVE_SLOT_MAX_SIZE
];
memset
(
memory
,
0
,
NATIVE_SLOT_MAX_SIZE
);
if
(
!
native_slot_set
(
intern
->
type
,
intern
->
msg_ce
,
memory
,
value
TSRMLS_CC
))
{
if
(
!
native_slot_set_by_array
(
intern
->
type
,
intern
->
msg_ce
,
memory
,
value
TSRMLS_CC
))
{
return
;
}
if
(
!
offset
||
Z_TYPE_P
(
offset
)
==
IS_NULL
)
{
index
=
zend_hash_num_elements
(
HASH_OF
(
intern
->
array
));
index
=
zend_hash_num_elements
(
PHP_PROTO_
HASH_OF
(
intern
->
array
));
}
else
{
if
(
protobuf_convert_to_uint64
(
offset
,
&
index
))
{
if
(
!
zend_hash_index_exists
(
ht
,
index
))
{
zend_error
(
E_USER_ERROR
,
"Element at %llu doesn't exist.
\n
"
,
index
);
zend_error
(
E_USER_ERROR
,
"Element at %llu doesn't exist.
\n
"
,
(
long
long
unsigned
int
)
index
);
return
;
}
}
else
{
...
...
@@ -192,15 +210,19 @@ static void repeated_field_write_dimension(zval *object, zval *offset,
}
}
zend_hash_index_update
(
ht
,
index
,
memory
,
size
,
NULL
);
php_proto_
zend_hash_index_update
(
ht
,
index
,
memory
,
size
,
NULL
);
}
#if PHP_MAJOR_VERSION < 7
static
HashTable
*
repeated_field_get_gc
(
zval
*
object
,
zval
***
table
,
int
*
n
TSRMLS_DC
)
{
#else
static
HashTable
*
repeated_field_get_gc
(
zval
*
object
,
zval
**
table
,
int
*
n
)
{
#endif
*
table
=
NULL
;
*
n
=
0
;
RepeatedField
*
intern
=
zend_object_store_get_object
(
object
TSRMLS_CC
);
return
HASH_OF
(
intern
->
array
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
object
);
return
PHP_PROTO_
HASH_OF
(
intern
->
array
);
}
// -----------------------------------------------------------------------------
...
...
@@ -208,10 +230,10 @@ static HashTable *repeated_field_get_gc(zval *object, zval ***table,
// -----------------------------------------------------------------------------
void
*
repeated_field_index_native
(
RepeatedField
*
intern
,
int
index
TSRMLS_DC
)
{
HashTable
*
ht
=
HASH_OF
(
intern
->
array
);
HashTable
*
ht
=
PHP_PROTO_
HASH_OF
(
intern
->
array
);
void
*
value
;
if
(
zend_hash_index_find
(
ht
,
index
,
(
void
**
)
&
value
)
==
FAILURE
)
{
if
(
php_proto_
zend_hash_index_find
(
ht
,
index
,
(
void
**
)
&
value
)
==
FAILURE
)
{
zend_error
(
E_USER_ERROR
,
"Element at %d doesn't exist.
\n
"
,
index
);
return
NULL
;
}
...
...
@@ -219,35 +241,37 @@ void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC) {
return
value
;
}
void
repeated_field_push_native
(
RepeatedField
*
intern
,
void
*
value
TSRMLS_DC
)
{
HashTable
*
ht
=
HASH_OF
(
intern
->
array
);
void
repeated_field_push_native
(
RepeatedField
*
intern
,
void
*
value
)
{
HashTable
*
ht
=
PHP_PROTO_
HASH_OF
(
intern
->
array
);
int
size
=
native_slot_size
(
intern
->
type
);
zend_hash_next_index_insert
(
ht
,
(
void
**
)
value
,
size
,
NULL
);
php_proto_
zend_hash_next_index_insert
(
ht
,
(
void
**
)
value
,
size
,
NULL
);
}
void
repeated_field_create_with_field
(
zend_class_entry
*
ce
,
const
upb_fielddef
*
field
,
zval
**
repeated_field
TSRMLS_DC
)
{
void
repeated_field_create_with_field
(
zend_class_entry
*
ce
,
const
upb_fielddef
*
field
,
CACHED_VALUE
*
repeated_field
PHP_PROTO_
TSRMLS_DC
)
{
upb_fieldtype_t
type
=
upb_fielddef_type
(
field
);
const
zend_class_entry
*
msg_ce
=
field_type_class
(
field
TSRMLS_CC
);
repeated_field_create_with_type
(
ce
,
type
,
msg_ce
,
repeated_field
TSRMLS_CC
);
const
zend_class_entry
*
msg_ce
=
field_type_class
(
field
PHP_PROTO_TSRMLS_CC
);
repeated_field_create_with_type
(
ce
,
type
,
msg_ce
,
repeated_field
PHP_PROTO_TSRMLS_CC
);
}
void
repeated_field_create_with_type
(
zend_class_entry
*
ce
,
upb_fieldtype_t
type
,
const
zend_class_entry
*
msg_ce
,
zval
**
repeated_field
TSRMLS_DC
)
{
MAKE_STD_ZVAL
(
*
repeated_field
);
Z_TYPE_PP
(
repeated_field
)
=
IS_OBJECT
;
Z_OBJVAL_PP
(
repeated_field
)
=
repeated_field_type
->
create_object
(
repeated_field_type
TSRMLS_CC
);
void
repeated_field_create_with_type
(
zend_class_entry
*
ce
,
upb_fieldtype_t
type
,
const
zend_class_entry
*
msg_ce
,
CACHED_VALUE
*
repeated_field
PHP_PROTO_TSRMLS_DC
)
{
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR
(
CACHED_PTR_TO_ZVAL_PTR
(
repeated_field
),
repeated_field_type
);
RepeatedField
*
intern
=
zend_object_store_get_object
(
*
repeated_field
TSRMLS_CC
);
UNBOX
(
RepeatedField
,
CACHED_TO_ZVAL_PTR
(
*
repeated_field
)
);
intern
->
type
=
type
;
intern
->
msg_ce
=
msg_ce
;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL
(
intern
->
array
);
repeated_field_array_init
(
intern
->
array
,
intern
->
type
,
0
ZEND_FILE_LINE_CC
);
#else
repeated_field_array_init
(
&
intern
->
array
,
intern
->
type
,
0
ZEND_FILE_LINE_CC
);
#endif
// TODO(teboring): Link class entry for message and enum
}
...
...
@@ -271,12 +295,16 @@ PHP_METHOD(RepeatedField, __construct) {
return
;
}
RepeatedField
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
getThis
()
);
intern
->
type
=
to_fieldtype
(
type
);
intern
->
msg_ce
=
klass
;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL
(
intern
->
array
);
repeated_field_array_init
(
intern
->
array
,
intern
->
type
,
0
ZEND_FILE_LINE_CC
);
#else
repeated_field_array_init
(
&
intern
->
array
,
intern
->
type
,
0
ZEND_FILE_LINE_CC
);
#endif
if
(
intern
->
type
==
UPB_TYPE_MESSAGE
&&
klass
==
NULL
)
{
zend_error
(
E_USER_ERROR
,
"Message type must have concrete class."
);
...
...
@@ -313,10 +341,10 @@ PHP_METHOD(RepeatedField, offsetExists) {
return
;
}
RepeatedField
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
getThis
()
);
RETURN_BOOL
(
index
>=
0
&&
index
<
zend_hash_num_elements
(
HASH_OF
(
intern
->
array
)));
index
<
zend_hash_num_elements
(
PHP_PROTO_
HASH_OF
(
intern
->
array
)));
}
/**
...
...
@@ -336,15 +364,16 @@ PHP_METHOD(RepeatedField, offsetGet) {
return
;
}
RepeatedField
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
HashTable
*
table
=
HASH_OF
(
intern
->
array
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
getThis
()
);
HashTable
*
table
=
PHP_PROTO_
HASH_OF
(
intern
->
array
);
if
(
zend_hash_index_find
(
table
,
index
,
(
void
**
)
&
memory
)
==
FAILURE
)
{
if
(
php_proto_
zend_hash_index_find
(
table
,
index
,
(
void
**
)
&
memory
)
==
FAILURE
)
{
zend_error
(
E_USER_ERROR
,
"Element at %ld doesn't exist.
\n
"
,
index
);
return
;
}
native_slot_get
(
intern
->
type
,
memory
,
return_value_ptr
TSRMLS_CC
);
native_slot_get_by_array
(
intern
->
type
,
memory
,
ZVAL_PTR_TO_CACHED_PTR
(
return_value
)
TSRMLS_CC
);
}
/**
...
...
@@ -379,16 +408,16 @@ PHP_METHOD(RepeatedField, offsetUnset) {
return
;
}
RepeatedField
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
getThis
()
);
// Only the element at the end of the array can be removed.
if
(
index
==
-
1
||
index
!=
(
zend_hash_num_elements
(
HASH_OF
(
intern
->
array
))
-
1
))
{
index
!=
(
zend_hash_num_elements
(
PHP_PROTO_
HASH_OF
(
intern
->
array
))
-
1
))
{
zend_error
(
E_USER_ERROR
,
"Cannot remove element at %ld.
\n
"
,
index
);
return
;
}
zend_hash_index_del
(
HASH_OF
(
intern
->
array
),
index
);
zend_hash_index_del
(
PHP_PROTO_
HASH_OF
(
intern
->
array
),
index
);
}
/**
...
...
@@ -397,13 +426,13 @@ PHP_METHOD(RepeatedField, offsetUnset) {
* @return long The number of stored elements.
*/
PHP_METHOD
(
RepeatedField
,
count
)
{
RepeatedField
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
getThis
()
);
if
(
zend_parse_parameters_none
()
==
FAILURE
)
{
return
;
}
RETURN_LONG
(
zend_hash_num_elements
(
HASH_OF
(
intern
->
array
)));
RETURN_LONG
(
zend_hash_num_elements
(
PHP_PROTO_
HASH_OF
(
intern
->
array
)));
}
/**
...
...
@@ -412,105 +441,77 @@ PHP_METHOD(RepeatedField, count) {
* @return object Beginning iterator.
*/
PHP_METHOD
(
RepeatedField
,
getIterator
)
{
zval
*
iter_php
=
NULL
;
MAKE_STD_ZVAL
(
iter_php
);
Z_TYPE_P
(
iter_php
)
=
IS_OBJECT
;
Z_OBJVAL_P
(
iter_php
)
=
repeated_field_iter_type
->
create_object
(
repeated_field_iter_type
TSRMLS_CC
);
RepeatedField
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
RepeatedFieldIter
*
iter
=
zend_object_store_get_object
(
iter_php
TSRMLS_CC
);
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR
(
return_value
,
repeated_field_iter_type
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
getThis
());
RepeatedFieldIter
*
iter
=
UNBOX
(
RepeatedFieldIter
,
return_value
);
iter
->
repeated_field
=
intern
;
iter
->
position
=
0
;
RETURN_ZVAL
(
iter_php
,
1
,
1
);
}
// -----------------------------------------------------------------------------
// RepeatedFieldIter creation/desctruction
// -----------------------------------------------------------------------------
void
repeated_field_iter_init
(
TSRMLS_D
)
{
zend_class_entry
class_type
;
const
char
*
class_name
=
"Google
\\
Protobuf
\\
Internal
\\
RepeatedFieldIter"
;
INIT_CLASS_ENTRY_EX
(
class_type
,
class_name
,
strlen
(
class_name
),
repeated_field_iter_methods
);
repeated_field_iter_type
=
zend_register_internal_class
(
&
class_type
TSRMLS_CC
);
repeated_field_iter_type
->
create_object
=
repeated_field_iter_create
;
zend_class_implements
(
repeated_field_iter_type
TSRMLS_CC
,
1
,
zend_ce_iterator
);
}
static
zend_object_value
repeated_field_iter_create
(
zend_class_entry
*
ce
TSRMLS_DC
)
{
zend_object_value
retval
=
{
0
};
RepeatedFieldIter
*
intern
;
intern
=
emalloc
(
sizeof
(
RepeatedFieldIter
));
memset
(
intern
,
0
,
sizeof
(
RepeatedFieldIter
));
zend_object_std_init
(
&
intern
->
std
,
ce
TSRMLS_CC
);
object_properties_init
(
&
intern
->
std
,
ce
);
// Define object free method.
PHP_PROTO_OBJECT_FREE_START
(
RepeatedFieldIter
,
repeated_field_iter
)
PHP_PROTO_OBJECT_FREE_END
intern
->
repeated_field
=
NULL
;
intern
->
position
=
0
;
retval
.
handle
=
zend_objects_store_put
(
intern
,
(
zend_objects_store_dtor_t
)
zend_objects_destroy_object
,
(
zend_objects_free_object_storage_t
)
repeated_field_iter_free
,
NULL
TSRMLS_CC
);
retval
.
handlers
=
zend_get_std_object_handlers
();
PHP_PROTO_OBJECT_DTOR_START
(
RepeatedFieldIter
,
repeated_field_iter
)
PHP_PROTO_OBJECT_DTOR_END
return
retval
;
}
// Define object create method.
PHP_PROTO_OBJECT_CREATE_START
(
RepeatedFieldIter
,
repeated_field_iter
)
intern
->
repeated_field
=
NULL
;
intern
->
position
=
0
;
PHP_PROTO_OBJECT_CREATE_END
(
RepeatedFieldIter
,
repeated_field_iter
)
static
void
repeated_field_iter_free
(
void
*
object
TSRMLS_DC
)
{
RepeatedFieldIter
*
intern
=
object
;
zend_object_std_dtor
(
&
intern
->
std
TSRMLS_CC
);
efree
(
object
);
}
// Init class entry.
PHP_PROTO_INIT_CLASS_START
(
"Google
\\
Protobuf
\\
Internal
\\
RepeatedFieldIter"
,
RepeatedFieldIter
,
repeated_field_iter
)
zend_class_implements
(
repeated_field_iter_type
TSRMLS_CC
,
1
,
zend_ce_iterator
);
PHP_PROTO_INIT_CLASS_END
// -----------------------------------------------------------------------------
// PHP RepeatedFieldIter Methods
// -----------------------------------------------------------------------------
PHP_METHOD
(
RepeatedFieldIter
,
rewind
)
{
RepeatedFieldIter
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
RepeatedFieldIter
*
intern
=
UNBOX
(
RepeatedFieldIter
,
getThis
()
);
intern
->
position
=
0
;
}
PHP_METHOD
(
RepeatedFieldIter
,
current
)
{
RepeatedFieldIter
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
RepeatedFieldIter
*
intern
=
UNBOX
(
RepeatedFieldIter
,
getThis
()
);
RepeatedField
*
repeated_field
=
intern
->
repeated_field
;
long
index
;
void
*
memory
;
HashTable
*
table
=
HASH_OF
(
repeated_field
->
array
);
HashTable
*
table
=
PHP_PROTO_
HASH_OF
(
repeated_field
->
array
);
if
(
zend_hash_index_find
(
table
,
intern
->
position
,
(
void
**
)
&
memory
)
==
if
(
php_proto_
zend_hash_index_find
(
table
,
intern
->
position
,
(
void
**
)
&
memory
)
==
FAILURE
)
{
zend_error
(
E_USER_ERROR
,
"Element at %ld doesn't exist.
\n
"
,
index
);
return
;
}
native_slot_get
(
repeated_field
->
type
,
memory
,
return_value_ptr
TSRMLS_CC
);
native_slot_get_by_array
(
repeated_field
->
type
,
memory
,
ZVAL_PTR_TO_CACHED_PTR
(
return_value
)
TSRMLS_CC
);
}
PHP_METHOD
(
RepeatedFieldIter
,
key
)
{
RepeatedFieldIter
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
RepeatedFieldIter
*
intern
=
UNBOX
(
RepeatedFieldIter
,
getThis
()
);
RETURN_LONG
(
intern
->
position
);
}
PHP_METHOD
(
RepeatedFieldIter
,
next
)
{
RepeatedFieldIter
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
RepeatedFieldIter
*
intern
=
UNBOX
(
RepeatedFieldIter
,
getThis
()
);
++
intern
->
position
;
}
PHP_METHOD
(
RepeatedFieldIter
,
valid
)
{
RepeatedFieldIter
*
intern
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
RETURN_BOOL
(
zend_hash_num_elements
(
HASH_OF
(
intern
->
repeated_field
->
array
))
>
intern
->
position
);
RepeatedFieldIter
*
intern
=
UNBOX
(
RepeatedFieldIter
,
getThis
()
);
RETURN_BOOL
(
zend_hash_num_elements
(
PHP_PROTO_HASH_OF
(
intern
->
repeated_field
->
array
))
>
intern
->
position
);
}
php/ext/google/protobuf/def.c
View file @
190b5270
...
...
@@ -31,19 +31,13 @@
#include "protobuf.h"
// Forward declare.
static
zend_object_value
descriptor_create
(
zend_class_entry
*
ce
TSRMLS_DC
);
static
void
descriptor_init_c_instance
(
Descriptor
*
intern
TSRMLS_DC
);
static
void
descriptor_free_c
(
Descriptor
*
object
TSRMLS_DC
);
static
void
descriptor_free
(
void
*
object
TSRMLS_DC
);
static
zend_object_value
enum_descriptor_create
(
zend_class_entry
*
ce
TSRMLS_DC
);
static
void
enum_descriptor_init_c_instance
(
EnumDescriptor
*
intern
TSRMLS_DC
);
static
void
enum_descriptor_free_c
(
EnumDescriptor
*
object
TSRMLS_DC
);
static
void
enum_descriptor_free
(
void
*
object
TSRMLS_DC
);
static
zend_object_value
descriptor_pool_create
(
zend_class_entry
*
ce
TSRMLS_DC
);
static
void
descriptor_pool_free_c
(
DescriptorPool
*
object
TSRMLS_DC
);
static
void
descriptor_pool_free
(
void
*
object
TSRMLS_DC
);
static
void
descriptor_pool_init_c_instance
(
DescriptorPool
*
pool
TSRMLS_DC
);
// -----------------------------------------------------------------------------
...
...
@@ -104,40 +98,31 @@ static void append_map_entry_name(char *result, const char *field_name,
} while (0)
// Define PHP class
#define DEFINE_PROTOBUF_INIT_CLASS(name_lower, string_name) \
void name_lower##_init(TSRMLS_D) { \
zend_class_entry class_type; \
INIT_CLASS_ENTRY(class_type, string_name, name_lower##_methods); \
name_lower##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
name_lower##_type->create_object = name_lower##_create; \
}
#define DEFINE_PROTOBUF_CREATE(name, name_lower) \
static zend_object_value name_lower##_create( \
zend_class_entry* ce TSRMLS_DC) { \
zend_object_value return_value; \
name* intern = (name*)emalloc(sizeof(name)); \
memset(intern, 0, sizeof(name)); \
name_lower##_init_c_instance(intern TSRMLS_CC); \
return_value.handle = zend_objects_store_put( \
intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \
name_lower##_free, NULL TSRMLS_CC); \
return_value.handlers = zend_get_std_object_handlers(); \
return return_value; \
}
#define DEFINE_PROTOBUF_FREE(name, name_lower) \
static void name_lower##_free(void* object TSRMLS_DC) { \
name* intern = (name*)object; \
name_lower##_free_c(intern TSRMLS_CC); \
efree(object); \
}
#define DEFINE_CLASS(name, name_lower, string_name) \
zend_class_entry* name_lower##_type; \
DEFINE_PROTOBUF_FREE(name, name_lower) \
DEFINE_PROTOBUF_CREATE(name, name_lower) \
DEFINE_PROTOBUF_INIT_CLASS(name_lower, string_name)
#define DEFINE_PROTOBUF_INIT_CLASS(CLASSNAME, CAMELNAME, LOWERNAME) \
PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWERNAME) \
PHP_PROTO_INIT_CLASS_END
#define DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \
PHP_PROTO_OBJECT_CREATE_START(NAME, LOWERNAME) \
LOWERNAME##_init_c_instance(intern TSRMLS_CC); \
PHP_PROTO_OBJECT_CREATE_END(NAME, LOWERNAME)
#define DEFINE_PROTOBUF_FREE(CAMELNAME, LOWERNAME) \
PHP_PROTO_OBJECT_FREE_START(CAMELNAME, LOWERNAME) \
LOWERNAME##_free_c(intern TSRMLS_CC); \
PHP_PROTO_OBJECT_FREE_END
#define DEFINE_PROTOBUF_DTOR(CAMELNAME, LOWERNAME) \
PHP_PROTO_OBJECT_DTOR_START(CAMELNAME, LOWERNAME) \
PHP_PROTO_OBJECT_DTOR_END
#define DEFINE_CLASS(NAME, LOWERNAME, string_name) \
zend_class_entry *LOWERNAME##_type; \
zend_object_handlers *LOWERNAME##_handlers; \
DEFINE_PROTOBUF_FREE(NAME, LOWERNAME) \
DEFINE_PROTOBUF_DTOR(NAME, LOWERNAME) \
DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME) \
DEFINE_PROTOBUF_INIT_CLASS(string_name, NAME, LOWERNAME)
// -----------------------------------------------------------------------------
// GPBType
...
...
@@ -176,6 +161,114 @@ void gpb_type_init(TSRMLS_D) {
zend_declare_class_constant_long
(
gpb_type_type
,
STR
(
"SINT64"
),
18
TSRMLS_CC
);
}
// -----------------------------------------------------------------------------
// Descriptor
// -----------------------------------------------------------------------------
static
zend_function_entry
descriptor_methods
[]
=
{
ZEND_FE_END
};
DEFINE_CLASS
(
Descriptor
,
descriptor
,
"Google
\\
Protobuf
\\
Internal
\\
Descriptor"
);
static
void
descriptor_free_c
(
Descriptor
*
self
TSRMLS_DC
)
{
if
(
self
->
layout
)
{
free_layout
(
self
->
layout
);
}
if
(
self
->
fill_handlers
)
{
upb_handlers_unref
(
self
->
fill_handlers
,
&
self
->
fill_handlers
);
}
if
(
self
->
fill_method
)
{
upb_pbdecodermethod_unref
(
self
->
fill_method
,
&
self
->
fill_method
);
}
if
(
self
->
json_fill_method
)
{
upb_json_parsermethod_unref
(
self
->
json_fill_method
,
&
self
->
json_fill_method
);
}
if
(
self
->
pb_serialize_handlers
)
{
upb_handlers_unref
(
self
->
pb_serialize_handlers
,
&
self
->
pb_serialize_handlers
);
}
if
(
self
->
json_serialize_handlers
)
{
upb_handlers_unref
(
self
->
json_serialize_handlers
,
&
self
->
json_serialize_handlers
);
}
if
(
self
->
json_serialize_handlers_preserve
)
{
upb_handlers_unref
(
self
->
json_serialize_handlers_preserve
,
&
self
->
json_serialize_handlers_preserve
);
}
}
static
void
descriptor_init_c_instance
(
Descriptor
*
desc
TSRMLS_DC
)
{
// zend_object_std_init(&desc->std, descriptor_type TSRMLS_CC);
desc
->
msgdef
=
NULL
;
desc
->
layout
=
NULL
;
desc
->
klass
=
NULL
;
desc
->
fill_handlers
=
NULL
;
desc
->
fill_method
=
NULL
;
desc
->
json_fill_method
=
NULL
;
desc
->
pb_serialize_handlers
=
NULL
;
desc
->
json_serialize_handlers
=
NULL
;
desc
->
json_serialize_handlers_preserve
=
NULL
;
}
// -----------------------------------------------------------------------------
// EnumDescriptor
// -----------------------------------------------------------------------------
static
zend_function_entry
enum_descriptor_methods
[]
=
{
ZEND_FE_END
};
DEFINE_CLASS
(
EnumDescriptor
,
enum_descriptor
,
"Google
\\
Protobuf
\\
Internal
\\
EnumDescriptor"
);
static
void
enum_descriptor_free_c
(
EnumDescriptor
*
self
TSRMLS_DC
)
{
}
static
void
enum_descriptor_init_c_instance
(
EnumDescriptor
*
self
TSRMLS_DC
)
{
// zend_object_std_init(&self->std, enum_descriptor_type TSRMLS_CC);
self
->
enumdef
=
NULL
;
self
->
klass
=
NULL
;
}
// -----------------------------------------------------------------------------
// FieldDescriptor
// -----------------------------------------------------------------------------
upb_fieldtype_t
to_fieldtype
(
upb_descriptortype_t
type
)
{
switch
(
type
)
{
#define CASE(descriptor_type, type) \
case UPB_DESCRIPTOR_TYPE_##descriptor_type: \
return UPB_TYPE_##type;
CASE
(
FLOAT
,
FLOAT
);
CASE
(
DOUBLE
,
DOUBLE
);
CASE
(
BOOL
,
BOOL
);
CASE
(
STRING
,
STRING
);
CASE
(
BYTES
,
BYTES
);
CASE
(
MESSAGE
,
MESSAGE
);
CASE
(
GROUP
,
MESSAGE
);
CASE
(
ENUM
,
ENUM
);
CASE
(
INT32
,
INT32
);
CASE
(
INT64
,
INT64
);
CASE
(
UINT32
,
UINT32
);
CASE
(
UINT64
,
UINT64
);
CASE
(
SINT32
,
INT32
);
CASE
(
SINT64
,
INT64
);
CASE
(
FIXED32
,
UINT32
);
CASE
(
FIXED64
,
UINT64
);
CASE
(
SFIXED32
,
INT32
);
CASE
(
SFIXED64
,
INT64
);
#undef CONVERT
}
zend_error
(
E_ERROR
,
"Unknown field type."
);
return
0
;
}
// -----------------------------------------------------------------------------
// DescriptorPool
// -----------------------------------------------------------------------------
...
...
@@ -190,25 +283,32 @@ static zend_function_entry descriptor_pool_methods[] = {
DEFINE_CLASS
(
DescriptorPool
,
descriptor_pool
,
"Google
\\
Protobuf
\\
Internal
\\
DescriptorPool"
);
zval
*
generated_pool_php
;
// wrapper of generated pool
// wrapper of generated pool
#if PHP_MAJOR_VERSION < 7
zval
*
generated_pool_php
;
#else
zend_object
*
generated_pool_php
;
#endif
DescriptorPool
*
generated_pool
;
// The actual generated pool
static
void
init_generated_pool_once
(
TSRMLS_D
)
{
if
(
generated_pool_php
==
NULL
)
{
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL
(
generated_pool_php
);
Z_TYPE_P
(
generated_pool_php
)
=
IS_OBJECT
;
generated_pool
=
ALLOC
(
DescriptorPool
);
descriptor_pool_init_c_instance
(
generated_pool
TSRMLS_CC
);
Z_OBJ_HANDLE_P
(
generated_pool_php
)
=
zend_objects_store_put
(
generated_pool
,
NULL
,
(
zend_objects_free_object_storage_t
)
descriptor_pool_free
,
NULL
TSRMLS_CC
);
Z_OBJ_HT_P
(
generated_pool_php
)
=
zend_get_std_object_handlers
();
ZVAL_OBJ
(
generated_pool_php
,
descriptor_pool_type
->
create_object
(
descriptor_pool_type
TSRMLS_CC
));
generated_pool
=
UNBOX
(
DescriptorPool
,
generated_pool_php
);
#else
generated_pool_php
=
descriptor_pool_type
->
create_object
(
descriptor_pool_type
TSRMLS_CC
);
generated_pool
=
(
DescriptorPool
*
)((
char
*
)
generated_pool_php
-
XtOffsetOf
(
DescriptorPool
,
std
));
#endif
}
}
static
void
descriptor_pool_init_c_instance
(
DescriptorPool
*
pool
TSRMLS_DC
)
{
zend_object_std_init
(
&
pool
->
std
,
descriptor_pool_type
TSRMLS_CC
);
//
zend_object_std_init(&pool->std, descriptor_pool_type TSRMLS_CC);
pool
->
symtab
=
upb_symtab_new
();
ALLOC_HASHTABLE
(
pool
->
pending_list
);
...
...
@@ -247,7 +347,12 @@ static void validate_msgdef(const upb_msgdef* msgdef) {
PHP_METHOD
(
DescriptorPool
,
getGeneratedPool
)
{
init_generated_pool_once
(
TSRMLS_C
);
#if PHP_MAJOR_VERSION < 7
RETURN_ZVAL
(
generated_pool_php
,
1
,
0
);
#else
++
GC_REFCOUNT
(
generated_pool_php
);
RETURN_OBJ
(
generated_pool_php
);
#endif
}
static
void
convert_to_class_name_inplace
(
char
*
class_name
,
...
...
@@ -306,7 +411,7 @@ static void convert_to_class_name_inplace(char *class_name,
PHP_METHOD
(
DescriptorPool
,
internalAddGeneratedFile
)
{
char
*
data
=
NULL
;
int
data_len
;
PHP_PROTO_SIZE
data_len
;
upb_filedef
**
files
;
size_t
i
;
...
...
@@ -335,11 +440,7 @@ PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
switch
(
upb_def_type
(
def
))
{
#define CASE_TYPE(def_type, def_type_lower, desc_type, desc_type_lower) \
case UPB_DEF_##def_type: { \
desc_type *desc; \
zval *desc_php; \
CREATE(desc_type, desc, desc_type_lower##_init_c_instance); \
BOX(desc_type, desc_php, desc, desc_type_lower##_free); \
Z_DELREF_P(desc_php); \
CREATE_HASHTABLE_VALUE(desc, desc_php, desc_type, desc_type_lower##_type); \
const upb_##def_type_lower *def_type_lower = \
upb_downcast_##def_type_lower(def); \
desc->def_type_lower = def_type_lower; \
...
...
@@ -362,14 +463,14 @@ PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
char *klass_name = ecalloc(sizeof(char), klass_name_len); \
convert_to_class_name_inplace(klass_name, fullname, prefix, \
upb_filedef_package(files[0])); \
zend_class_entry **pce;
\
if (
zend_lookup_class(klass_name, strlen(klass_name), &pce TSRMLS_CC
) == \
PHP_PROTO_CE_DECLARE pce;
\
if (
php_proto_zend_lookup_class(klass_name, strlen(klass_name), &pce
) == \
FAILURE) { \
zend_error(E_ERROR, "Generated message class %s hasn't been defined", \
klass_name); \
return; \
} else { \
desc->klass =
*pce;
\
desc->klass =
PHP_PROTO_CE_UNREF(pce);
\
} \
add_ce_obj(desc->klass, desc_php); \
efree(klass_name); \
...
...
@@ -389,7 +490,7 @@ PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
const
upb_def
*
def
=
upb_filedef_def
(
files
[
0
],
i
);
if
(
upb_def_type
(
def
)
==
UPB_DEF_MSG
)
{
const
upb_msgdef
*
msgdef
=
upb_downcast_msgdef
(
def
);
zval
*
desc_php
=
get_def_obj
(
msgdef
);
PHP_PROTO_HASHTABLE_VALUE
desc_php
=
get_def_obj
(
msgdef
);
build_class_from_descriptor
(
desc_php
TSRMLS_CC
);
}
}
...
...
@@ -397,111 +498,3 @@ PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
upb_filedef_unref
(
files
[
0
],
&
pool
);
upb_gfree
(
files
);
}
// -----------------------------------------------------------------------------
// Descriptor
// -----------------------------------------------------------------------------
static
zend_function_entry
descriptor_methods
[]
=
{
ZEND_FE_END
};
DEFINE_CLASS
(
Descriptor
,
descriptor
,
"Google
\\
Protobuf
\\
Internal
\\
Descriptor"
);
static
void
descriptor_free_c
(
Descriptor
*
self
TSRMLS_DC
)
{
if
(
self
->
layout
)
{
free_layout
(
self
->
layout
);
}
if
(
self
->
fill_handlers
)
{
upb_handlers_unref
(
self
->
fill_handlers
,
&
self
->
fill_handlers
);
}
if
(
self
->
fill_method
)
{
upb_pbdecodermethod_unref
(
self
->
fill_method
,
&
self
->
fill_method
);
}
if
(
self
->
json_fill_method
)
{
upb_json_parsermethod_unref
(
self
->
json_fill_method
,
&
self
->
json_fill_method
);
}
if
(
self
->
pb_serialize_handlers
)
{
upb_handlers_unref
(
self
->
pb_serialize_handlers
,
&
self
->
pb_serialize_handlers
);
}
if
(
self
->
json_serialize_handlers
)
{
upb_handlers_unref
(
self
->
json_serialize_handlers
,
&
self
->
json_serialize_handlers
);
}
if
(
self
->
json_serialize_handlers_preserve
)
{
upb_handlers_unref
(
self
->
json_serialize_handlers_preserve
,
&
self
->
json_serialize_handlers_preserve
);
}
}
static
void
descriptor_init_c_instance
(
Descriptor
*
desc
TSRMLS_DC
)
{
zend_object_std_init
(
&
desc
->
std
,
descriptor_type
TSRMLS_CC
);
desc
->
msgdef
=
NULL
;
desc
->
layout
=
NULL
;
desc
->
klass
=
NULL
;
desc
->
fill_handlers
=
NULL
;
desc
->
fill_method
=
NULL
;
desc
->
json_fill_method
=
NULL
;
desc
->
pb_serialize_handlers
=
NULL
;
desc
->
json_serialize_handlers
=
NULL
;
desc
->
json_serialize_handlers_preserve
=
NULL
;
}
// -----------------------------------------------------------------------------
// EnumDescriptor
// -----------------------------------------------------------------------------
static
zend_function_entry
enum_descriptor_methods
[]
=
{
ZEND_FE_END
};
DEFINE_CLASS
(
EnumDescriptor
,
enum_descriptor
,
"Google
\\
Protobuf
\\
Internal
\\
EnumDescriptor"
);
static
void
enum_descriptor_free_c
(
EnumDescriptor
*
self
TSRMLS_DC
)
{
}
static
void
enum_descriptor_init_c_instance
(
EnumDescriptor
*
self
TSRMLS_DC
)
{
zend_object_std_init
(
&
self
->
std
,
enum_descriptor_type
TSRMLS_CC
);
self
->
enumdef
=
NULL
;
self
->
klass
=
NULL
;
}
// -----------------------------------------------------------------------------
// FieldDescriptor
// -----------------------------------------------------------------------------
upb_fieldtype_t
to_fieldtype
(
upb_descriptortype_t
type
)
{
switch
(
type
)
{
#define CASE(descriptor_type, type) \
case UPB_DESCRIPTOR_TYPE_##descriptor_type: \
return UPB_TYPE_##type;
CASE
(
FLOAT
,
FLOAT
);
CASE
(
DOUBLE
,
DOUBLE
);
CASE
(
BOOL
,
BOOL
);
CASE
(
STRING
,
STRING
);
CASE
(
BYTES
,
BYTES
);
CASE
(
MESSAGE
,
MESSAGE
);
CASE
(
GROUP
,
MESSAGE
);
CASE
(
ENUM
,
ENUM
);
CASE
(
INT32
,
INT32
);
CASE
(
INT64
,
INT64
);
CASE
(
UINT32
,
UINT32
);
CASE
(
UINT64
,
UINT64
);
CASE
(
SINT32
,
INT32
);
CASE
(
SINT64
,
INT64
);
CASE
(
FIXED32
,
UINT32
);
CASE
(
FIXED64
,
UINT64
);
CASE
(
SFIXED32
,
INT32
);
CASE
(
SFIXED64
,
INT64
);
#undef CONVERT
}
zend_error
(
E_ERROR
,
"Unknown field type."
);
return
0
;
}
php/ext/google/protobuf/encode_decode.c
View file @
190b5270
...
...
@@ -197,7 +197,7 @@ static const void *newoneofhandlerdata(upb_handlers *h,
static
void
*
startseq_handler
(
void
*
closure
,
const
void
*
hd
)
{
MessageHeader
*
msg
=
closure
;
const
size_t
*
ofs
=
hd
;
return
(
void
*
)(
*
DEREF
(
msg
,
*
ofs
,
zval
*
*
));
return
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
*
ofs
,
CACHED_VALUE
*
));
}
// Handlers that append primitive values to a repeated field.
...
...
@@ -206,9 +206,8 @@ static void *startseq_handler(void* closure, const void* hd) {
ctype val) { \
zval* array = (zval*)closure; \
TSRMLS_FETCH(); \
RepeatedField* intern = \
(RepeatedField*)zend_object_store_get_object(array TSRMLS_CC); \
repeated_field_push_native(intern, &val TSRMLS_CC); \
RepeatedField* intern = UNBOX(RepeatedField, array); \
repeated_field_push_native(intern, &val); \
return true; \
}
...
...
@@ -226,15 +225,19 @@ static void* appendstr_handler(void *closure,
size_t
size_hint
)
{
zval
*
array
=
(
zval
*
)
closure
;
TSRMLS_FETCH
();
RepeatedField
*
intern
=
(
RepeatedField
*
)
zend_object_store_get_object
(
array
TSRMLS_CC
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
array
);
#if PHP_MAJOR_VERSION < 7
zval
*
str
;
MAKE_STD_ZVAL
(
str
);
ZVAL_STRING
(
str
,
""
,
1
);
repeated_field_push_native
(
intern
,
&
str
TSRMLS_CC
);
PHP_PROTO_ZVAL_STRING
(
str
,
""
,
1
);
repeated_field_push_native
(
intern
,
&
str
);
return
(
void
*
)
str
;
#else
zend_string
*
str
=
zend_string_init
(
""
,
0
,
1
);
repeated_field_push_native
(
intern
,
&
str
);
return
intern
;
#endif
}
// Appends a 'bytes' string to a repeated field.
...
...
@@ -243,24 +246,58 @@ static void* appendbytes_handler(void *closure,
size_t
size_hint
)
{
zval
*
array
=
(
zval
*
)
closure
;
TSRMLS_FETCH
();
RepeatedField
*
intern
=
(
RepeatedField
*
)
zend_object_store_get_object
(
array
TSRMLS_CC
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
array
);
#if PHP_MAJOR_VERSION < 7
zval
*
str
;
MAKE_STD_ZVAL
(
str
);
ZVAL_STRING
(
str
,
""
,
1
);
repeated_field_push_native
(
intern
,
&
str
TSRMLS_CC
);
PHP_PROTO_ZVAL_STRING
(
str
,
""
,
1
);
repeated_field_push_native
(
intern
,
&
str
);
return
(
void
*
)
str
;
#else
zend_string
*
str
=
zend_string_init
(
""
,
0
,
1
);
repeated_field_push_native
(
intern
,
&
str
);
return
intern
;
#endif
}
static
bool
int32_handler
(
void
*
closure
,
const
void
*
hd
,
int32_t
val
)
{
MessageHeader
*
msg
=
(
MessageHeader
*
)
closure
;
const
size_t
*
ofs
=
hd
;
DEREF
(
message_data
(
msg
),
*
ofs
,
int32_t
)
=
val
;
return
true
;
}
// Handlers that append primitive values to a repeated field.
#define DEFINE_SINGULAR_HANDLER(type, ctype) \
static bool type##_handler(void* closure, const void* hd, \
ctype val) { \
MessageHeader* msg = (MessageHeader*)closure; \
const size_t *ofs = hd; \
DEREF(message_data(msg), *ofs, ctype) = val; \
return true; \
}
DEFINE_SINGULAR_HANDLER
(
bool
,
bool
)
// DEFINE_SINGULAR_HANDLER(int32, int32_t)
DEFINE_SINGULAR_HANDLER
(
uint32
,
uint32_t
)
DEFINE_SINGULAR_HANDLER
(
float
,
float
)
DEFINE_SINGULAR_HANDLER
(
int64
,
int64_t
)
DEFINE_SINGULAR_HANDLER
(
uint64
,
uint64_t
)
DEFINE_SINGULAR_HANDLER
(
double
,
double
)
#undef DEFINE_SINGULAR_HANDLER
#if PHP_MAJOR_VERSION < 7
static
void
*
empty_php_string
(
zval
**
value_ptr
)
{
SEPARATE_ZVAL_IF_NOT_REF
(
value_ptr
);
zval
*
str
=
*
value_ptr
;
zval_dtor
(
str
);
ZVAL_STRINGL
(
str
,
""
,
0
,
1
);
return
(
void
*
)
str
;
return
(
void
*
)(
*
value_ptr
);
}
#else
static
void
*
empty_php_string
(
zval
*
value_ptr
)
{
return
value_ptr
;
}
#endif
// Sets a non-repeated string field in a message.
static
void
*
str_handler
(
void
*
closure
,
...
...
@@ -268,7 +305,7 @@ static void* str_handler(void *closure,
size_t
size_hint
)
{
MessageHeader
*
msg
=
closure
;
const
size_t
*
ofs
=
hd
;
return
empty_php_string
(
DEREF
(
m
sg
,
*
ofs
,
zval
*
*
));
return
empty_php_string
(
DEREF
(
m
essage_data
(
msg
),
*
ofs
,
CACHED_VALUE
*
));
}
// Sets a non-repeated 'bytes' field in a message.
...
...
@@ -277,52 +314,73 @@ static void* bytes_handler(void *closure,
size_t
size_hint
)
{
MessageHeader
*
msg
=
closure
;
const
size_t
*
ofs
=
hd
;
return
empty_php_string
(
DEREF
(
m
sg
,
*
ofs
,
zval
*
*
));
return
empty_php_string
(
DEREF
(
m
essage_data
(
msg
),
*
ofs
,
CACHED_VALUE
*
));
}
static
size_t
stringdata_handler
(
void
*
closure
,
const
void
*
hd
,
const
char
*
str
,
size_t
len
,
const
upb_bufhandle
*
handle
)
{
zval
*
php_str
=
(
zval
*
)
closure
;
#if PHP_MAJOR_VERSION < 7
// Oneof string/bytes fields may have NULL initial value, which doesn't need
// to be freed.
if
(
Z_TYPE_P
(
php_str
)
==
IS_STRING
&&
!
IS_INTERNED
(
Z_STRVAL_P
(
php_str
)))
{
FREE
(
Z_STRVAL_P
(
php_str
));
}
ZVAL_STRINGL
(
php_str
,
str
,
len
,
1
);
#else
if
(
Z_TYPE_P
(
php_str
)
==
IS_STRING
)
{
zend_string_release
(
Z_STR_P
(
php_str
));
}
ZVAL_NEW_STR
(
php_str
,
zend_string_init
(
str
,
len
,
0
));
#endif
return
len
;
}
char
*
old_str
=
Z_STRVAL_P
(
php_str
);
size_t
old_len
=
Z_STRLEN_P
(
php_str
);
assert
(
old_str
!=
NULL
);
char
*
new_str
=
emalloc
(
old_len
+
len
+
1
)
;
#if PHP_MAJOR_VERSION >= 7
static
size_t
zendstringdata_handler
(
void
*
closure
,
const
void
*
hd
,
const
char
*
str
,
size_t
len
,
const
upb_bufhandle
*
handle
)
{
RepeatedField
*
intern
=
(
RepeatedField
*
)
closure
;
memcpy
(
new_str
,
old_str
,
old_len
);
memcpy
(
new_str
+
old_len
,
str
,
len
);
new_str
[
old_len
+
len
]
=
0
;
FREE
(
old_str
);
unsigned
char
memory
[
NATIVE_SLOT_MAX_SIZE
];
memset
(
memory
,
0
,
NATIVE_SLOT_MAX_SIZE
);
*
(
zend_string
**
)
memory
=
zend_string_init
(
str
,
len
,
0
);
Z_STRVAL_P
(
php_str
)
=
new_str
;
Z_STRLEN_P
(
php_str
)
=
old_len
+
len
;
HashTable
*
ht
=
PHP_PROTO_HASH_OF
(
intern
->
array
);
int
index
=
zend_hash_num_elements
(
ht
)
-
1
;
php_proto_zend_hash_index_update
(
ht
,
index
,
memory
,
sizeof
(
zend_string
*
),
NULL
);
return
len
;
}
#endif
// Appends a submessage to a repeated field.
static
void
*
appendsubmsg_handler
(
void
*
closure
,
const
void
*
hd
)
{
zval
*
array
=
(
zval
*
)
closure
;
TSRMLS_FETCH
();
RepeatedField
*
intern
=
(
RepeatedField
*
)
zend_object_store_get_object
(
array
TSRMLS_CC
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
array
);
const
submsg_handlerdata_t
*
submsgdata
=
hd
;
zval
*
subdesc_php
=
get_def_obj
((
void
*
)
submsgdata
->
md
);
Descriptor
*
subdesc
=
zend_object_store_get_object
(
subdesc_php
TSRMLS_CC
);
Descriptor
*
subdesc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_def_obj
((
void
*
)
submsgdata
->
md
)
);
zend_class_entry
*
subklass
=
subdesc
->
klass
;
MessageHeader
*
submsg
;
#if PHP_MAJOR_VERSION < 7
zval
*
val
=
NULL
;
MAKE_STD_ZVAL
(
val
);
Z_TYPE_P
(
val
)
=
IS_OBJECT
;
Z_OBJVAL_P
(
val
)
=
subklass
->
create_object
(
subklass
TSRMLS_CC
);
repeated_field_push_native
(
intern
,
&
val
TSRMLS_CC
);
ZVAL_OBJ
(
val
,
subklass
->
create_object
(
subklass
TSRMLS_CC
));
repeated_field_push_native
(
intern
,
&
val
);
submsg
=
UNBOX
(
MessageHeader
,
val
);
#else
zend_object
*
obj
=
subklass
->
create_object
(
subklass
TSRMLS_CC
);
repeated_field_push_native
(
intern
,
&
obj
);
submsg
=
(
MessageHeader
*
)((
char
*
)
obj
-
XtOffsetOf
(
MessageHeader
,
std
));
#endif
custom_data_init
(
subklass
,
submsg
PHP_PROTO_TSRMLS_CC
);
submsg
=
zend_object_store_get_object
(
val
TSRMLS_CC
);
return
submsg
;
}
...
...
@@ -330,26 +388,35 @@ static void *appendsubmsg_handler(void *closure, const void *hd) {
static
void
*
submsg_handler
(
void
*
closure
,
const
void
*
hd
)
{
MessageHeader
*
msg
=
closure
;
const
submsg_handlerdata_t
*
submsgdata
=
hd
;
zval
*
subdesc_php
=
get_def_obj
((
void
*
)
submsgdata
->
md
);
TSRMLS_FETCH
();
Descriptor
*
subdesc
=
zend_object_store_get_object
(
subdesc_php
TSRMLS_CC
);
Descriptor
*
subdesc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_def_obj
((
void
*
)
submsgdata
->
md
));
zend_class_entry
*
subklass
=
subdesc
->
klass
;
zval
*
submsg_php
;
MessageHeader
*
submsg
;
if
(
Z_TYPE_P
(
*
DEREF
(
msg
,
submsgdata
->
ofs
,
zval
**
))
==
IS_NULL
)
{
if
(
Z_TYPE_P
(
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
submsgdata
->
ofs
,
CACHED_VALUE
*
)))
==
IS_NULL
)
{
#if PHP_MAJOR_VERSION < 7
zval
*
val
=
NULL
;
MAKE_STD_ZVAL
(
val
);
Z_TYPE_P
(
val
)
=
IS_OBJECT
;
Z_OBJVAL_P
(
val
)
=
subklass
->
create_object
(
subklass
TSRMLS_CC
);
zval_ptr_dtor
(
DEREF
(
msg
,
submsgdata
->
ofs
,
zval
**
));
*
DEREF
(
msg
,
submsgdata
->
ofs
,
zval
**
)
=
val
;
ZVAL_OBJ
(
val
,
subklass
->
create_object
(
subklass
TSRMLS_CC
));
MessageHeader
*
intern
=
UNBOX
(
MessageHeader
,
val
);
custom_data_init
(
subklass
,
intern
PHP_PROTO_TSRMLS_CC
);
php_proto_zval_ptr_dtor
(
*
DEREF
(
message_data
(
msg
),
submsgdata
->
ofs
,
zval
**
));
*
DEREF
(
message_data
(
msg
),
submsgdata
->
ofs
,
zval
**
)
=
val
;
#else
zend_object
*
obj
=
subklass
->
create_object
(
subklass
TSRMLS_CC
);
ZVAL_OBJ
(
DEREF
(
message_data
(
msg
),
submsgdata
->
ofs
,
zval
*
),
obj
);
MessageHeader
*
intern
=
UNBOX_HASHTABLE_VALUE
(
MessageHeader
,
obj
);
custom_data_init
(
subklass
,
intern
PHP_PROTO_TSRMLS_CC
);
#endif
}
submsg_php
=
*
DEREF
(
msg
,
submsgdata
->
ofs
,
zval
**
);
submsg_php
=
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
submsgdata
->
ofs
,
CACHED_VALUE
*
));
submsg
=
zend_object_store_get_object
(
submsg_php
TSRMLS_CC
);
submsg
=
UNBOX
(
MessageHeader
,
submsg_php
);
return
submsg
;
}
...
...
@@ -372,32 +439,52 @@ typedef struct {
// submessage. When the submessage ends, another handler is called to insert the
// value into the map.
typedef
struct
{
zval
*
map
;
char
key_storage
[
NATIVE_SLOT_MAX_SIZE
];
char
value_storage
[
NATIVE_SLOT_MAX_SIZE
];
}
map_parse_frame_t
;
}
map_parse_frame_
data_
t
;
static
void
map_slot_init
(
void
*
memory
,
upb_fieldtype_t
type
)
{
PHP_PROTO_WRAP_OBJECT_START
(
map_parse_frame_t
)
map_parse_frame_data_t
*
data
;
// Place needs to be consistent with
// MessageHeader.
zval
*
map
;
// In php7, we cannot allocate zval dynamically. So we need to add zval here
// to help decoding.
zval
key_zval
;
zval
value_zval
;
PHP_PROTO_WRAP_OBJECT_END
typedef
struct
map_parse_frame_t
map_parse_frame_t
;
static
void
map_slot_init
(
void
*
memory
,
upb_fieldtype_t
type
,
zval
*
cache
)
{
switch
(
type
)
{
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
#if PHP_MAJOR_VERSION < 7
// Store zval** in memory in order to be consistent with the layout of
// singular fields.
zval
**
holder
=
ALLOC
(
zval
*
);
zval
*
tmp
;
MAKE_STD_ZVAL
(
tmp
);
ZVAL_STRINGL
(
tmp
,
""
,
0
,
1
);
PHP_PROTO_
ZVAL_STRINGL
(
tmp
,
""
,
0
,
1
);
*
holder
=
tmp
;
*
(
zval
***
)
memory
=
holder
;
#else
*
(
zval
**
)
memory
=
cache
;
PHP_PROTO_ZVAL_STRINGL
(
*
(
zval
**
)
memory
,
""
,
0
,
1
);
#endif
break
;
}
case
UPB_TYPE_MESSAGE
:
{
#if PHP_MAJOR_VERSION < 7
zval
**
holder
=
ALLOC
(
zval
*
);
zval
*
tmp
;
MAKE_STD_ZVAL
(
tmp
);
ZVAL_NULL
(
tmp
);
*
holder
=
tmp
;
*
(
zval
***
)
memory
=
holder
;
#else
*
(
zval
**
)
memory
=
cache
;
ZVAL_NULL
(
*
(
zval
**
)
memory
);
#endif
break
;
}
default:
...
...
@@ -410,9 +497,13 @@ static void map_slot_uninit(void* memory, upb_fieldtype_t type) {
case
UPB_TYPE_MESSAGE
:
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
#if PHP_MAJOR_VERSION < 7
zval
**
holder
=
*
(
zval
***
)
memory
;
zval_ptr_dtor
(
holder
);
php_proto_zval_ptr_dtor
(
*
holder
);
FREE
(
holder
);
#else
php_proto_zval_ptr_dtor
(
*
(
zval
**
)
memory
);
#endif
break
;
}
default:
...
...
@@ -424,7 +515,11 @@ static void map_slot_key(upb_fieldtype_t type, const void* from,
const
char
**
keyval
,
size_t
*
length
)
{
if
(
type
==
UPB_TYPE_STRING
)
{
#if PHP_MAJOR_VERSION < 7
zval
*
key_php
=
**
(
zval
***
)
from
;
#else
zval
*
key_php
=
*
(
zval
**
)
from
;
#endif
*
keyval
=
Z_STRVAL_P
(
key_php
);
*
length
=
Z_STRLEN_P
(
key_php
);
}
else
{
...
...
@@ -444,6 +539,7 @@ static void map_slot_value(upb_fieldtype_t type, const void* from,
memset
(
to
,
0
,
native_slot_size
(
type
));
switch
(
type
)
{
#if PHP_MAJOR_VERSION < 7
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
case
UPB_TYPE_MESSAGE
:
{
...
...
@@ -451,6 +547,17 @@ static void map_slot_value(upb_fieldtype_t type, const void* from,
Z_ADDREF_PP
((
zval
**
)
to
);
break
;
}
#else
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
*
(
zend_string
**
)
to
=
Z_STR_P
(
*
(
zval
**
)
from
);
zend_string_addref
(
*
(
zend_string
**
)
to
);
break
;
case
UPB_TYPE_MESSAGE
:
*
(
zend_object
**
)
to
=
Z_OBJ_P
(
*
(
zval
**
)
from
);
++
GC_REFCOUNT
(
*
(
zend_object
**
)
to
);
break
;
#endif
default:
len
=
native_slot_size
(
type
);
memcpy
(
to
,
from
,
len
);
...
...
@@ -462,13 +569,17 @@ static void map_slot_value(upb_fieldtype_t type, const void* from,
static
void
*
startmapentry_handler
(
void
*
closure
,
const
void
*
hd
)
{
MessageHeader
*
msg
=
closure
;
const
map_handlerdata_t
*
mapdata
=
hd
;
zval
*
map
=
*
DEREF
(
msg
,
mapdata
->
ofs
,
zval
**
);
zval
*
map
=
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
mapdata
->
ofs
,
CACHED_VALUE
*
));
map_parse_frame_t
*
frame
=
ALLOC
(
map_parse_frame_t
);
frame
->
data
=
ALLOC
(
map_parse_frame_data_t
);
frame
->
map
=
map
;
map_slot_init
(
&
frame
->
key_storage
,
mapdata
->
key_field_type
);
map_slot_init
(
&
frame
->
value_storage
,
mapdata
->
value_field_type
);
map_slot_init
(
&
frame
->
data
->
key_storage
,
mapdata
->
key_field_type
,
&
frame
->
key_zval
);
map_slot_init
(
&
frame
->
data
->
value_storage
,
mapdata
->
value_field_type
,
&
frame
->
value_zval
);
return
frame
;
}
...
...
@@ -480,19 +591,20 @@ static bool endmap_handler(void* closure, const void* hd, upb_status* s) {
const
map_handlerdata_t
*
mapdata
=
hd
;
TSRMLS_FETCH
();
Map
*
map
=
(
Map
*
)
zend_object_store_get_object
(
frame
->
map
TSRMLS_CC
);
Map
*
map
=
UNBOX
(
Map
,
frame
->
map
);
const
char
*
keyval
=
NULL
;
upb_value
v
;
size_t
length
;
map_slot_key
(
map
->
key_type
,
&
frame
->
key_storage
,
&
keyval
,
&
length
);
map_slot_value
(
map
->
value_type
,
&
frame
->
value_storage
,
&
v
);
map_slot_key
(
map
->
key_type
,
&
frame
->
data
->
key_storage
,
&
keyval
,
&
length
);
map_slot_value
(
map
->
value_type
,
&
frame
->
data
->
value_storage
,
&
v
);
map_index_set
(
map
,
keyval
,
length
,
v
);
map_slot_uninit
(
&
frame
->
key_storage
,
mapdata
->
key_field_type
);
map_slot_uninit
(
&
frame
->
value_storage
,
mapdata
->
value_field_type
);
map_slot_uninit
(
&
frame
->
data
->
key_storage
,
mapdata
->
key_field_type
);
map_slot_uninit
(
&
frame
->
data
->
value_storage
,
mapdata
->
value_field_type
);
FREE
(
frame
->
data
);
FREE
(
frame
);
return
true
;
...
...
@@ -529,12 +641,13 @@ static map_handlerdata_t* new_map_handlerdata(
// Handlers that set primitive values in oneofs.
#define DEFINE_ONEOF_HANDLER(type, ctype) \
static bool oneof##type##_handler(void
*closure, const void *hd,
\
static bool oneof##type##_handler(void
* closure, const void* hd,
\
ctype val) { \
const oneof_handlerdata_t *oneofdata = hd; \
DEREF(closure, oneofdata->case_ofs, uint32_t) = \
const oneof_handlerdata_t* oneofdata = hd; \
MessageHeader* msg = (MessageHeader*)closure; \
DEREF(message_data(closure), oneofdata->case_ofs, uint32_t) = \
oneofdata->oneof_case_num; \
DEREF(
closure, oneofdata->ofs, ctype) = val;
\
DEREF(
message_data(closure), oneofdata->ofs, ctype) = val;
\
return true; \
}
...
...
@@ -548,74 +661,71 @@ DEFINE_ONEOF_HANDLER(double, double)
#undef DEFINE_ONEOF_HANDLER
// Handlers for strings in a oneof.
static
void
*
oneof
str
_handler
(
void
*
closure
,
// Handlers for string
/byte
s in a oneof.
static
void
*
oneof
bytes
_handler
(
void
*
closure
,
const
void
*
hd
,
size_t
size_hint
)
{
MessageHeader
*
msg
=
closure
;
const
oneof_handlerdata_t
*
oneofdata
=
hd
;
DEREF
(
m
sg
,
oneofdata
->
case_ofs
,
uint32_t
)
=
DEREF
(
m
essage_data
(
msg
)
,
oneofdata
->
case_ofs
,
uint32_t
)
=
oneofdata
->
oneof_case_num
;
DEREF
(
m
sg
,
oneofdata
->
ofs
,
zval
*
*
)
=
DEREF
(
m
essage_data
(
msg
),
oneofdata
->
ofs
,
CACHED_VALUE
*
)
=
&
(
msg
->
std
.
properties_table
)[
oneofdata
->
property_ofs
];
return
empty_php_string
(
DEREF
(
msg
,
oneofdata
->
ofs
,
zval
**
));
return
empty_php_string
(
DEREF
(
message_data
(
msg
),
oneofdata
->
ofs
,
CACHED_VALUE
*
));
}
static
void
*
oneof
bytes
_handler
(
void
*
closure
,
static
void
*
oneof
str
_handler
(
void
*
closure
,
const
void
*
hd
,
size_t
size_hint
)
{
MessageHeader
*
msg
=
closure
;
const
oneof_handlerdata_t
*
oneofdata
=
hd
;
DEREF
(
msg
,
oneofdata
->
case_ofs
,
uint32_t
)
=
oneofdata
->
oneof_case_num
;
DEREF
(
msg
,
oneofdata
->
ofs
,
zval
**
)
=
&
(
msg
->
std
.
properties_table
)[
oneofdata
->
property_ofs
];
// TODO(teboring): Add it back.
// rb_enc_associate(str, kRubyString8bitEncoding);
SEPARATE_ZVAL_IF_NOT_REF
(
DEREF
(
msg
,
oneofdata
->
ofs
,
zval
**
));
zval
*
str
=
*
DEREF
(
msg
,
oneofdata
->
ofs
,
zval
**
);
zval_dtor
(
str
);
ZVAL_STRINGL
(
str
,
""
,
0
,
1
);
return
(
void
*
)
str
;
return
oneofbytes_handler
(
closure
,
hd
,
size_hint
);
}
// Handler for a submessage field in a oneof.
static
void
*
oneofsubmsg_handler
(
void
*
closure
,
const
void
*
hd
)
{
MessageHeader
*
msg
=
closure
;
const
oneof_handlerdata_t
*
oneofdata
=
hd
;
uint32_t
oldcase
=
DEREF
(
msg
,
oneofdata
->
case_ofs
,
uint32_t
);
zval
*
subdesc_php
=
get_def_obj
((
void
*
)
oneofdata
->
md
);
uint32_t
oldcase
=
DEREF
(
message_data
(
msg
),
oneofdata
->
case_ofs
,
uint32_t
);
TSRMLS_FETCH
();
Descriptor
*
subdesc
=
zend_object_store_get_object
(
subdesc_php
TSRMLS_CC
);
Descriptor
*
subdesc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_def_obj
((
void
*
)
oneofdata
->
md
));
zend_class_entry
*
subklass
=
subdesc
->
klass
;
zval
*
submsg_php
;
MessageHeader
*
submsg
;
if
(
oldcase
!=
oneofdata
->
oneof_case_num
)
{
DEREF
(
msg
,
oneofdata
->
ofs
,
zval
**
)
=
// Ideally, we should clean up the old data. However, we don't even know the
// type of the old data. So, we will defer the desctruction of the old data
// to the time that containing message's destroyed or the same oneof field
// is accessed again and find that the old data hasn't been cleaned.
DEREF
(
message_data
(
msg
),
oneofdata
->
ofs
,
CACHED_VALUE
*
)
=
&
(
msg
->
std
.
properties_table
)[
oneofdata
->
property_ofs
];
}
if
(
Z_TYPE_P
(
*
DEREF
(
msg
,
oneofdata
->
ofs
,
zval
**
))
==
IS_NULL
)
{
zval
*
val
=
NULL
;
MAKE_STD_ZVAL
(
val
);
Z_TYPE_P
(
val
)
=
IS_OBJECT
;
Z_OBJVAL_P
(
val
)
=
subklass
->
create_object
(
subklass
TSRMLS_CC
);
// Old data was't cleaned when the oneof was accessed from another field.
if
(
Z_TYPE_P
(
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
oneofdata
->
ofs
,
CACHED_VALUE
*
)))
!=
IS_NULL
)
{
php_proto_zval_ptr_dtor
(
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
oneofdata
->
ofs
,
CACHED_VALUE
*
)));
}
zval_ptr_dtor
(
DEREF
(
msg
,
oneofdata
->
ofs
,
zval
**
));
*
DEREF
(
msg
,
oneofdata
->
ofs
,
zval
**
)
=
val
;
// Create new message.
ZVAL_OBJ
(
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
oneofdata
->
ofs
,
CACHED_VALUE
*
)),
subklass
->
create_object
(
subklass
TSRMLS_CC
));
}
DEREF
(
m
sg
,
oneofdata
->
case_ofs
,
uint32_t
)
=
DEREF
(
m
essage_data
(
msg
)
,
oneofdata
->
case_ofs
,
uint32_t
)
=
oneofdata
->
oneof_case_num
;
submsg_php
=
*
DEREF
(
msg
,
oneofdata
->
ofs
,
zval
**
);
submsg
=
zend_object_store_get_object
(
submsg_php
TSRMLS_CC
);
submsg_php
=
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
oneofdata
->
ofs
,
CACHED_VALUE
*
));
submsg
=
UNBOX
(
MessageHeader
,
submsg_php
);
custom_data_init
(
subklass
,
submsg
PHP_PROTO_TSRMLS_CC
);
return
submsg
;
}
...
...
@@ -652,7 +762,11 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
upb_handlers_setstartstr
(
h
,
f
,
is_bytes
?
appendbytes_handler
:
appendstr_handler
,
NULL
);
#if PHP_MAJOR_VERSION < 7
upb_handlers_setstring
(
h
,
f
,
stringdata_handler
,
NULL
);
#else
upb_handlers_setstring
(
h
,
f
,
zendstringdata_handler
,
NULL
);
#endif
break
;
}
case
UPB_TYPE_MESSAGE
:
{
...
...
@@ -670,16 +784,26 @@ static void add_handlers_for_singular_field(upb_handlers *h,
const
upb_fielddef
*
f
,
size_t
offset
)
{
switch
(
upb_fielddef_type
(
f
))
{
case
UPB_TYPE_BOOL
:
case
UPB_TYPE_INT32
:
case
UPB_TYPE_UINT32
:
case
UPB_TYPE_ENUM
:
case
UPB_TYPE_FLOAT
:
case
UPB_TYPE_INT64
:
case
UPB_TYPE_UINT64
:
case
UPB_TYPE_DOUBLE
:
upb_msg_setscalarhandler
(
h
,
f
,
offset
,
-
1
);
break
;
#define SET_HANDLER(utype, ltype) \
case utype: { \
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; \
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset)); \
upb_handlers_set##ltype(h, f, ltype##_handler, &attr); \
break; \
}
SET_HANDLER
(
UPB_TYPE_BOOL
,
bool
);
SET_HANDLER
(
UPB_TYPE_INT32
,
int32
);
SET_HANDLER
(
UPB_TYPE_UINT32
,
uint32
);
SET_HANDLER
(
UPB_TYPE_ENUM
,
int32
);
SET_HANDLER
(
UPB_TYPE_FLOAT
,
float
);
SET_HANDLER
(
UPB_TYPE_INT64
,
int64
);
SET_HANDLER
(
UPB_TYPE_UINT64
,
uint64
);
SET_HANDLER
(
UPB_TYPE_DOUBLE
,
double
);
#undef SET_HANDLER
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
bool
is_bytes
=
upb_fielddef_type
(
f
)
==
UPB_TYPE_BYTES
;
...
...
@@ -730,9 +854,11 @@ static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
upb_handlers_setendmsg
(
h
,
endmap_handler
,
&
attr
);
add_handlers_for_singular_field
(
h
,
key_field
,
offsetof
(
map_parse_frame_t
,
key_storage
));
offsetof
(
map_parse_frame_data_t
,
key_storage
));
add_handlers_for_singular_field
(
h
,
value_field
,
offsetof
(
map_parse_frame_t
,
value_storage
));
offsetof
(
map_parse_frame_data_t
,
value_storage
));
}
// Set up handlers for a oneof field.
...
...
@@ -787,8 +913,8 @@ static void add_handlers_for_message(const void* closure,
upb_handlers
*
h
)
{
const
upb_msgdef
*
msgdef
=
upb_handlers_msgdef
(
h
);
TSRMLS_FETCH
();
Descriptor
*
desc
=
(
Descriptor
*
)
zend_object_store_get_object
(
get_def_obj
((
void
*
)
msgdef
)
TSRMLS_CC
);
Descriptor
*
desc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_def_obj
((
void
*
)
msgdef
)
);
upb_msg_field_iter
i
;
// If this is a mapentry message type, set up a special set of handlers and
...
...
@@ -810,13 +936,11 @@ static void add_handlers_for_message(const void* closure,
!
upb_msg_field_done
(
&
i
);
upb_msg_field_next
(
&
i
))
{
const
upb_fielddef
*
f
=
upb_msg_iter_field
(
&
i
);
size_t
offset
=
desc
->
layout
->
fields
[
upb_fielddef_index
(
f
)].
offset
+
sizeof
(
MessageHeader
);
size_t
offset
=
desc
->
layout
->
fields
[
upb_fielddef_index
(
f
)].
offset
;
if
(
upb_fielddef_containingoneof
(
f
))
{
size_t
oneof_case_offset
=
desc
->
layout
->
fields
[
upb_fielddef_index
(
f
)].
case_offset
+
sizeof
(
MessageHeader
);
desc
->
layout
->
fields
[
upb_fielddef_index
(
f
)].
case_offset
;
int
property_cache_index
=
desc
->
layout
->
fields
[
upb_fielddef_index
(
f
)].
cache_index
;
add_handlers_for_oneof_field
(
h
,
f
,
offset
,
oneof_case_offset
,
...
...
@@ -883,6 +1007,8 @@ static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
static
void
putmsg
(
zval
*
msg
,
const
Descriptor
*
desc
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
);
static
void
putrawmsg
(
MessageHeader
*
msg
,
const
Descriptor
*
desc
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
);
static
void
putstr
(
zval
*
str
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
);
...
...
@@ -891,6 +1017,8 @@ static void putrawstr(const char* str, int len, const upb_fielddef* f,
static
void
putsubmsg
(
zval
*
submsg
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
);
static
void
putrawsubmsg
(
MessageHeader
*
submsg
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
);
static
void
putarray
(
zval
*
array
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
);
...
...
@@ -933,8 +1061,14 @@ static void put_optional_value(const void* memory, int len, const upb_fielddef*
putrawstr
(
memory
,
len
,
f
,
sink
);
break
;
case
UPB_TYPE_MESSAGE
:
{
zval
*
submsg
=
*
(
zval
**
)
memory
;
putsubmsg
(
submsg
,
f
,
sink
,
depth
TSRMLS_CC
);
#if PHP_MAJOR_VERSION < 7
MessageHeader
*
submsg
=
UNBOX
(
MessageHeader
,
*
(
zval
**
)
memory
);
#else
MessageHeader
*
submsg
=
(
MessageHeader
*
)((
char
*
)(
*
(
zend_object
**
)
memory
)
-
XtOffsetOf
(
MessageHeader
,
std
));
#endif
putrawsubmsg
(
submsg
,
f
,
sink
,
depth
TSRMLS_CC
);
break
;
}
default:
...
...
@@ -947,7 +1081,11 @@ static const char* raw_value(void* memory, const upb_fielddef* f) {
switch
(
upb_fielddef_type
(
f
))
{
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
#if PHP_MAJOR_VERSION < 7
return
Z_STRVAL_PP
((
zval
**
)
memory
);
#else
return
ZSTR_VAL
(
*
(
zend_string
**
)
memory
);
#endif
break
;
default:
return
memory
;
...
...
@@ -958,8 +1096,11 @@ static int raw_value_len(void* memory, int len, const upb_fielddef* f) {
switch
(
upb_fielddef_type
(
f
))
{
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
#if PHP_MAJOR_VERSION < 7
return
Z_STRLEN_PP
((
zval
**
)
memory
);
break
;
#else
return
ZSTR_LEN
(
*
(
zend_string
**
)
memory
);
#endif
default:
return
len
;
}
...
...
@@ -967,7 +1108,6 @@ static int raw_value_len(void* memory, int len, const upb_fielddef* f) {
static
void
putmap
(
zval
*
map
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
)
{
Map
*
self
;
upb_sink
subsink
;
const
upb_fielddef
*
key_field
;
const
upb_fielddef
*
value_field
;
...
...
@@ -975,8 +1115,7 @@ static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink,
int
len
,
size
;
assert
(
map
!=
NULL
);
Map
*
intern
=
(
Map
*
)
zend_object_store_get_object
(
map
TSRMLS_CC
);
Map
*
intern
=
UNBOX
(
Map
,
map
);
size
=
upb_strtable_count
(
&
intern
->
table
);
if
(
size
==
0
)
return
;
...
...
@@ -1013,6 +1152,12 @@ static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink,
static
void
putmsg
(
zval
*
msg_php
,
const
Descriptor
*
desc
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
)
{
MessageHeader
*
msg
=
UNBOX
(
MessageHeader
,
msg_php
);
putrawmsg
(
msg
,
desc
,
sink
,
depth
TSRMLS_CC
);
}
static
void
putrawmsg
(
MessageHeader
*
msg
,
const
Descriptor
*
desc
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
)
{
upb_msg_field_iter
i
;
upb_status
status
;
...
...
@@ -1025,21 +1170,18 @@ static void putmsg(zval* msg_php, const Descriptor* desc, upb_sink* sink,
"Maximum recursion depth exceeded during encoding."
);
}
MessageHeader
*
msg
=
zend_object_store_get_object
(
msg_php
TSRMLS_CC
);
for
(
upb_msg_field_begin
(
&
i
,
desc
->
msgdef
);
!
upb_msg_field_done
(
&
i
);
upb_msg_field_next
(
&
i
))
{
upb_fielddef
*
f
=
upb_msg_iter_field
(
&
i
);
uint32_t
offset
=
desc
->
layout
->
fields
[
upb_fielddef_index
(
f
)].
offset
+
sizeof
(
MessageHeader
);
uint32_t
offset
=
desc
->
layout
->
fields
[
upb_fielddef_index
(
f
)].
offset
;
if
(
upb_fielddef_containingoneof
(
f
))
{
uint32_t
oneof_case_offset
=
desc
->
layout
->
fields
[
upb_fielddef_index
(
f
)].
case_offset
+
sizeof
(
MessageHeader
);
desc
->
layout
->
fields
[
upb_fielddef_index
(
f
)].
case_offset
;
// For a oneof, check that this field is actually present -- skip all the
// below if not.
if
(
DEREF
(
msg
,
oneof_case_offset
,
uint32_t
)
!=
upb_fielddef_number
(
f
))
{
if
(
DEREF
(
message_data
(
msg
),
oneof_case_offset
,
uint32_t
)
!=
upb_fielddef_number
(
f
))
{
continue
;
}
// Otherwise, fall through to the appropriate singular-field handler
...
...
@@ -1047,28 +1189,33 @@ static void putmsg(zval* msg_php, const Descriptor* desc, upb_sink* sink,
}
if
(
is_map_field
(
f
))
{
zval
*
map
=
*
DEREF
(
msg
,
offset
,
zval
**
);
zval
*
map
=
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
offset
,
CACHED_VALUE
*
));
if
(
map
!=
NULL
)
{
putmap
(
map
,
f
,
sink
,
depth
TSRMLS_CC
);
}
}
else
if
(
upb_fielddef_isseq
(
f
))
{
zval
*
array
=
*
DEREF
(
msg
,
offset
,
zval
**
);
zval
*
array
=
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
offset
,
CACHED_VALUE
*
));
if
(
array
!=
NULL
)
{
putarray
(
array
,
f
,
sink
,
depth
TSRMLS_CC
);
}
}
else
if
(
upb_fielddef_isstring
(
f
))
{
zval
*
str
=
*
DEREF
(
msg
,
offset
,
zval
**
);
zval
*
str
=
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
offset
,
CACHED_VALUE
*
));
if
(
Z_STRLEN_P
(
str
)
>
0
)
{
putstr
(
str
,
f
,
sink
);
}
}
else
if
(
upb_fielddef_issubmsg
(
f
))
{
putsubmsg
(
*
DEREF
(
msg
,
offset
,
zval
**
),
f
,
sink
,
depth
TSRMLS_CC
);
putsubmsg
(
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
message_data
(
msg
),
offset
,
CACHED_VALUE
*
)),
f
,
sink
,
depth
TSRMLS_CC
);
}
else
{
upb_selector_t
sel
=
getsel
(
f
,
upb_handlers_getprimitivehandlertype
(
f
));
#define T(upbtypeconst, upbtype, ctype, default_value) \
case upbtypeconst: { \
ctype value = DEREF(m
sg, offset, ctype);
\
ctype value = DEREF(m
essage_data(msg), offset, ctype);
\
if (value != default_value) { \
upb_sink_put##upbtype(sink, sel, value); \
} \
...
...
@@ -1138,18 +1285,23 @@ static void putrawstr(const char* str, int len, const upb_fielddef* f,
upb_sink_endstr
(
sink
,
getsel
(
f
,
UPB_HANDLER_ENDSTR
));
}
static
void
putsubmsg
(
zval
*
submsg
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
,
static
void
putsubmsg
(
zval
*
submsg
_php
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
)
{
upb_sink
subsink
;
if
(
Z_TYPE_P
(
submsg_php
)
==
IS_NULL
)
return
;
if
(
Z_TYPE_P
(
submsg
)
==
IS_NULL
)
return
;
MessageHeader
*
submsg
=
UNBOX
(
MessageHeader
,
submsg_php
);
putrawsubmsg
(
submsg
,
f
,
sink
,
depth
TSRMLS_CC
);
}
static
void
putrawsubmsg
(
MessageHeader
*
submsg
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
)
{
upb_sink
subsink
;
zval
*
php_descriptor
=
get_def_obj
(
upb_fielddef_msgsubdef
(
f
));
Descriptor
*
subdesc
=
(
Descriptor
*
)
zend_object_store_get_object
(
php_descriptor
TSRMLS_CC
);
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_def_obj
(
upb_fielddef_msgsubdef
(
f
))
);
upb_sink_startsubmsg
(
sink
,
getsel
(
f
,
UPB_HANDLER_STARTSUBMSG
),
&
subsink
);
putmsg
(
submsg
,
subdesc
,
&
subsink
,
depth
+
1
TSRMLS_CC
);
put
raw
msg
(
submsg
,
subdesc
,
&
subsink
,
depth
+
1
TSRMLS_CC
);
upb_sink_endsubmsg
(
sink
,
getsel
(
f
,
UPB_HANDLER_ENDSUBMSG
));
}
...
...
@@ -1161,9 +1313,10 @@ static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink,
int
size
,
i
;
assert
(
array
!=
NULL
);
RepeatedField
*
intern
=
(
RepeatedField
*
)
zend_object_store_get_object
(
array
TSRMLS_CC
);
size
=
zend_hash_num_elements
(
HASH_OF
(
intern
->
array
));
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
array
);
HashTable
*
ht
=
PHP_PROTO_HASH_OF
(
intern
->
array
);
size
=
zend_hash_num_elements
(
ht
);
// size = zend_hash_num_elements(PHP_PROTO_HASH_OF(intern->array));
if
(
size
==
0
)
return
;
upb_sink_startseq
(
sink
,
getsel
(
f
,
UPB_HANDLER_STARTSEQ
),
&
subsink
);
...
...
@@ -1190,12 +1343,28 @@ static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink,
T
(
UPB_TYPE_UINT64
,
uint64
,
uint64_t
)
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
putstr
(
*
((
zval
**
)
memory
),
f
,
&
subsink
);
case
UPB_TYPE_BYTES
:
{
#if PHP_MAJOR_VERSION < 7
const
char
*
rawstr
=
Z_STRVAL_P
(
*
(
zval
**
)
memory
);
int
len
=
Z_STRLEN_P
(
*
(
zval
**
)
memory
);
#else
const
char
*
rawstr
=
ZSTR_VAL
(
*
(
zend_string
**
)
memory
);
int
len
=
ZSTR_LEN
(
*
(
zend_string
**
)
memory
);
#endif
putrawstr
(
rawstr
,
len
,
f
,
&
subsink
);
break
;
case
UPB_TYPE_MESSAGE
:
putsubmsg
(
*
((
zval
**
)
memory
),
f
,
&
subsink
,
depth
TSRMLS_CC
);
}
case
UPB_TYPE_MESSAGE
:
{
#if PHP_MAJOR_VERSION < 7
MessageHeader
*
submsg
=
UNBOX
(
MessageHeader
,
*
(
zval
**
)
memory
);
#else
MessageHeader
*
submsg
=
(
MessageHeader
*
)((
char
*
)(
*
(
zend_object
**
)
memory
)
-
XtOffsetOf
(
MessageHeader
,
std
));
#endif
putrawsubmsg
(
submsg
,
f
,
&
subsink
,
depth
TSRMLS_CC
);
break
;
}
#undef T
}
...
...
@@ -1235,9 +1404,8 @@ static const upb_handlers* msgdef_json_serialize_handlers(
// -----------------------------------------------------------------------------
PHP_METHOD
(
Message
,
serializeToString
)
{
zval
*
php_descriptor
=
get_ce_obj
(
Z_OBJCE_P
(
getThis
()));
Descriptor
*
desc
=
(
Descriptor
*
)
zend_object_store_get_object
(
php_descriptor
TSRMLS_CC
);
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_ce_obj
(
Z_OBJCE_P
(
getThis
()))
);
stringsink
sink
;
stringsink_init
(
&
sink
);
...
...
@@ -1253,7 +1421,7 @@ PHP_METHOD(Message, serializeToString) {
putmsg
(
getThis
(),
desc
,
upb_pb_encoder_input
(
encoder
),
0
TSRMLS_CC
);
RETVAL_STRINGL
(
sink
.
ptr
,
sink
.
len
,
1
);
PHP_PROTO_
RETVAL_STRINGL
(
sink
.
ptr
,
sink
.
len
,
1
);
stackenv_uninit
(
&
se
);
stringsink_uninit
(
&
sink
);
...
...
@@ -1261,13 +1429,12 @@ PHP_METHOD(Message, serializeToString) {
}
PHP_METHOD
(
Message
,
mergeFromString
)
{
zval
*
php_descriptor
=
get_ce_obj
(
Z_OBJCE_P
(
getThis
()));
Descriptor
*
desc
=
(
Descriptor
*
)
zend_object_store_get_object
(
php_descriptor
TSRMLS_CC
);
MessageHeader
*
msg
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_ce_obj
(
Z_OBJCE_P
(
getThis
()))
);
MessageHeader
*
msg
=
UNBOX
(
MessageHeader
,
getThis
()
);
char
*
data
=
NULL
;
int
data_len
;
PHP_PROTO_SIZE
data_len
;
if
(
zend_parse_parameters
(
ZEND_NUM_ARGS
()
TSRMLS_CC
,
"s"
,
&
data
,
&
data_len
)
==
FAILURE
)
{
return
;
...
...
@@ -1290,9 +1457,8 @@ PHP_METHOD(Message, mergeFromString) {
}
PHP_METHOD
(
Message
,
jsonEncode
)
{
zval
*
php_descriptor
=
get_ce_obj
(
Z_OBJCE_P
(
getThis
()));
Descriptor
*
desc
=
(
Descriptor
*
)
zend_object_store_get_object
(
php_descriptor
TSRMLS_CC
);
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_ce_obj
(
Z_OBJCE_P
(
getThis
()))
);
zend_bool
preserve_proto_fieldnames
=
false
;
if
(
zend_parse_parameters
(
ZEND_NUM_ARGS
()
TSRMLS_CC
,
"|b"
,
...
...
@@ -1314,7 +1480,7 @@ PHP_METHOD(Message, jsonEncode) {
putmsg
(
getThis
(),
desc
,
upb_json_printer_input
(
printer
),
0
TSRMLS_CC
);
RETVAL_STRINGL
(
sink
.
ptr
,
sink
.
len
,
1
);
PHP_PROTO_
RETVAL_STRINGL
(
sink
.
ptr
,
sink
.
len
,
1
);
stackenv_uninit
(
&
se
);
stringsink_uninit
(
&
sink
);
...
...
@@ -1322,10 +1488,9 @@ PHP_METHOD(Message, jsonEncode) {
}
PHP_METHOD
(
Message
,
jsonDecode
)
{
zval
*
php_descriptor
=
get_ce_obj
(
Z_OBJCE_P
(
getThis
()));
Descriptor
*
desc
=
(
Descriptor
*
)
zend_object_store_get_object
(
php_descriptor
TSRMLS_CC
);
MessageHeader
*
msg
=
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_ce_obj
(
Z_OBJCE_P
(
getThis
()))
);
MessageHeader
*
msg
=
UNBOX
(
MessageHeader
,
getThis
()
);
char
*
data
=
NULL
;
int
data_len
;
...
...
php/ext/google/protobuf/map.c
View file @
190b5270
...
...
@@ -109,7 +109,7 @@ static bool table_key(Map* self, zval* key,
if (!protobuf_convert_to_##type(key, &type##_value)) { \
return false; \
} \
native_slot_set
(self->key_type, NULL, buf, key TSRMLS_CC);
\
native_slot_set
_by_array(self->key_type, NULL, buf, key TSRMLS_CC);
\
*out_key = buf; \
*out_length = native_slot_size(self->key_type); \
break; \
...
...
@@ -148,7 +148,7 @@ static zend_function_entry map_field_methods[] = {
// Forward declare static functions.
static
bool
map_field_write_dimension
(
zval
*
object
,
zval
*
key
,
static
void
map_field_write_dimension
(
zval
*
object
,
zval
*
key
,
zval
*
value
TSRMLS_DC
);
// -----------------------------------------------------------------------------
...
...
@@ -163,8 +163,7 @@ static void map_begin_internal(Map *map, MapIter *iter) {
upb_strtable_begin
(
&
iter
->
it
,
&
map
->
table
);
}
static
HashTable
*
map_field_get_gc
(
zval
*
object
,
zval
***
table
,
int
*
n
TSRMLS_DC
)
{
static
HashTable
*
map_field_get_gc
(
zval
*
object
,
CACHED_VALUE
**
table
,
int
*
n
)
{
// TODO(teboring): Unfortunately, zend engine does not support garbage
// collection for custom array. We have to use zend engine's native array
// instead.
...
...
@@ -173,111 +172,101 @@ static HashTable *map_field_get_gc(zval *object, zval ***table,
return
NULL
;
}
void
map_field_init
(
TSRMLS_D
)
{
zend_class_entry
class_type
;
const
char
*
class_name
=
"Google
\\
Protobuf
\\
Internal
\\
MapField"
;
INIT_CLASS_ENTRY_EX
(
class_type
,
class_name
,
strlen
(
class_name
),
map_field_methods
);
map_field_type
=
zend_register_internal_class
(
&
class_type
TSRMLS_CC
);
map_field_type
->
create_object
=
map_field_create
;
zend_class_implements
(
map_field_type
TSRMLS_CC
,
2
,
spl_ce_ArrayAccess
,
spl_ce_Countable
);
map_field_handlers
=
PEMALLOC
(
zend_object_handlers
);
memcpy
(
map_field_handlers
,
zend_get_std_object_handlers
(),
sizeof
(
zend_object_handlers
));
map_field_handlers
->
write_dimension
=
map_field_write_dimension
;
map_field_handlers
->
get_gc
=
map_field_get_gc
;
// Define map value element free function.
#if PHP_MAJOR_VERSION < 7
static
inline
void
php_proto_map_string_release
(
void
*
value
)
{
zval_ptr_dtor
(
value
);
}
zend_object_value
map_field_create
(
zend_class_entry
*
ce
TSRMLS_DC
)
{
zend_object_value
retval
=
{
0
};
Map
*
intern
;
intern
=
emalloc
(
sizeof
(
Map
));
memset
(
intern
,
0
,
sizeof
(
Map
));
zend_object_std_init
(
&
intern
->
std
,
ce
TSRMLS_CC
);
object_properties_init
(
&
intern
->
std
,
ce
);
// Table value type is always UINT64: this ensures enough space to store the
// native_slot value.
if
(
!
upb_strtable_init
(
&
intern
->
table
,
UPB_CTYPE_UINT64
))
{
zend_error
(
E_USER_ERROR
,
"Could not allocate table."
);
static
inline
void
php_proto_map_object_release
(
void
*
value
)
{
zval_ptr_dtor
(
value
);
}
#else
static
inline
void
php_proto_map_string_release
(
void
*
value
)
{
zend_string
*
object
=
*
(
zend_string
**
)
value
;
zend_string_release
(
object
);
}
static
inline
void
php_proto_map_object_release
(
void
*
value
)
{
zend_object
*
object
=
*
(
zend_object
**
)
value
;
if
(
--
GC_REFCOUNT
(
object
)
==
0
)
{
zend_objects_store_del
(
object
);
}
retval
.
handle
=
zend_objects_store_put
(
intern
,
(
zend_objects_store_dtor_t
)
zend_objects_destroy_object
,
(
zend_objects_free_object_storage_t
)
map_field_free
,
NULL
TSRMLS_CC
);
retval
.
handlers
=
map_field_handlers
;
return
retval
;
}
#endif
void
map_field_free
(
void
*
object
TSRMLS_DC
)
{
Map
*
map
=
(
Map
*
)
object
;
switch
(
map
->
value_type
)
{
case
UPB_TYPE_MESSAGE
:
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
MapIter
it
;
int
len
;
for
(
map_begin_internal
(
map
,
&
it
);
!
map_done
(
&
it
);
map_next
(
&
it
))
{
// Define object free method.
PHP_PROTO_OBJECT_FREE_START
(
Map
,
map_field
)
MapIter
it
;
int
len
;
for
(
map_begin_internal
(
intern
,
&
it
);
!
map_done
(
&
it
);
map_next
(
&
it
))
{
upb_value
value
=
map_iter_value
(
&
it
,
&
len
);
void
*
mem
=
upb_value_memory
(
&
value
);
zval_ptr_dtor
(
mem
);
}
switch
(
intern
->
value_type
)
{
case
UPB_TYPE_MESSAGE
:
php_proto_map_object_release
(
mem
);
break
;
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
php_proto_map_string_release
(
mem
);
break
;
}
default
:
break
;
}
}
upb_strtable_uninit
(
&
intern
->
table
);
PHP_PROTO_OBJECT_FREE_END
upb_strtable_uninit
(
&
map
->
table
);
zend_object_std_dtor
(
&
map
->
std
TSRMLS_CC
);
efree
(
object
);
PHP_PROTO_OBJECT_DTOR_START
(
Map
,
map_field
)
PHP_PROTO_OBJECT_DTOR_END
// Define object create method.
PHP_PROTO_OBJECT_CREATE_START
(
Map
,
map_field
)
// Table value type is always UINT64: this ensures enough space to store the
// native_slot value.
if
(
!
upb_strtable_init
(
&
intern
->
table
,
UPB_CTYPE_UINT64
))
{
zend_error
(
E_USER_ERROR
,
"Could not allocate table."
);
}
PHP_PROTO_OBJECT_CREATE_END
(
Map
,
map_field
)
void
map_field_create_with_field
(
zend_class_entry
*
ce
,
const
upb_fielddef
*
field
,
zval
**
map_field
TSRMLS_DC
)
{
// 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
);
map_field_handlers
->
write_dimension
=
map_field_write_dimension
;
map_field_handlers
->
get_gc
=
map_field_get_gc
;
PHP_PROTO_INIT_CLASS_END
void
map_field_create_with_field
(
const
zend_class_entry
*
ce
,
const
upb_fielddef
*
field
,
CACHED_VALUE
*
map_field
PHP_PROTO_TSRMLS_DC
)
{
const
upb_fielddef
*
key_field
=
map_field_key
(
field
);
const
upb_fielddef
*
value_field
=
map_field_value
(
field
);
map_field_create_with_type
(
ce
,
upb_fielddef_type
(
key_field
),
upb_fielddef_type
(
value_field
),
field_type_class
(
value_field
TSRMLS_CC
),
map_field
TSRMLS_CC
);
field_type_class
(
value_field
TSRMLS_CC
),
map_field
PHP_PROTO_
TSRMLS_CC
);
}
void
map_field_create_with_type
(
zend_class_entry
*
ce
,
upb_fieldtype_t
key_type
,
void
map_field_create_with_type
(
const
zend_class_entry
*
ce
,
upb_fieldtype_t
key_type
,
upb_fieldtype_t
value_type
,
const
zend_class_entry
*
msg_ce
,
zval
**
map_field
TSRMLS_DC
)
{
MAKE_STD_ZVAL
(
*
map_field
);
Z_TYPE_PP
(
map_field
)
=
IS_OBJECT
;
Z_OBJVAL_PP
(
map_field
)
=
map_field_type
->
create_object
(
map_field_type
TSRMLS_CC
);
Map
*
intern
=
(
Map
*
)
zend_object_store_get_object
(
*
map_field
TSRMLS_CC
);
CACHED_VALUE
*
map_field
PHP_PROTO_TSRMLS_DC
)
{
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR
(
CACHED_PTR_TO_ZVAL_PTR
(
map_field
),
map_field_type
);
Map
*
intern
=
UNBOX
(
Map
,
CACHED_TO_ZVAL_PTR
(
*
map_field
));
intern
->
key_type
=
key_type
;
intern
->
value_type
=
value_type
;
intern
->
msg_ce
=
msg_ce
;
}
static
void
map_field_free_element
(
void
*
object
)
{
}
// -----------------------------------------------------------------------------
// MapField Handlers
// -----------------------------------------------------------------------------
static
bool
map_field_read_dimension
(
zval
*
object
,
zval
*
key
,
int
type
,
zval
**
retval
TSRMLS_DC
)
{
Map
*
intern
=
(
Map
*
)
zend_object_store_get_object
(
object
TSRMLS_CC
);
CACHED_VALUE
*
retval
TSRMLS_DC
)
{
Map
*
intern
=
UNBOX
(
Map
,
object
);
char
keybuf
[
TABLE_KEY_BUF_LENGTH
];
const
char
*
keyval
=
NULL
;
...
...
@@ -292,7 +281,7 @@ static bool map_field_read_dimension(zval *object, zval *key, int type,
if
(
upb_strtable_lookup2
(
&
intern
->
table
,
keyval
,
length
,
&
v
))
{
void
*
mem
=
upb_value_memory
(
&
v
);
native_slot_get
(
intern
->
value_type
,
mem
,
retval
TSRMLS_CC
);
native_slot_get
_by_array
(
intern
->
value_type
,
mem
,
retval
TSRMLS_CC
);
return
true
;
}
else
{
zend_error
(
E_USER_ERROR
,
"Given key doesn't exist."
);
...
...
@@ -310,9 +299,9 @@ bool map_index_set(Map *intern, const char* keyval, int length, upb_value v) {
return
true
;
}
static
bool
map_field_write_dimension
(
zval
*
object
,
zval
*
key
,
static
void
map_field_write_dimension
(
zval
*
object
,
zval
*
key
,
zval
*
value
TSRMLS_DC
)
{
Map
*
intern
=
(
Map
*
)
zend_object_store_get_object
(
object
TSRMLS_CC
);
Map
*
intern
=
UNBOX
(
Map
,
object
);
char
keybuf
[
TABLE_KEY_BUF_LENGTH
];
const
char
*
keyval
=
NULL
;
...
...
@@ -320,14 +309,14 @@ static bool map_field_write_dimension(zval *object, zval *key,
upb_value
v
;
void
*
mem
;
if
(
!
table_key
(
intern
,
key
,
keybuf
,
&
keyval
,
&
length
TSRMLS_CC
))
{
return
false
;
return
;
}
mem
=
upb_value_memory
(
&
v
);
memset
(
mem
,
0
,
native_slot_size
(
intern
->
value_type
));
if
(
!
native_slot_set
(
intern
->
value_type
,
intern
->
msg_ce
,
mem
,
if
(
!
native_slot_set
_by_array
(
intern
->
value_type
,
intern
->
msg_ce
,
mem
,
value
TSRMLS_CC
))
{
return
false
;
return
;
}
#ifndef NDEBUG
v
.
ctype
=
UPB_CTYPE_UINT64
;
...
...
@@ -337,14 +326,12 @@ static bool map_field_write_dimension(zval *object, zval *key,
upb_strtable_remove2
(
&
intern
->
table
,
keyval
,
length
,
NULL
);
if
(
!
upb_strtable_insert2
(
&
intern
->
table
,
keyval
,
length
,
v
))
{
zend_error
(
E_USER_ERROR
,
"Could not insert into table"
);
return
false
;
return
;
}
return
true
;
}
static
bool
map_field_unset_dimension
(
zval
*
object
,
zval
*
key
TSRMLS_DC
)
{
Map
*
intern
=
(
Map
*
)
zend_object_store_get_object
(
object
TSRMLS_CC
);
Map
*
intern
=
UNBOX
(
Map
,
object
);
char
keybuf
[
TABLE_KEY_BUF_LENGTH
];
const
char
*
keyval
=
NULL
;
...
...
@@ -375,8 +362,7 @@ PHP_METHOD(MapField, __construct) {
return
;
}
Map
*
intern
=
(
Map
*
)
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
Map
*
intern
=
UNBOX
(
Map
,
getThis
());
intern
->
key_type
=
to_fieldtype
(
key_type
);
intern
->
value_type
=
to_fieldtype
(
value_type
);
intern
->
msg_ce
=
klass
;
...
...
@@ -404,7 +390,7 @@ PHP_METHOD(MapField, offsetExists) {
return
;
}
Map
*
intern
=
(
Map
*
)
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
Map
*
intern
=
UNBOX
(
Map
,
getThis
()
);
char
keybuf
[
TABLE_KEY_BUF_LENGTH
];
const
char
*
keyval
=
NULL
;
...
...
@@ -427,7 +413,7 @@ PHP_METHOD(MapField, offsetGet) {
return
;
}
map_field_read_dimension
(
getThis
(),
index
,
BP_VAR_R
,
return_value_ptr
TSRMLS_CC
);
ZVAL_PTR_TO_CACHED_PTR
(
return_value
)
TSRMLS_CC
);
}
PHP_METHOD
(
MapField
,
offsetSet
)
{
...
...
@@ -449,8 +435,7 @@ PHP_METHOD(MapField, offsetUnset) {
}
PHP_METHOD
(
MapField
,
count
)
{
Map
*
intern
=
(
Map
*
)
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
Map
*
intern
=
UNBOX
(
Map
,
getThis
());
if
(
zend_parse_parameters_none
()
==
FAILURE
)
{
return
;
...
...
php/ext/google/protobuf/message.c
View file @
190b5270
...
...
@@ -53,40 +53,64 @@ static zend_function_entry message_methods[] = {
// Forward declare static functions.
#if PHP_MAJOR_VERSION < 7
static
void
message_set_property
(
zval
*
object
,
zval
*
member
,
zval
*
value
,
const
zend_literal
*
key
TSRMLS_DC
);
php_proto_zend_literal
key
TSRMLS_DC
);
static
zval
*
message_get_property
(
zval
*
object
,
zval
*
member
,
int
type
,
const
zend_literal
*
key
TSRMLS_DC
);
static
zval
**
message_get_property_ptr_ptr
(
zval
*
object
,
zval
*
member
,
int
type
,
const
zend_literal
*
key
TSRMLS_DC
);
static
HashTable
*
message_get_properties
(
zval
*
object
TSRMLS_DC
);
php_proto_zend_literal
key
TSRMLS_DC
);
static
HashTable
*
message_get_gc
(
zval
*
object
,
zval
***
table
,
int
*
n
TSRMLS_DC
);
static
zend_object_value
message_create
(
zend_class_entry
*
ce
TSRMLS_DC
);
static
void
message_free
(
void
*
object
TSRMLS_DC
);
#else
static
void
message_set_property
(
zval
*
object
,
zval
*
member
,
zval
*
value
,
void
**
cache_slot
);
static
zval
*
message_get_property
(
zval
*
object
,
zval
*
member
,
int
type
,
void
**
cache_slot
,
zval
*
rv
);
static
zval
*
message_get_property_ptr_ptr
(
zval
*
object
,
zval
*
member
,
int
type
,
void
**
cache_slot
);
static
HashTable
*
message_get_gc
(
zval
*
object
,
zval
**
table
,
int
*
n
);
#endif
static
HashTable
*
message_get_properties
(
zval
*
object
TSRMLS_DC
);
// -----------------------------------------------------------------------------
// PHP Message Handlers
// -----------------------------------------------------------------------------
void
message_init
(
TSRMLS_D
)
{
zend_class_entry
class_type
;
INIT_CLASS_ENTRY
(
class_type
,
"Google
\\
Protobuf
\\
Internal
\\
Message"
,
message_methods
);
message_type
=
zend_register_internal_class
(
&
class_type
TSRMLS_CC
);
message_handlers
=
PEMALLOC
(
zend_object_handlers
);
memcpy
(
message_handlers
,
zend_get_std_object_handlers
(),
sizeof
(
zend_object_handlers
));
// Define object free method.
PHP_PROTO_OBJECT_FREE_START
(
MessageHeader
,
message
)
FREE
(
intern
->
data
);
PHP_PROTO_OBJECT_FREE_END
PHP_PROTO_OBJECT_DTOR_START
(
MessageHeader
,
message
)
PHP_PROTO_OBJECT_DTOR_END
// Define object create method.
PHP_PROTO_OBJECT_CREATE_START
(
MessageHeader
,
message
)
// Because php call this create func before calling the sub-message's
// constructor defined in PHP, it's possible that the decriptor of this class
// hasn't been added to descritpor pool (when the class is first
// instantiated). In that case, we will defer the initialization of the custom
// data to the parent Message's constructor, which will be called by
// sub-message's constructors after the descriptor has been added.
PHP_PROTO_OBJECT_CREATE_END
(
MessageHeader
,
message
)
// Init class entry.
PHP_PROTO_INIT_CLASS_START
(
"Google
\\
Protobuf
\\
Internal
\\
Message"
,
MessageHeader
,
message
)
message_handlers
->
write_property
=
message_set_property
;
message_handlers
->
read_property
=
message_get_property
;
message_handlers
->
get_property_ptr_ptr
=
message_get_property_ptr_ptr
;
message_handlers
->
get_properties
=
message_get_properties
;
message_handlers
->
get_gc
=
message_get_gc
;
}
PHP_PROTO_INIT_CLASS_END
#if PHP_MAJOR_VERSION < 7
static
void
message_set_property
(
zval
*
object
,
zval
*
member
,
zval
*
value
,
const
zend_literal
*
key
TSRMLS_DC
)
{
php_proto_zend_literal
key
TSRMLS_DC
)
{
#else
static
void
message_set_property
(
zval
*
object
,
zval
*
member
,
zval
*
value
,
void
**
cache_slot
)
{
#endif
if
(
Z_TYPE_P
(
member
)
!=
IS_STRING
)
{
zend_error
(
E_USER_ERROR
,
"Unexpected type for field name"
);
return
;
...
...
@@ -100,7 +124,7 @@ static void message_set_property(zval* object, zval* member, zval* value,
const
upb_fielddef
*
field
;
MessageHeader
*
self
=
zend_object_store_get_object
(
object
TSRMLS_CC
);
MessageHeader
*
self
=
UNBOX
(
MessageHeader
,
object
);
field
=
upb_msgdef_ntofz
(
self
->
descriptor
->
msgdef
,
Z_STRVAL_P
(
member
));
if
(
field
==
NULL
)
{
...
...
@@ -110,46 +134,55 @@ static void message_set_property(zval* object, zval* member, zval* value,
layout_set
(
self
->
descriptor
->
layout
,
self
,
field
,
value
TSRMLS_CC
);
}
#if PHP_MAJOR_VERSION < 7
static
zval
*
message_get_property
(
zval
*
object
,
zval
*
member
,
int
type
,
const
zend_literal
*
key
TSRMLS_DC
)
{
#else
static
zval
*
message_get_property
(
zval
*
object
,
zval
*
member
,
int
type
,
void
**
cache_slot
,
zval
*
rv
)
{
#endif
if
(
Z_TYPE_P
(
member
)
!=
IS_STRING
)
{
zend_error
(
E_USER_ERROR
,
"Property name has to be a string."
);
return
EG
(
uninitialized_zval_ptr
)
;
return
PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL
;
}
if
(
Z_OBJCE_P
(
object
)
!=
EG
(
scope
))
{
// User cannot get property directly (e.g., $a = $m->a)
zend_error
(
E_USER_ERROR
,
"Cannot access private property."
);
return
EG
(
uninitialized_zval_ptr
);
}
zend_property_info
*
property_info
=
NULL
;
// All properties should have been declared in the generated code and have
// corresponding zvals in properties_table.
ulong
h
=
zend_get_hash_value
(
Z_STRVAL_P
(
member
),
Z_STRLEN_P
(
member
)
+
1
);
if
(
zend_hash_quick_find
(
&
Z_OBJCE_P
(
object
)
->
properties_info
,
Z_STRVAL_P
(
member
),
Z_STRLEN_P
(
member
)
+
1
,
h
,
(
void
**
)
&
property_info
)
!=
SUCCESS
)
{
zend_error
(
E_USER_ERROR
,
"Property does not exist."
);
return
EG
(
uninitialized_zval_ptr
);
return
PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL
;
}
MessageHeader
*
self
=
(
MessageHeader
*
)
zend_object_store_get_object
(
object
TSRMLS_CC
);
MessageHeader
*
self
=
UNBOX
(
MessageHeader
,
object
);
const
upb_fielddef
*
field
;
field
=
upb_msgdef_ntofz
(
self
->
descriptor
->
msgdef
,
Z_STRVAL_P
(
member
));
if
(
field
==
NULL
)
{
return
EG
(
uninitialized_zval_ptr
)
;
return
PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL
;
}
zend_property_info
*
property_info
;
#if PHP_MAJOR_VERSION < 7
property_info
=
zend_get_property_info
(
Z_OBJCE_P
(
object
),
member
,
true
TSRMLS_CC
);
return
layout_get
(
self
->
descriptor
->
layout
,
message_data
(
self
),
field
,
&
Z_OBJ_P
(
object
)
->
properties_table
[
property_info
->
offset
]
TSRMLS_CC
);
#else
property_info
=
zend_get_property_info
(
Z_OBJCE_P
(
object
),
Z_STR_P
(
member
),
true
);
return
layout_get
(
self
->
descriptor
->
layout
,
message_data
(
self
),
field
,
OBJ_PROP
(
Z_OBJ_P
(
object
),
property_info
->
offset
)
TSRMLS_CC
);
#endif
}
#if PHP_MAJOR_VERSION < 7
static
zval
**
message_get_property_ptr_ptr
(
zval
*
object
,
zval
*
member
,
int
type
,
const
zend_literal
*
key
TSRMLS_DC
)
{
php_proto_zend_literal
key
TSRMLS_DC
)
{
#else
static
zval
*
message_get_property_ptr_ptr
(
zval
*
object
,
zval
*
member
,
int
type
,
void
**
cache_slot
)
{
#endif
return
NULL
;
}
...
...
@@ -157,7 +190,8 @@ static HashTable* message_get_properties(zval* object TSRMLS_DC) {
return
NULL
;
}
static
HashTable
*
message_get_gc
(
zval
*
object
,
zval
***
table
,
int
*
n
TSRMLS_DC
)
{
static
HashTable
*
message_get_gc
(
zval
*
object
,
CACHED_VALUE
**
table
,
int
*
n
TSRMLS_DC
)
{
zend_object
*
zobj
=
Z_OBJ_P
(
object
);
*
table
=
zobj
->
properties_table
;
*
n
=
zobj
->
ce
->
default_properties_count
;
...
...
@@ -168,57 +202,25 @@ static HashTable* message_get_gc(zval* object, zval*** table, int* n TSRMLS_DC)
// C Message Utilities
// -----------------------------------------------------------------------------
void
*
message_data
(
void
*
msg
)
{
return
((
uint8_t
*
)
msg
)
+
sizeof
(
MessageHeader
);
}
static
void
message_free
(
void
*
object
TSRMLS_DC
)
{
MessageHeader
*
msg
=
(
MessageHeader
*
)
object
;
int
i
;
for
(
i
=
0
;
i
<
msg
->
std
.
ce
->
default_properties_count
;
i
++
)
{
zval_ptr_dtor
(
&
msg
->
std
.
properties_table
[
i
]);
}
efree
(
msg
->
std
.
properties_table
);
efree
(
msg
);
void
*
message_data
(
MessageHeader
*
msg
)
{
return
msg
->
data
;
}
static
zend_object_value
message_create
(
zend_class_entry
*
ce
TSRMLS_DC
)
{
zend_object_value
return_value
;
zval
*
php_descriptor
=
get_ce_obj
(
ce
);
Descriptor
*
desc
=
zend_object_store_get_object
(
php_descriptor
TSRMLS_CC
);
MessageHeader
*
msg
=
(
MessageHeader
*
)
ALLOC_N
(
uint8_t
,
sizeof
(
MessageHeader
)
+
desc
->
layout
->
size
);
memset
(
message_data
(
msg
),
0
,
desc
->
layout
->
size
);
void
custom_data_init
(
const
zend_class_entry
*
ce
,
MessageHeader
*
intern
PHP_PROTO_TSRMLS_DC
)
{
Descriptor
*
desc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_ce_obj
(
ce
));
intern
->
data
=
ALLOC_N
(
uint8_t
,
desc
->
layout
->
size
);
memset
(
message_data
(
intern
),
0
,
desc
->
layout
->
size
);
// We wrap first so that everything in the message object is GC-rooted in
// case a collection happens during object creation in layout_init().
msg
->
descriptor
=
desc
;
zend_object_std_init
(
&
msg
->
std
,
ce
TSRMLS_CC
);
object_properties_init
(
&
msg
->
std
,
ce
);
layout_init
(
desc
->
layout
,
message_data
(
msg
),
msg
->
std
.
properties_table
TSRMLS_CC
);
return_value
.
handle
=
zend_objects_store_put
(
msg
,
(
zend_objects_store_dtor_t
)
zend_objects_destroy_object
,
message_free
,
NULL
TSRMLS_CC
);
return_value
.
handlers
=
message_handlers
;
return
return_value
;
intern
->
descriptor
=
desc
;
layout_init
(
desc
->
layout
,
message_data
(
intern
),
intern
->
std
.
properties_table
PHP_PROTO_TSRMLS_CC
);
}
void
message_create_with_type
(
zend_class_entry
*
ce
,
zval
**
message
TSRMLS_DC
)
{
MAKE_STD_ZVAL
(
*
message
);
Z_TYPE_PP
(
message
)
=
IS_OBJECT
;
Z_OBJVAL_PP
(
message
)
=
ce
->
create_object
(
ce
TSRMLS_CC
);
Z_DELREF_PP
(
message
);
}
void
build_class_from_descriptor
(
zval
*
php_descriptor
TSRMLS_DC
)
{
Descriptor
*
desc
=
UNBOX
(
Descriptor
,
php_descriptor
);
void
build_class_from_descriptor
(
PHP_PROTO_HASHTABLE_VALUE
php_descriptor
TSRMLS_DC
)
{
Descriptor
*
desc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
php_descriptor
);
// Map entries don't have existing php class.
if
(
upb_msgdef_mapentry
(
desc
->
msgdef
))
{
...
...
@@ -243,26 +245,18 @@ void build_class_from_descriptor(zval* php_descriptor TSRMLS_DC) {
// modified. As a result, the first created instance will be a normal zend
// object. Here, we manually modify it to our message in such a case.
PHP_METHOD
(
Message
,
__construct
)
{
if
(
Z_OBJVAL_P
(
getThis
()).
handlers
!=
message_handlers
)
{
zend_class_entry
*
ce
=
Z_OBJCE_P
(
getThis
());
zval_dtor
(
getThis
());
Z_OBJVAL_P
(
getThis
())
=
message_create
(
ce
TSRMLS_CC
);
if
(
EXPECTED
(
class_added
(
ce
)))
{
MessageHeader
*
intern
=
UNBOX
(
MessageHeader
,
getThis
());
custom_data_init
(
ce
,
intern
PHP_PROTO_TSRMLS_CC
);
}
}
PHP_METHOD
(
Message
,
clear
)
{
MessageHeader
*
msg
=
(
MessageHeader
*
)
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
MessageHeader
*
msg
=
UNBOX
(
MessageHeader
,
getThis
());
Descriptor
*
desc
=
msg
->
descriptor
;
zend_class_entry
*
ce
=
desc
->
klass
;
int
i
;
for
(
i
=
0
;
i
<
msg
->
std
.
ce
->
default_properties_count
;
i
++
)
{
zval_ptr_dtor
(
&
msg
->
std
.
properties_table
[
i
]);
}
efree
(
msg
->
std
.
properties_table
);
zend_object_std_init
(
&
msg
->
std
,
ce
TSRMLS_CC
);
object_properties_init
(
&
msg
->
std
,
ce
);
layout_init
(
desc
->
layout
,
message_data
(
msg
),
msg
->
std
.
properties_table
TSRMLS_CC
);
...
...
@@ -275,10 +269,8 @@ PHP_METHOD(Message, mergeFrom) {
return
;
}
MessageHeader
*
from
=
(
MessageHeader
*
)
zend_object_store_get_object
(
value
TSRMLS_CC
);
MessageHeader
*
to
=
(
MessageHeader
*
)
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
MessageHeader
*
from
=
UNBOX
(
MessageHeader
,
value
);
MessageHeader
*
to
=
UNBOX
(
MessageHeader
,
getThis
());
if
(
from
->
descriptor
!=
to
->
descriptor
)
{
zend_error
(
E_USER_ERROR
,
"Cannot merge messages with different class."
);
...
...
@@ -289,36 +281,37 @@ PHP_METHOD(Message, mergeFrom) {
}
PHP_METHOD
(
Message
,
readOneof
)
{
long
index
;
PHP_PROTO_LONG
index
;
if
(
zend_parse_parameters
(
ZEND_NUM_ARGS
()
TSRMLS_CC
,
"l"
,
&
index
)
==
FAILURE
)
{
return
;
}
MessageHeader
*
msg
=
(
MessageHeader
*
)
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
MessageHeader
*
msg
=
UNBOX
(
MessageHeader
,
getThis
());
const
upb_fielddef
*
field
=
upb_msgdef_itof
(
msg
->
descriptor
->
msgdef
,
index
);
int
property_cache_index
=
msg
->
descriptor
->
layout
->
fields
[
upb_fielddef_index
(
field
)].
cache_index
;
zval
*
*
cache_ptr
=
&
(
msg
->
std
.
properties_table
)[
property_cache_index
]
;
zval
*
property_ptr
=
OBJ_PROP
(
Z_OBJ_P
(
getThis
()),
property_cache_index
)
;
// Unlike singular fields, oneof fields share cached property. So we cannot
// let lay_get modify the cached property. Instead, we pass in the return
// value directly.
layout_get
(
msg
->
descriptor
->
layout
,
message_data
(
msg
),
field
,
&
return_value
TSRMLS_CC
);
ZVAL_PTR_TO_CACHED_PTR
(
return_value
)
TSRMLS_CC
);
}
PHP_METHOD
(
Message
,
writeOneof
)
{
long
index
;
PHP_PROTO_LONG
index
;
zval
*
value
;
if
(
zend_parse_parameters
(
ZEND_NUM_ARGS
()
TSRMLS_CC
,
"lz"
,
&
index
,
&
value
)
==
FAILURE
)
{
return
;
}
MessageHeader
*
msg
=
(
MessageHeader
*
)
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
MessageHeader
*
msg
=
UNBOX
(
MessageHeader
,
getThis
());
const
upb_fielddef
*
field
=
upb_msgdef_itof
(
msg
->
descriptor
->
msgdef
,
index
);
...
...
@@ -327,19 +320,18 @@ PHP_METHOD(Message, writeOneof) {
PHP_METHOD
(
Message
,
whichOneof
)
{
char
*
oneof_name
;
int
length
;
PHP_PROTO_SIZE
length
;
if
(
zend_parse_parameters
(
ZEND_NUM_ARGS
()
TSRMLS_CC
,
"s"
,
&
oneof_name
,
&
length
)
==
FAILURE
)
{
return
;
}
MessageHeader
*
msg
=
(
MessageHeader
*
)
zend_object_store_get_object
(
getThis
()
TSRMLS_CC
);
MessageHeader
*
msg
=
UNBOX
(
MessageHeader
,
getThis
());
const
upb_oneofdef
*
oneof
=
upb_msgdef_ntoo
(
msg
->
descriptor
->
msgdef
,
oneof_name
,
length
);
const
char
*
oneof_case_name
=
layout_get_oneof_case
(
msg
->
descriptor
->
layout
,
message_data
(
msg
),
oneof
TSRMLS_CC
);
RETURN_STRING
(
oneof_case_name
,
1
);
PHP_PROTO_
RETURN_STRING
(
oneof_case_name
,
1
);
}
php/ext/google/protobuf/protobuf.c
View file @
190b5270
...
...
@@ -55,39 +55,60 @@ static void add_to_table(HashTable* t, const void* def, void* value) {
uint
nIndex
=
(
ulong
)
def
&
t
->
nTableMask
;
zval
*
pDest
=
NULL
;
zend_hash_index_update
(
t
,
(
zend_ulong
)
def
,
&
value
,
sizeof
(
zval
*
),
(
void
**
)
&
pDest
);
php_proto_zend_hash_index_update
(
t
,
(
zend_ulong
)
def
,
&
value
,
sizeof
(
zval
*
),
(
void
**
)
&
pDest
);
}
static
void
*
get_from_table
(
const
HashTable
*
t
,
const
void
*
def
)
{
void
**
value
;
if
(
zend_hash_index_find
(
t
,
(
zend_ulong
)
def
,
(
void
**
)
&
value
)
==
FAILURE
)
{
if
(
php_proto_zend_hash_index_find
(
t
,
(
zend_ulong
)
def
,
(
void
**
)
&
value
)
==
FAILURE
)
{
zend_error
(
E_ERROR
,
"PHP object not found for given definition.
\n
"
);
return
NULL
;
}
return
*
value
;
}
static
bool
exist_in_table
(
const
HashTable
*
t
,
const
void
*
def
)
{
void
**
value
;
return
(
php_proto_zend_hash_index_find
(
t
,
(
zend_ulong
)
def
,
(
void
**
)
&
value
)
==
SUCCESS
);
}
static
void
add_to_list
(
HashTable
*
t
,
void
*
value
)
{
zval
*
pDest
=
NULL
;
zend_hash_next_index_insert
(
t
,
&
value
,
sizeof
(
void
*
),
(
void
**
)
&
pDest
);
php_proto_zend_hash_next_index_insert
(
t
,
&
value
,
sizeof
(
void
*
),
(
void
**
)
&
pDest
);
}
void
add_def_obj
(
const
void
*
def
,
zval
*
value
)
{
void
add_def_obj
(
const
void
*
def
,
PHP_PROTO_HASHTABLE_VALUE
value
)
{
#if PHP_MAJOR_VERSION < 7
Z_ADDREF_P
(
value
);
#else
++
GC_REFCOUNT
(
value
);
#endif
add_to_table
(
upb_def_to_php_obj_map
,
def
,
value
);
}
zval
*
get_def_obj
(
const
void
*
def
)
{
return
(
zval
*
)
get_from_table
(
upb_def_to_php_obj_map
,
def
);
PHP_PROTO_HASHTABLE_VALUE
get_def_obj
(
const
void
*
def
)
{
return
(
PHP_PROTO_HASHTABLE_VALUE
)
get_from_table
(
upb_def_to_php_obj_map
,
def
);
}
void
add_ce_obj
(
const
void
*
ce
,
zval
*
value
)
{
void
add_ce_obj
(
const
void
*
ce
,
PHP_PROTO_HASHTABLE_VALUE
value
)
{
#if PHP_MAJOR_VERSION < 7
Z_ADDREF_P
(
value
);
#else
++
GC_REFCOUNT
(
value
);
#endif
add_to_table
(
ce_to_php_obj_map
,
ce
,
value
);
}
zval
*
get_ce_obj
(
const
void
*
ce
)
{
return
(
zval
*
)
get_from_table
(
ce_to_php_obj_map
,
ce
);
PHP_PROTO_HASHTABLE_VALUE
get_ce_obj
(
const
void
*
ce
)
{
return
(
PHP_PROTO_HASHTABLE_VALUE
)
get_from_table
(
ce_to_php_obj_map
,
ce
);
}
bool
class_added
(
const
void
*
ce
)
{
return
exist_in_table
(
ce_to_php_obj_map
,
ce
);
}
// -----------------------------------------------------------------------------
...
...
@@ -125,12 +146,23 @@ static PHP_GINIT_FUNCTION(protobuf) {
static
PHP_GSHUTDOWN_FUNCTION
(
protobuf
)
{
}
#if PHP_MAJOR_VERSION >= 7
static
void
php_proto_hashtable_descriptor_release
(
zval
*
value
)
{
void
*
ptr
=
Z_PTR_P
(
value
);
zend_object
*
object
=
*
(
zend_object
**
)
ptr
;
if
(
--
GC_REFCOUNT
(
object
)
==
0
)
{
zend_objects_store_del
(
object
);
}
efree
(
ptr
);
}
#endif
static
PHP_RINIT_FUNCTION
(
protobuf
)
{
ALLOC_HASHTABLE
(
upb_def_to_php_obj_map
);
zend_hash_init
(
upb_def_to_php_obj_map
,
16
,
NULL
,
ZVAL_PTR
_DTOR
,
0
);
zend_hash_init
(
upb_def_to_php_obj_map
,
16
,
NULL
,
HASHTABLE_VALUE
_DTOR
,
0
);
ALLOC_HASHTABLE
(
ce_to_php_obj_map
);
zend_hash_init
(
ce_to_php_obj_map
,
16
,
NULL
,
ZVAL_PTR
_DTOR
,
0
);
zend_hash_init
(
ce_to_php_obj_map
,
16
,
NULL
,
HASHTABLE_VALUE
_DTOR
,
0
);
generated_pool
=
NULL
;
generated_pool_php
=
NULL
;
...
...
@@ -145,10 +177,12 @@ static PHP_RSHUTDOWN_FUNCTION(protobuf) {
zend_hash_destroy
(
ce_to_php_obj_map
);
FREE_HASHTABLE
(
ce_to_php_obj_map
);
#if PHP_MAJOR_VERSION < 7
if
(
generated_pool_php
!=
NULL
)
{
zval_dtor
(
generated_pool_php
);
FREE_ZVAL
(
generated_pool_php
);
}
#endif
return
0
;
}
...
...
@@ -170,6 +204,7 @@ static PHP_MINIT_FUNCTION(protobuf) {
static
PHP_MSHUTDOWN_FUNCTION
(
protobuf
)
{
PEFREE
(
message_handlers
);
PEFREE
(
repeated_field_handlers
);
PEFREE
(
repeated_field_iter_handlers
);
PEFREE
(
map_field_handlers
);
return
0
;
...
...
php/ext/google/protobuf/protobuf.h
View file @
190b5270
...
...
@@ -42,6 +42,323 @@
#define MAX_LENGTH_OF_INT64 20
#define SIZEOF_INT64 8
// -----------------------------------------------------------------------------
// PHP7 Wrappers
// ----------------------------------------------------------------------------
#if PHP_MAJOR_VERSION < 7
#define php_proto_zend_literal const zend_literal*
#define PHP_PROTO_CASE_IS_BOOL IS_BOOL
#define PHP_PROTO_SIZE int
#define PHP_PROTO_LONG long
#define PHP_PROTO_TSRMLS_DC TSRMLS_DC
#define PHP_PROTO_TSRMLS_CC TSRMLS_CC
// PHP String
#define PHP_PROTO_ZVAL_STRING(zval_ptr, s, copy) \
ZVAL_STRING(zval_ptr, s, copy)
#define PHP_PROTO_ZVAL_STRINGL(zval_ptr, s, len, copy) \
ZVAL_STRINGL(zval_ptr, s, len, copy)
#define PHP_PROTO_RETURN_STRING(s, copy) RETURN_STRING(s, copy)
#define PHP_PROTO_RETURN_STRINGL(s, len, copy) RETURN_STRINGL(s, len, copy)
#define PHP_PROTO_RETVAL_STRINGL(s, len, copy) RETVAL_STRINGL(s, len, copy)
#define php_proto_zend_make_printable_zval(from, to) \
{ \
int use_copy; \
zend_make_printable_zval(from, to, &use_copy); \
}
// PHP Array
#define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(array)
#define php_proto_zend_hash_index_update(ht, h, pData, nDataSize, pDest) \
zend_hash_index_update(ht, h, pData, nDataSize, pDest)
#define php_proto_zend_hash_index_find(ht, h, pDest) \
zend_hash_index_find(ht, h, pDest)
#define php_proto_zend_hash_next_index_insert(ht, pData, nDataSize, pDest) \
zend_hash_next_index_insert(ht, pData, nDataSize, pDest)
#define php_proto_zend_hash_get_current_data_ex(ht, pDest, pos) \
zend_hash_get_current_data_ex(ht, pDest, pos)
// PHP Object
#define PHP_PROTO_WRAP_OBJECT_START(name) \
struct name { \
zend_object std;
#define PHP_PROTO_WRAP_OBJECT_END \
};
#define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
void LOWWERNAME##_init(TSRMLS_D) { \
zend_class_entry class_type; \
const char* class_name = CLASSNAME; \
INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \
LOWWERNAME##_methods); \
LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
LOWWERNAME##_type->create_object = LOWWERNAME##_create; \
LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \
memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \
sizeof(zend_object_handlers));
#define PHP_PROTO_INIT_CLASS_END \
}
#define PHP_PROTO_OBJECT_CREATE_START(NAME, LOWWERNAME) \
static zend_object_value LOWWERNAME##_create( \
zend_class_entry* ce TSRMLS_DC) { \
PHP_PROTO_ALLOC_CLASS_OBJECT(NAME, ce); \
zend_object_std_init(&intern->std, ce TSRMLS_CC); \
object_properties_init(&intern->std, ce);
#define PHP_PROTO_OBJECT_CREATE_END(NAME, LOWWERNAME) \
PHP_PROTO_FREE_CLASS_OBJECT(NAME, LOWWERNAME##_free, LOWWERNAME##_handlers); \
}
#define PHP_PROTO_OBJECT_FREE_START(classname, lowername) \
void lowername##_free(void* object TSRMLS_DC) { \
classname* intern = object;
#define PHP_PROTO_OBJECT_FREE_END \
zend_object_std_dtor(&intern->std TSRMLS_CC); \
efree(intern); \
}
#define PHP_PROTO_OBJECT_DTOR_START(classname, lowername)
#define PHP_PROTO_OBJECT_DTOR_END
#define CACHED_VALUE zval*
#define CACHED_TO_ZVAL_PTR(VALUE) (VALUE)
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (*VALUE)
#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (&VALUE)
#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
ZVAL_OBJ(zval_ptr, class_type->create_object(class_type TSRMLS_CC));
#define PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(value) \
SEPARATE_ZVAL_IF_NOT_REF(value)
#define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL EG(uninitialized_zval_ptr)
#define OBJ_PROP(PROPERTIES, OFFSET) (PROPERTIES)->properties_table[OFFSET]
#define php_proto_zval_ptr_dtor(zval_ptr) \
zval_ptr_dtor(&(zval_ptr))
#define PHP_PROTO_ALLOC_CLASS_OBJECT(class_object, class_type) \
class_object* intern; \
intern = (class_object*)emalloc(sizeof(class_object)); \
memset(intern, 0, sizeof(class_object));
#define PHP_PROTO_FREE_CLASS_OBJECT(class_object, class_object_free, handler) \
zend_object_value retval = {0}; \
retval.handle = zend_objects_store_put( \
intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \
class_object_free, NULL TSRMLS_CC); \
retval.handlers = handler; \
return retval;
#define PHP_PROTO_ALLOC_ARRAY(zval_ptr) \
ALLOC_HASHTABLE(Z_ARRVAL_P(zval_ptr)); \
Z_TYPE_P(zval_ptr) = IS_ARRAY;
#define ZVAL_OBJ(zval_ptr, call_create) \
Z_TYPE_P(zval_ptr) = IS_OBJECT; \
Z_OBJVAL_P(zval_ptr) = call_create;
#define UNBOX(class_name, val) \
(class_name*)zend_object_store_get_object(val TSRMLS_CC);
#define UNBOX_HASHTABLE_VALUE(class_name, val) UNBOX(class_name, val)
#define HASHTABLE_VALUE_DTOR ZVAL_PTR_DTOR
#define PHP_PROTO_HASHTABLE_VALUE zval*
#define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \
OBJ_TYPE* OBJ; \
PHP_PROTO_HASHTABLE_VALUE WRAPPED_OBJ; \
MAKE_STD_ZVAL(WRAPPED_OBJ); \
ZVAL_OBJ(WRAPPED_OBJ, \
OBJ_CLASS_ENTRY->create_object(OBJ_CLASS_ENTRY TSRMLS_CC)); \
OBJ = UNBOX_HASHTABLE_VALUE(OBJ_TYPE, WRAPPED_OBJ); \
Z_DELREF_P(desc_php);
#define PHP_PROTO_CE_DECLARE zend_class_entry**
#define PHP_PROTO_CE_UNREF(ce) (*ce)
#define php_proto_zend_lookup_class(name, name_length, ce) \
zend_lookup_class(name, name_length, ce TSRMLS_CC)
#else // PHP_MAJOR_VERSION >= 7
#define php_proto_zend_literal void**
#define PHP_PROTO_CASE_IS_BOOL IS_TRUE: case IS_FALSE
#define PHP_PROTO_SIZE size_t
#define PHP_PROTO_LONG zend_long
#define PHP_PROTO_TSRMLS_DC
#define PHP_PROTO_TSRMLS_CC
// PHP String
#define PHP_PROTO_ZVAL_STRING(zval_ptr, s, copy) \
ZVAL_STRING(zval_ptr, s)
#define PHP_PROTO_ZVAL_STRINGL(zval_ptr, s, len, copy) \
ZVAL_STRINGL(zval_ptr, s, len)
#define PHP_PROTO_RETURN_STRING(s, copy) RETURN_STRING(s)
#define PHP_PROTO_RETURN_STRINGL(s, len, copy) RETURN_STRINGL(s, len)
#define PHP_PROTO_RETVAL_STRINGL(s, len, copy) RETVAL_STRINGL(s, len)
#define php_proto_zend_make_printable_zval(from, to) \
zend_make_printable_zval(from, to)
// PHP Array
#define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(&array)
static
inline
int
php_proto_zend_hash_index_update
(
HashTable
*
ht
,
ulong
h
,
void
*
pData
,
uint
nDataSize
,
void
**
pDest
)
{
void
*
result
=
NULL
;
result
=
zend_hash_index_update_mem
(
ht
,
h
,
pData
,
nDataSize
);
if
(
pDest
!=
NULL
)
*
pDest
=
result
;
return
result
!=
NULL
?
SUCCESS
:
FAILURE
;
}
static
inline
int
php_proto_zend_hash_index_find
(
const
HashTable
*
ht
,
ulong
h
,
void
**
pDest
)
{
void
*
result
=
NULL
;
result
=
zend_hash_index_find_ptr
(
ht
,
h
);
if
(
pDest
!=
NULL
)
*
pDest
=
result
;
return
result
!=
NULL
?
SUCCESS
:
FAILURE
;
}
static
inline
int
php_proto_zend_hash_next_index_insert
(
HashTable
*
ht
,
void
*
pData
,
uint
nDataSize
,
void
**
pDest
)
{
void
*
result
=
NULL
;
result
=
zend_hash_next_index_insert_mem
(
ht
,
pData
,
nDataSize
);
if
(
pDest
!=
NULL
)
*
pDest
=
result
;
return
result
!=
NULL
?
SUCCESS
:
FAILURE
;
}
static
inline
int
php_proto_zend_hash_get_current_data_ex
(
HashTable
*
ht
,
void
**
pDest
,
HashPosition
*
pos
)
{
void
*
result
=
NULL
;
result
=
zend_hash_get_current_data_ex
(
ht
,
pos
);
if
(
pDest
!=
NULL
)
*
pDest
=
result
;
return
result
!=
NULL
?
SUCCESS
:
FAILURE
;
}
// PHP Object
#define PHP_PROTO_WRAP_OBJECT_START(name) struct name {
#define PHP_PROTO_WRAP_OBJECT_END \
zend_object std; \
};
#define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
void LOWWERNAME##_init(TSRMLS_D) { \
zend_class_entry class_type; \
const char* class_name = CLASSNAME; \
INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \
LOWWERNAME##_methods); \
LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
LOWWERNAME##_type->create_object = LOWWERNAME##_create; \
LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \
memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \
sizeof(zend_object_handlers)); \
LOWWERNAME##_handlers->free_obj = LOWWERNAME##_free; \
LOWWERNAME##_handlers->dtor_obj = LOWWERNAME##_dtor; \
LOWWERNAME##_handlers->offset = XtOffsetOf(CAMELNAME, std);
#define PHP_PROTO_INIT_CLASS_END \
}
#define PHP_PROTO_OBJECT_FREE_START(classname, lowername) \
void lowername##_free(zend_object* object) { \
classname* intern = \
(classname*)((char*)object - XtOffsetOf(classname, std));
#define PHP_PROTO_OBJECT_FREE_END \
}
#define PHP_PROTO_OBJECT_DTOR_START(classname, lowername) \
void lowername##_dtor(zend_object* object) { \
classname* intern = \
(classname*)((char*)object - XtOffsetOf(classname, std));
#define PHP_PROTO_OBJECT_DTOR_END \
zend_object_std_dtor(object TSRMLS_CC); \
}
#define PHP_PROTO_OBJECT_CREATE_START(NAME, LOWWERNAME) \
static zend_object* LOWWERNAME##_create(zend_class_entry* ce TSRMLS_DC) { \
PHP_PROTO_ALLOC_CLASS_OBJECT(NAME, ce); \
zend_object_std_init(&intern->std, ce TSRMLS_CC); \
object_properties_init(&intern->std, ce);
#define PHP_PROTO_OBJECT_CREATE_END(NAME, LOWWERNAME) \
PHP_PROTO_FREE_CLASS_OBJECT(NAME, LOWWERNAME##_free, LOWWERNAME##_handlers); \
}
#define CACHED_VALUE zval
#define CACHED_TO_ZVAL_PTR(VALUE) (&VALUE)
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (VALUE)
#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (VALUE)
#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
ZVAL_OBJ(zval_ptr, class_type->create_object(class_type));
#define PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(value) ;
#define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL &EG(uninitialized_zval)
#define php_proto_zval_ptr_dtor(zval_ptr) \
zval_ptr_dtor(zval_ptr)
#define PHP_PROTO_ALLOC_CLASS_OBJECT(class_object, class_type) \
class_object* intern; \
int size = sizeof(class_object) + zend_object_properties_size(class_type); \
intern = ecalloc(1, size); \
memset(intern, 0, size);
#define PHP_PROTO_FREE_CLASS_OBJECT(class_object, class_object_free, handler) \
intern->std.handlers = handler; \
return &intern->std;
#define PHP_PROTO_ALLOC_ARRAY(zval_ptr) \
ZVAL_NEW_ARR(zval_ptr)
#define UNBOX(class_name, val) \
(class_name*)((char*)Z_OBJ_P(val) - XtOffsetOf(class_name, std));
#define UNBOX_HASHTABLE_VALUE(class_name, val) \
(class_name*)((char*)val - XtOffsetOf(class_name, std))
#define HASHTABLE_VALUE_DTOR php_proto_hashtable_descriptor_release
#define PHP_PROTO_HASHTABLE_VALUE zend_object*
#define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \
OBJ_TYPE* OBJ; \
PHP_PROTO_HASHTABLE_VALUE WRAPPED_OBJ; \
WRAPPED_OBJ = OBJ_CLASS_ENTRY->create_object(OBJ_CLASS_ENTRY); \
OBJ = UNBOX_HASHTABLE_VALUE(OBJ_TYPE, WRAPPED_OBJ); \
--GC_REFCOUNT(WRAPPED_OBJ);
#define PHP_PROTO_CE_DECLARE zend_class_entry*
#define PHP_PROTO_CE_UNREF(ce) (ce)
static
inline
int
php_proto_zend_lookup_class
(
const
char
*
name
,
int
name_length
,
zend_class_entry
**
ce
TSRMLS_DC
)
{
zend_string
*
zstr_name
=
zend_string_init
(
name
,
name_length
,
0
);
*
ce
=
zend_lookup_class
(
zstr_name
);
zend_string_release
(
zstr_name
);
return
*
ce
!=
NULL
?
SUCCESS
:
FAILURE
;
}
#endif // PHP_MAJOR_VERSION >= 7
// -----------------------------------------------------------------------------
// Forward Declaration
// ----------------------------------------------------------------------------
...
...
@@ -55,7 +372,8 @@ struct MessageHeader;
struct
MessageLayout
;
struct
RepeatedField
;
struct
RepeatedFieldIter
;
struct
MapField
;
struct
Map
;
struct
Oneof
;
typedef
struct
DescriptorPool
DescriptorPool
;
typedef
struct
Descriptor
Descriptor
;
...
...
@@ -66,7 +384,8 @@ typedef struct MessageHeader MessageHeader;
typedef
struct
MessageLayout
MessageLayout
;
typedef
struct
RepeatedField
RepeatedField
;
typedef
struct
RepeatedFieldIter
RepeatedFieldIter
;
typedef
struct
MapField
MapField
;
typedef
struct
Map
Map
;
typedef
struct
Oneof
Oneof
;
// -----------------------------------------------------------------------------
// Globals.
...
...
@@ -88,13 +407,14 @@ void message_init(TSRMLS_D);
// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
// instances.
void
add_def_obj
(
const
void
*
def
,
zval
*
value
);
zval
*
get_def_obj
(
const
void
*
def
);
void
add_def_obj
(
const
void
*
def
,
PHP_PROTO_HASHTABLE_VALUE
value
);
PHP_PROTO_HASHTABLE_VALUE
get_def_obj
(
const
void
*
def
);
// Global map from PHP class entries to wrapper Descriptor/EnumDescriptor
// instances.
void
add_ce_obj
(
const
void
*
ce
,
zval
*
value
);
zval
*
get_ce_obj
(
const
void
*
ce
);
void
add_ce_obj
(
const
void
*
ce
,
PHP_PROTO_HASHTABLE_VALUE
value
);
PHP_PROTO_HASHTABLE_VALUE
get_ce_obj
(
const
void
*
ce
);
bool
class_added
(
const
void
*
ce
);
extern
zend_class_entry
*
map_field_type
;
extern
zend_class_entry
*
repeated_field_type
;
...
...
@@ -103,20 +423,25 @@ extern zend_class_entry* repeated_field_type;
// Descriptor.
// -----------------------------------------------------------------------------
struct
DescriptorPool
{
zend_object
std
;
PHP_PROTO_WRAP_OBJECT_START
(
DescriptorPool
)
upb_symtab
*
symtab
;
HashTable
*
pending_list
;
};
PHP_PROTO_WRAP_OBJECT_END
PHP_METHOD
(
DescriptorPool
,
getGeneratedPool
);
PHP_METHOD
(
DescriptorPool
,
internalAddGeneratedFile
);
extern
zval
*
generated_pool_php
;
// wrapper of generated pool
// wrapper of generated pool
#if PHP_MAJOR_VERSION < 7
extern
zval
*
generated_pool_php
;
void
descriptor_pool_free
(
void
*
object
TSRMLS_DC
);
#else
extern
zend_object
*
generated_pool_php
;
void
descriptor_pool_free
(
zend_object
*
object
);
#endif
extern
DescriptorPool
*
generated_pool
;
// The actual generated pool
struct
Descriptor
{
zend_object
std
;
PHP_PROTO_WRAP_OBJECT_START
(
Descriptor
)
const
upb_msgdef
*
msgdef
;
MessageLayout
*
layout
;
zend_class_entry
*
klass
;
// begins as NULL
...
...
@@ -126,23 +451,21 @@ struct Descriptor {
const
upb_handlers
*
pb_serialize_handlers
;
const
upb_handlers
*
json_serialize_handlers
;
const
upb_handlers
*
json_serialize_handlers_preserve
;
};
PHP_PROTO_WRAP_OBJECT_END
extern
zend_class_entry
*
descriptor_type
;
void
descriptor_name_set
(
Descriptor
*
desc
,
const
char
*
name
);
struct
FieldDescriptor
{
zend_object
std
;
PHP_PROTO_WRAP_OBJECT_START
(
FieldDescriptor
)
const
upb_fielddef
*
fielddef
;
};
PHP_PROTO_WRAP_OBJECT_END
struct
EnumDescriptor
{
zend_object
std
;
PHP_PROTO_WRAP_OBJECT_START
(
EnumDescriptor
)
const
upb_enumdef
*
enumdef
;
zend_class_entry
*
klass
;
// begins as NULL
// VALUE module; // begins as nil
};
PHP_PROTO_WRAP_OBJECT_END
extern
zend_class_entry
*
enum_descriptor_type
;
...
...
@@ -150,13 +473,15 @@ extern zend_class_entry* enum_descriptor_type;
// Message class creation.
// -----------------------------------------------------------------------------
void
*
message_data
(
void
*
msg
);
void
message_create_with_type
(
zend_class_entry
*
ce
,
zval
**
message
TSRMLS_DC
);
void
*
message_data
(
MessageHeader
*
msg
);
void
custom_data_init
(
const
zend_class_entry
*
ce
,
MessageHeader
*
msg
PHP_PROTO_TSRMLS_DC
);
// Build PHP class for given descriptor. Instead of building from scratch, this
// function modifies existing class which has been partially defined in PHP
// code.
void
build_class_from_descriptor
(
zval
*
php_descriptor
TSRMLS_DC
);
void
build_class_from_descriptor
(
PHP_PROTO_HASHTABLE_VALUE
php_descriptor
TSRMLS_DC
);
extern
zend_object_handlers
*
message_handlers
;
...
...
@@ -227,18 +552,17 @@ struct MessageLayout {
size_t
size
;
};
struct
MessageHeader
{
zend_object
std
;
// Stores properties table and class info of PHP instance
.
// This is needed for MessageHeader to be accessed via PHP
.
PHP_PROTO_WRAP_OBJECT_START
(
MessageHeader
)
void
*
data
;
// Point to the real message data
.
// Place needs to be consistent with map_parse_frame_data_t
.
Descriptor
*
descriptor
;
// Kept alive by self.class.descriptor reference.
// The real message data is appended after MessageHeader.
};
PHP_PROTO_WRAP_OBJECT_END
MessageLayout
*
create_layout
(
const
upb_msgdef
*
msgdef
);
void
layout_init
(
MessageLayout
*
layout
,
void
*
storage
,
zval
**
properties_table
TSRMLS_DC
);
CACHED_VALUE
*
properties_table
PHP_PROTO_
TSRMLS_DC
);
zval
*
layout_get
(
MessageLayout
*
layout
,
const
void
*
storage
,
const
upb_fielddef
*
field
,
zval
*
*
cache
TSRMLS_DC
);
const
upb_fielddef
*
field
,
CACHED_VALUE
*
cache
TSRMLS_DC
);
void
layout_set
(
MessageLayout
*
layout
,
MessageHeader
*
header
,
const
upb_fielddef
*
field
,
zval
*
val
TSRMLS_DC
);
void
layout_merge
(
MessageLayout
*
layout
,
MessageHeader
*
from
,
...
...
@@ -308,7 +632,12 @@ PHP_METHOD(Util, checkRepeatedField);
size_t
native_slot_size
(
upb_fieldtype_t
type
);
bool
native_slot_set
(
upb_fieldtype_t
type
,
const
zend_class_entry
*
klass
,
void
*
memory
,
zval
*
value
TSRMLS_DC
);
void
native_slot_init
(
upb_fieldtype_t
type
,
void
*
memory
,
zval
**
cache
);
// String/Message is stored differently in array/map from normal message fields.
// So we need to make a special method to handle that.
bool
native_slot_set_by_array
(
upb_fieldtype_t
type
,
const
zend_class_entry
*
klass
,
void
*
memory
,
zval
*
value
TSRMLS_DC
);
void
native_slot_init
(
upb_fieldtype_t
type
,
void
*
memory
,
void
*
cache
);
// For each property, in order to avoid conversion between the zval object and
// the actual data type during parsing/serialization, the containing message
// object use the custom memory layout to store the actual data type for each
...
...
@@ -317,8 +646,13 @@ void native_slot_init(upb_fieldtype_t type, void* memory, zval** cache);
// for providing such a zval object. Instead the caller needs to provide one
// (cache) and update it with the actual data (memory).
void
native_slot_get
(
upb_fieldtype_t
type
,
const
void
*
memory
,
zval
**
cache
TSRMLS_DC
);
void
native_slot_get_default
(
upb_fieldtype_t
type
,
zval
**
cache
TSRMLS_DC
);
CACHED_VALUE
*
cache
TSRMLS_DC
);
// String/Message is stored differently in array/map from normal message fields.
// So we need to make a special method to handle that.
void
native_slot_get_by_array
(
upb_fieldtype_t
type
,
const
void
*
memory
,
CACHED_VALUE
*
cache
TSRMLS_DC
);
void
native_slot_get_default
(
upb_fieldtype_t
type
,
CACHED_VALUE
*
cache
TSRMLS_DC
);
// -----------------------------------------------------------------------------
// Map Field.
...
...
@@ -326,13 +660,12 @@ void native_slot_get_default(upb_fieldtype_t type, zval** cache TSRMLS_DC);
extern
zend_object_handlers
*
map_field_handlers
;
typedef
struct
{
zend_object
std
;
PHP_PROTO_WRAP_OBJECT_START
(
Map
)
upb_fieldtype_t
key_type
;
upb_fieldtype_t
value_type
;
const
zend_class_entry
*
msg_ce
;
// class entry for value message
upb_strtable
table
;
}
Map
;
PHP_PROTO_WRAP_OBJECT_END
typedef
struct
{
Map
*
self
;
...
...
@@ -349,14 +682,14 @@ upb_value map_iter_value(MapIter* iter, int* len);
const
upb_fielddef
*
map_entry_key
(
const
upb_msgdef
*
msgdef
);
const
upb_fielddef
*
map_entry_value
(
const
upb_msgdef
*
msgdef
);
zend_object_value
map_field_create
(
zend_class_entry
*
ce
TSRMLS_DC
);
void
map_field_create_with_field
(
zend_class_entry
*
ce
,
const
upb_fielddef
*
field
,
zval
**
map_field
TSRMLS_DC
);
void
map_field_create_with_type
(
zend_class_entry
*
ce
,
upb_fieldtype_t
key_type
,
void
map_field_create_with_field
(
const
zend_class_entry
*
ce
,
const
upb_fielddef
*
field
,
CACHED_VALUE
*
map_field
PHP_PROTO_TSRMLS_DC
);
void
map_field_create_with_type
(
const
zend_class_entry
*
ce
,
upb_fieldtype_t
key_type
,
upb_fieldtype_t
value_type
,
const
zend_class_entry
*
msg_ce
,
zval
**
map_field
TSRMLS_DC
);
void
map_field_free
(
void
*
object
TSRMLS_DC
);
const
zend_class_entry
*
msg_ce
,
CACHED_VALUE
*
map_field
PHP_PROTO_TSRMLS_DC
);
void
*
upb_value_memory
(
upb_value
*
v
);
#define MAP_KEY_FIELD 1
...
...
@@ -382,33 +715,36 @@ PHP_METHOD(MapField, count);
// -----------------------------------------------------------------------------
extern
zend_object_handlers
*
repeated_field_handlers
;
extern
zend_object_handlers
*
repeated_field_iter_handlers
;
struct
RepeatedField
{
zend_object
std
;
PHP_PROTO_WRAP_OBJECT_START
(
RepeatedField
)
#if PHP_MAJOR_VERSION < 7
zval
*
array
;
#else
zval
array
;
#endif
upb_fieldtype_t
type
;
const
zend_class_entry
*
msg_ce
;
// class entry for containing message
// (for message field only).
};
PHP_PROTO_WRAP_OBJECT_END
struct
RepeatedFieldIter
{
zend_object
std
;
PHP_PROTO_WRAP_OBJECT_START
(
RepeatedFieldIter
)
RepeatedField
*
repeated_field
;
long
position
;
};
void
repeated_field_create_with_field
(
zend_class_entry
*
ce
,
const
upb_fielddef
*
field
,
zval
**
repeated_field
TSRMLS_DC
);
void
repeated_field_create_with_type
(
zend_class_entry
*
ce
,
upb_fieldtype_t
type
,
const
zend_class_entry
*
msg_ce
,
zval
**
repeated_field
TSRMLS_DC
);
PHP_PROTO_WRAP_OBJECT_END
void
repeated_field_create_with_field
(
zend_class_entry
*
ce
,
const
upb_fielddef
*
field
,
CACHED_VALUE
*
repeated_field
PHP_PROTO_
TSRMLS_DC
);
void
repeated_field_create_with_type
(
zend_class_entry
*
ce
,
upb_fieldtype_t
type
,
const
zend_class_entry
*
msg_ce
,
CACHED_VALUE
*
repeated_field
PHP_PROTO_
TSRMLS_DC
);
// Return the element at the index position from the repeated field. There is
// not restriction on the type of stored elements.
void
*
repeated_field_index_native
(
RepeatedField
*
intern
,
int
index
TSRMLS_DC
);
// Add the element to the end of the repeated field. There is not restriction on
// the type of stored elements.
void
repeated_field_push_native
(
RepeatedField
*
intern
,
void
*
value
TSRMLS_DC
);
void
repeated_field_push_native
(
RepeatedField
*
intern
,
void
*
value
);
PHP_METHOD
(
RepeatedField
,
__construct
);
PHP_METHOD
(
RepeatedField
,
append
);
...
...
@@ -429,12 +765,11 @@ PHP_METHOD(RepeatedFieldIter, valid);
// Oneof Field.
// -----------------------------------------------------------------------------
typedef
struct
{
zend_object
std
;
PHP_PROTO_WRAP_OBJECT_START
(
Oneof
)
upb_oneofdef
*
oneofdef
;
int
index
;
// Index of field in oneof. -1 if not set.
char
value
[
NATIVE_SLOT_MAX_SIZE
];
}
Oneof
;
PHP_PROTO_WRAP_OBJECT_END
// Oneof case slot value to indicate that no oneof case is set. The value `0` is
// safe because field numbers are used as case identifiers, and no field can
...
...
@@ -446,24 +781,13 @@ typedef struct {
// -----------------------------------------------------------------------------
upb_fieldtype_t
to_fieldtype
(
upb_descriptortype_t
type
);
const
zend_class_entry
*
field_type_class
(
const
upb_fielddef
*
field
TSRMLS_DC
);
const
zend_class_entry
*
field_type_class
(
const
upb_fielddef
*
field
PHP_PROTO_TSRMLS_DC
);
// -----------------------------------------------------------------------------
// Utilities.
// -----------------------------------------------------------------------------
// PHP <-> C conversion.
#define UNBOX(class_name, val) \
(class_name*)zend_object_store_get_object(val TSRMLS_CC);
#define BOX(class_name, wrapper, intern, free_func) \
MAKE_STD_ZVAL(wrapper); \
Z_TYPE_P(wrapper) = IS_OBJECT; \
Z_OBJVAL_P(wrapper) \
.handle = \
zend_objects_store_put(intern, NULL, free_func, NULL TSRMLS_CC); \
Z_OBJVAL_P(wrapper).handlers = zend_get_std_object_handlers();
// Memory management
#define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name))
#define PEMALLOC(class_name) (class_name*) pemalloc(sizeof(class_name), 1)
...
...
@@ -471,19 +795,15 @@ const zend_class_entry *field_type_class(const upb_fielddef *field TSRMLS_DC);
#define FREE(object) efree(object)
#define PEFREE(object) pefree(object, 1)
// Create PHP internal instance.
#define CREATE(class_name, intern, init_func) \
intern = ALLOC(class_name); \
memset(intern, 0, sizeof(class_name)); \
init_func(intern TSRMLS_CC);
// String argument.
#define STR(str) (str), strlen(str)
// Zend Value
#if PHP_MAJOR_VERSION < 7
#define Z_OBJ_P(zval_p) \
((zend_object*)(EG(objects_store) \
.object_buckets[Z_OBJ_HANDLE_P(zval_p)] \
.bucket.obj.object))
#endif
#endif // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
php/ext/google/protobuf/storage.c
View file @
190b5270
...
...
@@ -57,7 +57,7 @@ size_t native_slot_size(upb_fieldtype_t type) {
}
}
static
bool
native_slot_is_default
(
upb_fieldtype_t
type
,
void
*
memory
)
{
static
bool
native_slot_is_default
(
upb_fieldtype_t
type
,
const
void
*
memory
)
{
switch
(
type
)
{
#define CASE_TYPE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
...
...
@@ -75,15 +75,17 @@ static bool native_slot_is_default(upb_fieldtype_t type, void* memory) {
#undef CASE_TYPE
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
return
Z_STRLEN_PP
(
DEREF
(
memory
,
zval
**
))
==
0
;
return
Z_STRLEN_P
(
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
memory
,
CACHED_VALUE
*
)))
==
0
;
case
UPB_TYPE_MESSAGE
:
return
Z_TYPE_PP
(
DEREF
(
memory
,
zval
**
))
==
IS_NULL
;
return
Z_TYPE_P
(
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
memory
,
CACHED_VALUE
*
)))
==
IS_NULL
;
default:
return
false
;
}
}
bool
native_slot_set
(
upb_fieldtype_t
type
,
const
zend_class_entry
*
klass
,
void
*
memory
,
zval
*
value
TSRMLS_DC
)
{
void
*
memory
,
zval
*
value
PHP_PROTO_
TSRMLS_DC
)
{
switch
(
type
)
{
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
...
...
@@ -95,14 +97,14 @@ bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
zend_error
(
E_USER_ERROR
,
"Given string is not UTF8 encoded."
);
return
false
;
}
if
(
*
(
zval
**
)
memory
!=
NULL
)
{
zval
*
cached_zval
=
CACHED_PTR_TO_ZVAL_PTR
((
CACHED_VALUE
*
)
memory
);
if
(
EXPECTED
(
cached_zval
!=
NULL
))
{
#if PHP_MAJOR_VERSION < 7
REPLACE_ZVAL_VALUE
((
zval
**
)
memory
,
value
,
1
);
}
else
{
// Handles repeated/map string field. Memory provided by
// RepeatedField/Map is not initialized.
MAKE_STD_ZVAL
(
DEREF
(
memory
,
zval
*
));
ZVAL_STRINGL
(
DEREF
(
memory
,
zval
*
),
Z_STRVAL_P
(
value
),
Z_STRLEN_P
(
value
),
1
);
#else
zend_assign_to_variable
(
cached_zval
,
value
,
IS_CV
);
#endif
}
break
;
}
...
...
@@ -115,13 +117,18 @@ bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
zend_error
(
E_USER_ERROR
,
"Given message does not have correct class."
);
return
false
;
}
if
(
EXPECTED
(
DEREF
(
memory
,
zval
*
)
!=
value
))
{
if
(
DEREF
(
memory
,
zval
*
)
!=
NULL
)
{
zval_ptr_dtor
((
zval
**
)
memory
);
zval
*
property_ptr
=
CACHED_PTR_TO_ZVAL_PTR
((
CACHED_VALUE
*
)
memory
);
if
(
EXPECTED
(
property_ptr
!=
value
))
{
php_proto_zval_ptr_dtor
(
property_ptr
);
}
#if PHP_MAJOR_VERSION < 7
DEREF
(
memory
,
zval
*
)
=
value
;
Z_ADDREF_P
(
value
);
}
#else
ZVAL_ZVAL
(
property_ptr
,
value
,
1
,
0
);
#endif
break
;
}
...
...
@@ -151,7 +158,59 @@ bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
return
true
;
}
void
native_slot_init
(
upb_fieldtype_t
type
,
void
*
memory
,
zval
**
cache
)
{
bool
native_slot_set_by_array
(
upb_fieldtype_t
type
,
const
zend_class_entry
*
klass
,
void
*
memory
,
zval
*
value
TSRMLS_DC
)
{
switch
(
type
)
{
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
if
(
!
protobuf_convert_to_string
(
value
))
{
return
false
;
}
if
(
type
==
UPB_TYPE_STRING
&&
!
is_structurally_valid_utf8
(
Z_STRVAL_P
(
value
),
Z_STRLEN_P
(
value
)))
{
zend_error
(
E_USER_ERROR
,
"Given string is not UTF8 encoded."
);
return
false
;
}
// Handles repeated/map string field. Memory provided by
// RepeatedField/Map is not initialized.
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL
(
DEREF
(
memory
,
zval
*
));
PHP_PROTO_ZVAL_STRINGL
(
DEREF
(
memory
,
zval
*
),
Z_STRVAL_P
(
value
),
Z_STRLEN_P
(
value
),
1
);
#else
*
(
zend_string
**
)
memory
=
zend_string_dup
(
Z_STR_P
(
value
),
0
);
#endif
break
;
}
case
UPB_TYPE_MESSAGE
:
{
if
(
Z_TYPE_P
(
value
)
!=
IS_OBJECT
)
{
zend_error
(
E_USER_ERROR
,
"Given value is not message."
);
return
false
;
}
if
(
Z_TYPE_P
(
value
)
==
IS_OBJECT
&&
klass
!=
Z_OBJCE_P
(
value
))
{
zend_error
(
E_USER_ERROR
,
"Given message does not have correct class."
);
return
false
;
}
#if PHP_MAJOR_VERSION < 7
if
(
EXPECTED
(
DEREF
(
memory
,
zval
*
)
!=
value
))
{
DEREF
(
memory
,
zval
*
)
=
value
;
Z_ADDREF_P
(
value
);
}
#else
DEREF
(
memory
,
zend_object
*
)
=
Z_OBJ_P
(
value
);
++
GC_REFCOUNT
(
Z_OBJ_P
(
value
));
#endif
break
;
}
default:
return
native_slot_set
(
type
,
klass
,
memory
,
value
TSRMLS_CC
);
}
return
true
;
}
void
native_slot_init
(
upb_fieldtype_t
type
,
void
*
memory
,
void
*
cache
)
{
zval
*
tmp
=
NULL
;
switch
(
type
)
{
case
UPB_TYPE_FLOAT
:
...
...
@@ -166,7 +225,7 @@ void native_slot_init(upb_fieldtype_t type, void* memory, zval** cache) {
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
case
UPB_TYPE_MESSAGE
:
DEREF
(
memory
,
zval
*
*
)
=
cache
;
DEREF
(
memory
,
CACHED_VALUE
*
)
=
cache
;
break
;
case
UPB_TYPE_ENUM
:
case
UPB_TYPE_INT32
:
...
...
@@ -187,36 +246,36 @@ void native_slot_init(upb_fieldtype_t type, void* memory, zval** cache) {
}
void
native_slot_get
(
upb_fieldtype_t
type
,
const
void
*
memory
,
zval
*
*
cache
TSRMLS_DC
)
{
CACHED_VALUE
*
cache
TSRMLS_DC
)
{
switch
(
type
)
{
#define CASE(upb_type, php_type, c_type) \
case UPB_TYPE_##upb_type: \
SEPARATE_ZVAL_IF_NOT_REF(cache);
\
ZVAL_##php_type(*cache
, DEREF(memory, c_type)); \
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
\
ZVAL_##php_type(CACHED_PTR_TO_ZVAL_PTR(cache)
, DEREF(memory, c_type)); \
return;
CASE
(
FLOAT
,
DOUBLE
,
float
)
CASE
(
DOUBLE
,
DOUBLE
,
double
)
CASE
(
BOOL
,
BOOL
,
int8_t
)
CASE
(
INT32
,
LONG
,
int32_t
)
CASE
(
ENUM
,
LONG
,
uint32_t
)
CASE
(
FLOAT
,
DOUBLE
,
float
)
CASE
(
DOUBLE
,
DOUBLE
,
double
)
CASE
(
BOOL
,
BOOL
,
int8_t
)
CASE
(
INT32
,
LONG
,
int32_t
)
CASE
(
ENUM
,
LONG
,
uint32_t
)
#undef CASE
#if SIZEOF_LONG == 4
#define CASE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
SEPARATE_ZVAL_IF_NOT_REF(cache);
\
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
\
char buffer[MAX_LENGTH_OF_INT64]; \
sprintf(buffer, "%lld", DEREF(memory, c_type)); \
ZVAL_STRING(*cache, buffer, 1);
\
PHP_PROTO_ZVAL_STRING(CACHED_PTR_TO_ZVAL_PTR(cache), buffer, 1);
\
return; \
}
#else
#define CASE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
SEPARATE_ZVAL_IF_NOT_REF(cache);
\
ZVAL_LONG(*cache, DEREF(memory, c_type));
\
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
\
ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), DEREF(memory, c_type));
\
return; \
}
#endif
...
...
@@ -227,32 +286,34 @@ CASE(INT64, int64_t)
case
UPB_TYPE_UINT32
:
{
// Prepend bit-1 for negative numbers, so that uint32 value will be
// consistent on both 32-bit and 64-bit architectures.
SEPARATE_ZVAL_IF_NOT_REF
(
cache
);
PHP_PROTO_
SEPARATE_ZVAL_IF_NOT_REF
(
cache
);
int
value
=
DEREF
(
memory
,
int32_t
);
if
(
sizeof
(
int
)
==
8
)
{
value
|=
(
-
((
value
>>
31
)
&
0x1
)
&
0xFFFFFFFF00000000
);
}
ZVAL_LONG
(
*
cache
,
value
);
ZVAL_LONG
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
,
value
);
return
;
}
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
// For optional string/bytes fields, the cache is owned by the containing
// message and should have been updated during setting/decoding. However,
// for repeated string/bytes fields, the cache is provided by zend engine
// and has not been updated.
zval
*
value
=
DEREF
(
memory
,
zval
*
);
if
(
*
cache
!=
value
)
{
ZVAL_STRINGL
(
*
cache
,
Z_STRVAL_P
(
value
),
Z_STRLEN_P
(
value
),
1
);
// For optional string/bytes/message fields, the cache is owned by the
// containing message and should have been updated during
// setting/decoding. However, oneof accessor call this function by
// providing the return value directly, which is not the same as the cache
// value.
zval
*
value
=
CACHED_PTR_TO_ZVAL_PTR
((
CACHED_VALUE
*
)
memory
);
if
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
!=
value
)
{
PHP_PROTO_ZVAL_STRINGL
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
),
Z_STRVAL_P
(
value
),
Z_STRLEN_P
(
value
),
1
);
}
break
;
}
case
UPB_TYPE_MESSAGE
:
{
// Same as above for string/bytes fields.
zval
*
value
=
DEREF
(
memory
,
zval
*
);
if
(
*
cache
!=
value
)
{
ZVAL_ZVAL
(
*
cache
,
value
,
1
,
0
);
zval
*
value
=
CACHED_PTR_TO_ZVAL_PTR
((
CACHED_VALUE
*
)
memory
);
if
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
!=
value
)
{
ZVAL_ZVAL
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
,
value
,
1
,
0
);
}
return
;
}
...
...
@@ -261,12 +322,46 @@ CASE(INT64, int64_t)
}
}
void
native_slot_get_default
(
upb_fieldtype_t
type
,
zval
**
cache
TSRMLS_DC
)
{
void
native_slot_get_by_array
(
upb_fieldtype_t
type
,
const
void
*
memory
,
CACHED_VALUE
*
cache
TSRMLS_DC
)
{
switch
(
type
)
{
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
#if PHP_MAJOR_VERSION < 7
zval
*
value
=
CACHED_PTR_TO_ZVAL_PTR
((
CACHED_VALUE
*
)
memory
);
if
(
EXPECTED
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
!=
value
))
{
PHP_PROTO_ZVAL_STRINGL
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
),
Z_STRVAL_P
(
value
),
Z_STRLEN_P
(
value
),
1
);
}
#else
ZVAL_NEW_STR
(
cache
,
zend_string_dup
(
*
(
zend_string
**
)
memory
,
0
));
#endif
return
;
}
case
UPB_TYPE_MESSAGE
:
{
#if PHP_MAJOR_VERSION < 7
zval
*
value
=
CACHED_PTR_TO_ZVAL_PTR
((
CACHED_VALUE
*
)
memory
);
if
(
EXPECTED
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
!=
value
))
{
ZVAL_ZVAL
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
),
value
,
1
,
0
);
}
#else
++
GC_REFCOUNT
(
*
(
zend_object
**
)
memory
);
ZVAL_OBJ
(
cache
,
*
(
zend_object
**
)
memory
);
#endif
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
)
{
#define CASE(upb_type, php_type) \
case UPB_TYPE_##upb_type: \
SEPARATE_ZVAL_IF_NOT_REF(cache);
\
ZVAL_##php_type(
*cache, 0);
\
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
\
ZVAL_##php_type(
CACHED_PTR_TO_ZVAL_PTR(cache), 0);
\
return;
CASE
(
FLOAT
,
DOUBLE
)
...
...
@@ -281,15 +376,15 @@ void native_slot_get_default(upb_fieldtype_t type, zval** cache TSRMLS_DC) {
#if SIZEOF_LONG == 4
#define CASE(upb_type) \
case UPB_TYPE_##upb_type: { \
SEPARATE_ZVAL_IF_NOT_REF(cache);
\
ZVAL_STRING(*cache, "0", 1);
\
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
\
PHP_PROTO_ZVAL_STRING(CACHED_PTR_TO_ZVAL_PTR(cache), "0", 1);
\
return; \
}
#else
#define CASE(upb_type) \
case UPB_TYPE_##upb_type: { \
SEPARATE_ZVAL_IF_NOT_REF(cache);
\
ZVAL_LONG(*cache, 0);
\
PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(cache);
\
ZVAL_LONG(CACHED_PTR_TO_ZVAL_PTR(cache), 0);
\
return; \
}
#endif
...
...
@@ -299,13 +394,13 @@ CASE(INT64)
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
SEPARATE_ZVAL_IF_NOT_REF
(
cache
);
ZVAL_STRINGL
(
*
cache
,
""
,
0
,
1
);
PHP_PROTO_
SEPARATE_ZVAL_IF_NOT_REF
(
cache
);
PHP_PROTO_ZVAL_STRINGL
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
,
""
,
0
,
1
);
break
;
}
case
UPB_TYPE_MESSAGE
:
{
SEPARATE_ZVAL_IF_NOT_REF
(
cache
);
ZVAL_NULL
(
*
cache
);
PHP_PROTO_
SEPARATE_ZVAL_IF_NOT_REF
(
cache
);
ZVAL_NULL
(
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
);
return
;
}
default:
...
...
@@ -359,14 +454,15 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
return
value_field
;
}
const
zend_class_entry
*
field_type_class
(
const
upb_fielddef
*
field
TSRMLS_DC
)
{
const
zend_class_entry
*
field_type_class
(
const
upb_fielddef
*
field
PHP_PROTO_TSRMLS_DC
)
{
if
(
upb_fielddef_type
(
field
)
==
UPB_TYPE_MESSAGE
)
{
zval
*
desc_php
=
get_def_obj
(
upb_fielddef_subdef
(
field
));
Descriptor
*
desc
=
zend_object_store_get_object
(
desc_php
TSRMLS_CC
);
Descriptor
*
desc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_def_obj
(
upb_fielddef_subdef
(
field
))
);
return
desc
->
klass
;
}
else
if
(
upb_fielddef_type
(
field
)
==
UPB_TYPE_ENUM
)
{
zval
*
desc_php
=
get_def_obj
(
upb_fielddef_subdef
(
field
));
EnumDescriptor
*
desc
=
zend_object_store_get_object
(
desc_php
TSRMLS_CC
);
EnumDescriptor
*
desc
=
UNBOX_HASHTABLE_VALUE
(
EnumDescriptor
,
get_def_obj
(
upb_fielddef_subdef
(
field
))
);
return
desc
->
klass
;
}
return
NULL
;
...
...
@@ -501,7 +597,7 @@ void free_layout(MessageLayout* layout) {
}
void
layout_init
(
MessageLayout
*
layout
,
void
*
storage
,
zval
**
properties_table
TSRMLS_DC
)
{
CACHED_VALUE
*
properties_table
PHP_PROTO_
TSRMLS_DC
)
{
int
i
;
upb_msg_field_iter
it
;
for
(
upb_msg_field_begin
(
&
it
,
layout
->
msgdef
),
i
=
0
;
!
upb_msg_field_done
(
&
it
);
...
...
@@ -510,20 +606,27 @@ void layout_init(MessageLayout* layout, void* storage,
void
*
memory
=
slot_memory
(
layout
,
storage
,
field
);
uint32_t
*
oneof_case
=
slot_oneof_case
(
layout
,
storage
,
field
);
int
cache_index
=
slot_property_cache
(
layout
,
storage
,
field
);
zval
*
*
property_ptr
=
&
properties_table
[
cache_index
];
CACHED_VALUE
*
property_ptr
=
&
properties_table
[
cache_index
];
if
(
upb_fielddef_containingoneof
(
field
))
{
memset
(
memory
,
0
,
NATIVE_SLOT_MAX_SIZE
);
*
oneof_case
=
ONEOF_CASE_NONE
;
}
else
if
(
is_map_field
(
field
))
{
zval_ptr_dtor
(
property_ptr
);
map_field_create_with_field
(
map_field_type
,
field
,
property_ptr
TSRMLS_CC
);
DEREF
(
memory
,
zval
**
)
=
property_ptr
;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL
(
*
property_ptr
);
#endif
map_field_create_with_field
(
map_field_type
,
field
,
property_ptr
PHP_PROTO_TSRMLS_CC
);
DEREF
(
memory
,
CACHED_VALUE
*
)
=
property_ptr
;
}
else
if
(
upb_fielddef_label
(
field
)
==
UPB_LABEL_REPEATED
)
{
zval_ptr_dtor
(
property_ptr
);
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL
(
*
property_ptr
);
#endif
repeated_field_create_with_field
(
repeated_field_type
,
field
,
property_ptr
TSRMLS_CC
);
DEREF
(
memory
,
zval
*
*
)
=
property_ptr
;
property_ptr
PHP_PROTO_
TSRMLS_CC
);
DEREF
(
memory
,
CACHED_VALUE
*
)
=
property_ptr
;
}
else
{
native_slot_init
(
upb_fielddef_type
(
field
),
memory
,
property_ptr
);
}
...
...
@@ -537,7 +640,7 @@ static void* value_memory(const upb_fielddef* field, void* memory) {
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
case
UPB_TYPE_MESSAGE
:
memory
=
DEREF
(
memory
,
zval
*
*
);
memory
=
DEREF
(
memory
,
CACHED_VALUE
*
);
break
;
default:
// No operation
...
...
@@ -547,7 +650,7 @@ static void* value_memory(const upb_fielddef* field, void* memory) {
}
zval
*
layout_get
(
MessageLayout
*
layout
,
const
void
*
storage
,
const
upb_fielddef
*
field
,
zval
*
*
cache
TSRMLS_DC
)
{
const
upb_fielddef
*
field
,
CACHED_VALUE
*
cache
TSRMLS_DC
)
{
void
*
memory
=
slot_memory
(
layout
,
storage
,
field
);
uint32_t
*
oneof_case
=
slot_oneof_case
(
layout
,
storage
,
field
);
...
...
@@ -558,13 +661,13 @@ zval* layout_get(MessageLayout* layout, const void* storage,
native_slot_get
(
upb_fielddef_type
(
field
),
value_memory
(
field
,
memory
),
cache
TSRMLS_CC
);
}
return
*
cache
;
return
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
;
}
else
if
(
upb_fielddef_label
(
field
)
==
UPB_LABEL_REPEATED
)
{
return
*
cache
;
return
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
;
}
else
{
native_slot_get
(
upb_fielddef_type
(
field
),
value_memory
(
field
,
memory
),
cache
TSRMLS_CC
);
return
*
cache
;
return
CACHED_PTR_TO_ZVAL_PTR
(
cache
)
;
}
}
...
...
@@ -583,8 +686,7 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
switch
(
type
)
{
case
UPB_TYPE_MESSAGE
:
{
const
upb_msgdef
*
msg
=
upb_fielddef_msgsubdef
(
field
);
zval
*
desc_php
=
get_def_obj
(
msg
);
Descriptor
*
desc
=
zend_object_store_get_object
(
desc_php
TSRMLS_CC
);
Descriptor
*
desc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_def_obj
(
msg
));
ce
=
desc
->
klass
;
// Intentionally fall through.
}
...
...
@@ -593,9 +695,9 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
int
property_cache_index
=
header
->
descriptor
->
layout
->
fields
[
upb_fielddef_index
(
field
)]
.
cache_index
;
DEREF
(
memory
,
zval
*
*
)
=
DEREF
(
memory
,
CACHED_VALUE
*
)
=
&
(
header
->
std
.
properties_table
)[
property_cache_index
];
memory
=
DEREF
(
memory
,
zval
*
*
);
memory
=
DEREF
(
memory
,
CACHED_VALUE
*
);
break
;
}
default:
...
...
@@ -606,27 +708,130 @@ void layout_set(MessageLayout* layout, MessageHeader* header,
*
oneof_case
=
upb_fielddef_number
(
field
);
}
else
if
(
upb_fielddef_label
(
field
)
==
UPB_LABEL_REPEATED
)
{
// Works for both repeated and map fields
memory
=
DEREF
(
memory
,
zval
**
);
if
(
EXPECTED
(
DEREF
(
memory
,
zval
*
)
!=
val
))
{
zval_ptr_dtor
(
memory
);
DEREF
(
memory
,
zval
*
)
=
val
;
Z_ADDREF_P
(
val
);
memory
=
DEREF
(
memory
,
void
**
);
zval
*
property_ptr
=
CACHED_PTR_TO_ZVAL_PTR
((
CACHED_VALUE
*
)
memory
);
if
(
EXPECTED
(
property_ptr
!=
val
))
{
#if PHP_MAJOR_VERSION < 7
REPLACE_ZVAL_VALUE
((
zval
**
)
memory
,
val
,
1
);
#else
php_proto_zval_ptr_dtor
(
property_ptr
);
ZVAL_ZVAL
(
property_ptr
,
val
,
1
,
0
);
#endif
}
}
else
{
upb_fieldtype_t
type
=
upb_fielddef_type
(
field
);
zend_class_entry
*
ce
=
NULL
;
if
(
type
==
UPB_TYPE_MESSAGE
)
{
const
upb_msgdef
*
msg
=
upb_fielddef_msgsubdef
(
field
);
zval
*
desc_php
=
get_def_obj
(
msg
);
Descriptor
*
desc
=
zend_object_store_get_object
(
desc_php
TSRMLS_CC
);
Descriptor
*
desc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_def_obj
(
msg
));
ce
=
desc
->
klass
;
}
native_slot_set
(
type
,
ce
,
value_memory
(
field
,
memory
),
val
TSRMLS_CC
);
}
}
static
native_slot_merge
(
const
upb_fielddef
*
field
,
const
void
*
from_memory
,
void
*
to_memory
PHP_PROTO_TSRMLS_DC
)
{
upb_fieldtype_t
type
=
upb_fielddef_type
(
field
);
zend_class_entry
*
ce
=
NULL
;
if
(
!
native_slot_is_default
(
type
,
from_memory
))
{
switch
(
type
)
{
#define CASE_TYPE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
DEREF(to_memory, c_type) = DEREF(from_memory, c_type); \
break; \
}
CASE_TYPE
(
INT32
,
int32_t
)
CASE_TYPE
(
UINT32
,
uint32_t
)
CASE_TYPE
(
ENUM
,
int32_t
)
CASE_TYPE
(
INT64
,
int64_t
)
CASE_TYPE
(
UINT64
,
uint64_t
)
CASE_TYPE
(
FLOAT
,
float
)
CASE_TYPE
(
DOUBLE
,
double
)
CASE_TYPE
(
BOOL
,
int8_t
)
#undef CASE_TYPE
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
native_slot_set
(
type
,
NULL
,
value_memory
(
field
,
to_memory
),
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
from_memory
,
CACHED_VALUE
*
))
PHP_PROTO_TSRMLS_CC
);
break
;
case
UPB_TYPE_MESSAGE
:
{
const
upb_msgdef
*
msg
=
upb_fielddef_msgsubdef
(
field
);
Descriptor
*
desc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_def_obj
(
msg
));
ce
=
desc
->
klass
;
if
(
native_slot_is_default
(
type
,
to_memory
))
{
#if PHP_MAJOR_VERSION < 7
SEPARATE_ZVAL_IF_NOT_REF
((
zval
**
)
value_memory
(
field
,
to_memory
));
#endif
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR
(
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
to_memory
,
CACHED_VALUE
*
)),
ce
);
MessageHeader
*
submsg
=
UNBOX
(
MessageHeader
,
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
to_memory
,
CACHED_VALUE
*
)));
custom_data_init
(
ce
,
submsg
PHP_PROTO_TSRMLS_CC
);
}
MessageHeader
*
sub_from
=
UNBOX
(
MessageHeader
,
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
from_memory
,
CACHED_VALUE
*
)));
MessageHeader
*
sub_to
=
UNBOX
(
MessageHeader
,
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
to_memory
,
CACHED_VALUE
*
)));
layout_merge
(
desc
->
layout
,
sub_from
,
sub_to
PHP_PROTO_TSRMLS_CC
);
break
;
}
}
}
}
static
native_slot_merge_by_array
(
const
upb_fielddef
*
field
,
const
void
*
from_memory
,
void
*
to_memory
PHP_PROTO_TSRMLS_DC
)
{
upb_fieldtype_t
type
=
upb_fielddef_type
(
field
);
switch
(
type
)
{
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL
(
DEREF
(
to_memory
,
zval
*
));
PHP_PROTO_ZVAL_STRINGL
(
DEREF
(
to_memory
,
zval
*
),
Z_STRVAL_P
(
*
(
zval
**
)
from_memory
),
Z_STRLEN_P
(
*
(
zval
**
)
from_memory
),
1
);
#else
DEREF
(
to_memory
,
zend_string
*
)
=
zend_string_dup
(
*
(
zend_string
**
)
from_memory
,
0
);
#endif
break
;
}
case
UPB_TYPE_MESSAGE
:
{
const
upb_msgdef
*
msg
=
upb_fielddef_msgsubdef
(
field
);
Descriptor
*
desc
=
UNBOX_HASHTABLE_VALUE
(
Descriptor
,
get_def_obj
(
msg
));
zend_class_entry
*
ce
=
desc
->
klass
;
#if PHP_MAJOR_VERSION < 7
MAKE_STD_ZVAL
(
DEREF
(
to_memory
,
zval
*
));
CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR
(
DEREF
(
to_memory
,
zval
*
),
ce
);
#else
DEREF
(
to_memory
,
zend_object
*
)
=
ce
->
create_object
(
ce
TSRMLS_CC
);
#endif
MessageHeader
*
sub_from
=
UNBOX_HASHTABLE_VALUE
(
MessageHeader
,
DEREF
(
from_memory
,
PHP_PROTO_HASHTABLE_VALUE
));
MessageHeader
*
sub_to
=
UNBOX_HASHTABLE_VALUE
(
MessageHeader
,
DEREF
(
to_memory
,
PHP_PROTO_HASHTABLE_VALUE
));
custom_data_init
(
ce
,
sub_to
PHP_PROTO_TSRMLS_CC
);
layout_merge
(
desc
->
layout
,
sub_from
,
sub_to
PHP_PROTO_TSRMLS_CC
);
break
;
}
default:
native_slot_merge
(
field
,
from_memory
,
to_memory
PHP_PROTO_TSRMLS_CC
);
break
;
}
}
void
layout_merge
(
MessageLayout
*
layout
,
MessageHeader
*
from
,
MessageHeader
*
to
TSRMLS_DC
)
{
MessageHeader
*
to
PHP_PROTO_
TSRMLS_DC
)
{
int
i
,
j
;
upb_msg_field_iter
it
;
...
...
@@ -639,11 +844,10 @@ void layout_merge(MessageLayout* layout, MessageHeader* from,
if
(
upb_fielddef_containingoneof
(
field
))
{
uint32_t
oneof_case_offset
=
layout
->
fields
[
upb_fielddef_index
(
field
)].
case_offset
+
sizeof
(
MessageHeader
);
layout
->
fields
[
upb_fielddef_index
(
field
)].
case_offset
;
// For a oneof, check that this field is actually present -- skip all the
// below if not.
if
(
DEREF
((
(
uint8_t
*
)
from
+
oneof_case_offset
),
uint32_t
)
!=
if
(
DEREF
((
message_data
(
from
)
+
oneof_case_offset
),
uint32_t
)
!=
upb_fielddef_number
(
field
))
{
continue
;
}
...
...
@@ -658,7 +862,7 @@ void layout_merge(MessageLayout* layout, MessageHeader* from,
case
UPB_TYPE_BYTES
:
{
int
property_cache_index
=
layout
->
fields
[
upb_fielddef_index
(
field
)].
cache_index
;
DEREF
(
to_memory
,
zval
*
*
)
=
DEREF
(
to_memory
,
CACHED_VALUE
*
)
=
&
(
to
->
std
.
properties_table
)[
property_cache_index
];
break
;
}
...
...
@@ -676,141 +880,57 @@ void layout_merge(MessageLayout* layout, MessageHeader* from,
int
size
,
key_length
,
value_length
;
MapIter
map_it
;
zval
*
to_map_php
=
*
DEREF
(
to_memory
,
zval
**
);
zval
*
from_map_php
=
*
DEREF
(
from_memory
,
zval
**
);
Map
*
to_map
=
zend_object_store_get_object
(
to_map_php
TSRMLS_CC
);
Map
*
from_map
=
zend_object_store_get_object
(
from_map_php
TSRMLS_CC
);
zval
*
to_map_php
=
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
to_memory
,
CACHED_VALUE
*
));
zval
*
from_map_php
=
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
from_memory
,
CACHED_VALUE
*
));
Map
*
to_map
=
UNBOX
(
Map
,
to_map_php
);
Map
*
from_map
=
UNBOX
(
Map
,
from_map_php
);
size
=
upb_strtable_count
(
&
from_map
->
table
);
if
(
size
==
0
)
continue
;
const
upb_msgdef
*
mapentry_def
=
upb_fielddef_msgsubdef
(
field
);
const
upb_fielddef
*
value_field
=
upb_msgdef_itof
(
mapentry_def
,
2
);
for
(
map_begin
(
from_map_php
,
&
map_it
TSRMLS_CC
);
!
map_done
(
&
map_it
);
map_next
(
&
map_it
))
{
const
char
*
key
=
map_iter_key
(
&
map_it
,
&
key_length
);
upb_value
value
=
map_iter_value
(
&
map_it
,
&
value_length
);
void
*
mem
=
upb_value_memory
(
&
value
);
switch
(
to_map
->
value_type
)
{
case
UPB_TYPE_MESSAGE
:
{
zval
*
new_message
;
message_create_with_type
(
to_map
->
msg_ce
,
&
new_message
TSRMLS_CC
);
Z_ADDREF_P
(
new_message
);
upb_value
from_value
=
map_iter_value
(
&
map_it
,
&
value_length
);
upb_value
to_value
;
void
*
from_mem
=
upb_value_memory
(
&
from_value
);
void
*
to_mem
=
upb_value_memory
(
&
to_value
);
memset
(
to_mem
,
0
,
native_slot_size
(
to_map
->
value_type
));
zval
*
subdesc_php
=
get_ce_obj
(
to_map
->
msg_ce
);
Descriptor
*
subdesc
=
zend_object_store_get_object
(
subdesc_php
TSRMLS_CC
);
MessageHeader
*
sub_from
=
(
MessageHeader
*
)
zend_object_store_get_object
(
DEREF
(
mem
,
zval
*
)
TSRMLS_CC
);
MessageHeader
*
sub_to
=
(
MessageHeader
*
)
zend_object_store_get_object
(
new_message
TSRMLS_CC
);
layout_merge
(
subdesc
->
layout
,
sub_from
,
sub_to
TSRMLS_CC
);
DEREF
(
mem
,
zval
*
)
=
new_message
;
break
;
}
case
UPB_TYPE_BYTES
:
case
UPB_TYPE_STRING
:
Z_ADDREF_PP
((
zval
**
)
mem
);
break
;
default:
break
;
}
map_index_set
(
to_map
,
key
,
key_length
,
value
);
native_slot_merge_by_array
(
value_field
,
from_mem
,
to_mem
PHP_PROTO_TSRMLS_CC
);
map_index_set
(
to_map
,
key
,
key_length
,
to_value
);
}
}
else
if
(
upb_fielddef_label
(
field
)
==
UPB_LABEL_REPEATED
)
{
zval
*
to_array_php
=
*
DEREF
(
to_memory
,
zval
**
);
zval
*
from_array_php
=
*
DEREF
(
from_memory
,
zval
**
);
RepeatedField
*
to_array
=
zend_object_store_get_object
(
to_array_php
TSRMLS_CC
);
RepeatedField
*
from_array
=
zend_object_store_get_object
(
from_array_php
TSRMLS_CC
);
int
size
=
zend_hash_num_elements
(
HASH_OF
(
from_array
->
array
));
zval
*
to_array_php
=
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
to_memory
,
CACHED_VALUE
*
));
zval
*
from_array_php
=
CACHED_PTR_TO_ZVAL_PTR
(
DEREF
(
from_memory
,
CACHED_VALUE
*
));
RepeatedField
*
to_array
=
UNBOX
(
RepeatedField
,
to_array_php
);
RepeatedField
*
from_array
=
UNBOX
(
RepeatedField
,
from_array_php
);
int
size
=
zend_hash_num_elements
(
PHP_PROTO_HASH_OF
(
from_array
->
array
));
if
(
size
>
0
)
{
for
(
j
=
0
;
j
<
size
;
j
++
)
{
void
*
memory
=
NULL
;
zend_hash_index_find
(
HASH_OF
(
from_array
->
array
),
j
,
(
void
**
)
&
memory
);
switch
(
to_array
->
type
)
{
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
zval
*
str
;
MAKE_STD_ZVAL
(
str
);
ZVAL_STRINGL
(
str
,
Z_STRVAL_PP
((
zval
**
)
memory
),
Z_STRLEN_PP
((
zval
**
)
memory
),
1
);
memory
=
&
str
;
break
;
}
case
UPB_TYPE_MESSAGE
:
{
zval
*
new_message
;
message_create_with_type
(
from_array
->
msg_ce
,
&
new_message
TSRMLS_CC
);
Z_ADDREF_P
(
new_message
);
zval
*
subdesc_php
=
get_ce_obj
(
from_array
->
msg_ce
);
Descriptor
*
subdesc
=
zend_object_store_get_object
(
subdesc_php
TSRMLS_CC
);
MessageHeader
*
sub_from
=
(
MessageHeader
*
)
zend_object_store_get_object
(
DEREF
(
memory
,
zval
*
)
TSRMLS_CC
);
MessageHeader
*
sub_to
=
(
MessageHeader
*
)
zend_object_store_get_object
(
new_message
TSRMLS_CC
);
layout_merge
(
subdesc
->
layout
,
sub_from
,
sub_to
TSRMLS_CC
);
memory
=
&
new_message
;
}
default:
break
;
}
repeated_field_push_native
(
to_array
,
memory
TSRMLS_CC
);
void
*
from_memory
=
NULL
;
void
*
to_memory
=
ALLOC_N
(
char
,
native_slot_size
(
upb_fielddef_type
(
field
)));
memset
(
to_memory
,
0
,
native_slot_size
(
upb_fielddef_type
(
field
)));
php_proto_zend_hash_index_find
(
PHP_PROTO_HASH_OF
(
from_array
->
array
),
j
,
(
void
**
)
&
from_memory
);
native_slot_merge_by_array
(
field
,
from_memory
,
to_memory
PHP_PROTO_TSRMLS_CC
);
repeated_field_push_native
(
to_array
,
to_memory
);
FREE
(
to_memory
);
}
}
}
else
{
upb_fieldtype_t
type
=
upb_fielddef_type
(
field
);
zend_class_entry
*
ce
=
NULL
;
if
(
!
native_slot_is_default
(
type
,
from_memory
))
{
switch
(
type
)
{
#define CASE_TYPE(upb_type, c_type) \
case UPB_TYPE_##upb_type: { \
DEREF(to_memory, c_type) = DEREF(from_memory, c_type); \
break; \
}
CASE_TYPE
(
INT32
,
int32_t
)
CASE_TYPE
(
UINT32
,
uint32_t
)
CASE_TYPE
(
ENUM
,
int32_t
)
CASE_TYPE
(
INT64
,
int64_t
)
CASE_TYPE
(
UINT64
,
uint64_t
)
CASE_TYPE
(
FLOAT
,
float
)
CASE_TYPE
(
DOUBLE
,
double
)
CASE_TYPE
(
BOOL
,
int8_t
)
#undef CASE_TYPE
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
native_slot_set
(
type
,
NULL
,
value_memory
(
field
,
to_memory
),
*
DEREF
(
from_memory
,
zval
**
)
TSRMLS_CC
);
break
;
case
UPB_TYPE_MESSAGE
:
{
const
upb_msgdef
*
msg
=
upb_fielddef_msgsubdef
(
field
);
zval
*
desc_php
=
get_def_obj
(
msg
);
Descriptor
*
desc
=
zend_object_store_get_object
(
desc_php
TSRMLS_CC
);
ce
=
desc
->
klass
;
if
(
native_slot_is_default
(
type
,
to_memory
))
{
zval
*
new_message
=
NULL
;
message_create_with_type
(
ce
,
&
new_message
TSRMLS_CC
);
native_slot_set
(
type
,
ce
,
value_memory
(
field
,
to_memory
),
new_message
TSRMLS_CC
);
}
MessageHeader
*
sub_from
=
(
MessageHeader
*
)
zend_object_store_get_object
(
*
DEREF
(
from_memory
,
zval
**
)
TSRMLS_CC
);
MessageHeader
*
sub_to
=
(
MessageHeader
*
)
zend_object_store_get_object
(
*
DEREF
(
to_memory
,
zval
**
)
TSRMLS_CC
);
layout_merge
(
desc
->
layout
,
sub_from
,
sub_to
TSRMLS_CC
);
}
}
}
native_slot_merge
(
field
,
from_memory
,
to_memory
PHP_PROTO_TSRMLS_CC
);
}
}
}
...
...
php/ext/google/protobuf/type_check.c
View file @
190b5270
...
...
@@ -325,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
;
...
...
@@ -357,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
;
}
...
...
@@ -417,34 +430,45 @@ PHP_METHOD(Util, checkMessage) {
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
,
"zl|C"
,
&
val
,
&
type
,
&
klass
)
==
FAILURE
)
{
return
;
}
#if PHP_MAJOR_VERSION >= 7
if
(
Z_ISREF_P
(
val
))
{
ZVAL_DEREF
(
val
);
}
#endif
if
(
Z_TYPE_P
(
val
)
==
IS_ARRAY
)
{
HashTable
*
table
=
Z_ARRVAL_P
(
val
);
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
);
RepeatedField
*
intern
=
(
RepeatedField
*
)
zend_object_store_get_object
(
repeated_field
TSRMLS_CC
);
for
(
zend_hash_internal_pointer_reset_ex
(
table
,
&
pointer
);
zend_hash_get_current_data_ex
(
table
,
(
void
**
)
&
memory
,
&
pointer
)
==
SUCCESS
;
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
(
repeated_field
,
NULL
,
*
(
zval
**
)
memory
TSRMLS_CC
);
repeated_field_handlers
->
write_dimension
(
CACHED_TO_ZVAL_PTR
(
repeated_field
),
NULL
,
CACHED_PTR_TO_ZVAL_PTR
((
CACHED_VALUE
*
)
memory
)
TSRMLS_CC
);
}
Z_DELREF_P
(
repeated_field
);
RETURN_ZVAL
(
repeated_field
,
1
,
0
);
Z_DELREF_P
(
CACHED_TO_ZVAL_PTR
(
repeated_field
)
);
RETURN_ZVAL
(
CACHED_TO_ZVAL_PTR
(
repeated_field
)
,
1
,
0
);
}
else
if
(
Z_TYPE_P
(
val
)
==
IS_OBJECT
)
{
if
(
!
instanceof_function
(
Z_OBJCE_P
(
val
),
repeated_field_type
TSRMLS_CC
))
{
...
...
@@ -452,8 +476,7 @@ PHP_METHOD(Util, checkRepeatedField) {
repeated_field_type
->
name
);
return
;
}
RepeatedField
*
intern
=
(
RepeatedField
*
)
zend_object_store_get_object
(
val
TSRMLS_CC
);
RepeatedField
*
intern
=
UNBOX
(
RepeatedField
,
val
);
if
(
to_fieldtype
(
type
)
!=
intern
->
type
)
{
zend_error
(
E_USER_ERROR
,
"Incorrect repeated field type."
);
return
;
...
...
@@ -474,43 +497,55 @@ PHP_METHOD(Util, checkRepeatedField) {
PHP_METHOD
(
Util
,
checkMapField
)
{
zval
*
val
;
long
key_type
,
value_type
;
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
;
}
#if PHP_MAJOR_VERSION >= 7
if
(
Z_ISREF_P
(
val
))
{
ZVAL_DEREF
(
val
);
}
#endif
if
(
Z_TYPE_P
(
val
)
==
IS_ARRAY
)
{
HashTable
*
table
=
Z_ARRVAL_P
(
val
);
HashPosition
pointer
;
zval
key
,
*
map_field
;
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
);
Map
*
intern
=
(
Map
*
)
zend_object_store_get_object
(
map_field
TSRMLS_CC
);
for
(
zend_hash_internal_pointer_reset_ex
(
table
,
&
pointer
);
zend_hash_get_current_data_ex
(
table
,
(
void
**
)
&
value
,
&
pointer
)
==
SUCCESS
;
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
(
map_field
,
&
key
,
*
(
zval
**
)
value
TSRMLS_CC
);
map_field_handlers
->
write_dimension
(
CACHED_TO_ZVAL_PTR
(
map_field
),
&
key
,
CACHED_PTR_TO_ZVAL_PTR
((
CACHED_VALUE
*
)
value
)
TSRMLS_CC
);
}
Z_DELREF_P
(
map_field
);
RETURN_ZVAL
(
map_field
,
1
,
0
);
Z_DELREF_P
(
CACHED_TO_ZVAL_PTR
(
map_field
)
);
RETURN_ZVAL
(
CACHED_TO_ZVAL_PTR
(
map_field
)
,
1
,
0
);
}
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
=
(
Map
*
)
zend_object_store_get_object
(
val
TSRMLS_CC
);
Map
*
intern
=
UNBOX
(
Map
,
val
);
if
(
to_fieldtype
(
key_type
)
!=
intern
->
key_type
)
{
zend_error
(
E_USER_ERROR
,
"Incorrect map field key type."
);
return
;
...
...
php/src/Google/Protobuf/Internal/MapField.php
View file @
190b5270
...
...
@@ -284,6 +284,9 @@ class MapField implements \ArrayAccess, \IteratorAggregate, \Countable
GPBUtil
::
checkString
(
$value
,
true
);
break
;
case
GPBType
::
MESSAGE
:
if
(
is_null
(
$value
))
{
trigger_error
(
"Map element cannot be null."
,
E_USER_ERROR
);
}
GPBUtil
::
checkMessage
(
$value
,
$this
->
klass
);
break
;
default
:
...
...
php/src/Google/Protobuf/Internal/RepeatedField.php
View file @
190b5270
...
...
@@ -225,6 +225,10 @@ class RepeatedField implements \ArrayAccess, \IteratorAggregate, \Countable
GPBUtil
::
checkString
(
$value
,
true
);
break
;
case
GPBType
::
MESSAGE
:
if
(
is_null
(
$value
))
{
trigger_error
(
"RepeatedField element cannot be null."
,
E_USER_ERROR
);
}
GPBUtil
::
checkMessage
(
$value
,
$this
->
klass
);
break
;
default
:
...
...
php/tests/array_test.php
View file @
190b5270
...
...
@@ -751,23 +751,13 @@ class RepeatedFieldTest extends PHPUnit_Framework_TestCase
$arr
[]
=
$sub_m
;
$this
->
assertSame
(
1
,
$arr
[
0
]
->
getA
());
$null
=
null
;
$arr
[]
=
$null
;
$this
->
assertNull
(
$arr
[
1
]);
$this
->
assertEquals
(
2
,
count
(
$arr
));
for
(
$i
=
0
;
$i
<
count
(
$arr
);
$i
++
)
{
$arr
[
$i
]
=
$null
;
$this
->
assertNull
(
$arr
[
$i
]);
}
$this
->
assertEquals
(
1
,
count
(
$arr
));
// Test set.
$sub_m
=
new
TestMessage_Sub
();
$sub_m
->
setA
(
2
);
$arr
[
0
]
=
$sub_m
;
$this
->
assertSame
(
1
,
$arr
[
0
]
->
getA
());
$arr
[
1
]
=
$null
;
$this
->
assertNull
(
$arr
[
1
]);
$this
->
assertSame
(
2
,
$arr
[
0
]
->
getA
());
}
/**
...
...
@@ -817,6 +807,27 @@ class RepeatedFieldTest extends PHPUnit_Framework_TestCase
$arr
[]
=
new
TestMessage
;
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public
function
testMessageAppendNullFail
()
{
$arr
=
new
RepeatedField
(
GPBType
::
MESSAGE
,
TestMessage_Sub
::
class
);
$null
=
null
;
$arr
[]
=
$null
;
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public
function
testMessageSetNullFail
()
{
$arr
=
new
RepeatedField
(
GPBType
::
MESSAGE
,
TestMessage_Sub
::
class
);
$arr
[]
=
new
TestMessage_Sub
();
$null
=
null
;
$arr
[
0
]
=
$null
;
}
#########################################################
# Test offset type
#########################################################
...
...
php/tests/gdb_test.sh
View file @
190b5270
...
...
@@ -3,10 +3,8 @@
# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which
# phpunit` --bootstrap autoload.php tmp_test.php
#
gdb
--args
php
-dextension
=
../ext/google/protobuf/modules/protobuf.so
`
which phpunit
`
--bootstrap
autoload.php
array
_test.php
gdb
--args
php
-dextension
=
../ext/google/protobuf/modules/protobuf.so
`
which phpunit
`
--bootstrap
autoload.php
encode_decode
_test.php
#
# # gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so
# memory_leak_test.php
# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
#
# # USE_ZEND_ALLOC=0 valgrind --leak-check=yes php
# -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
# USE_ZEND_ALLOC=0 valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
php/tests/map_field_test.php
View file @
190b5270
...
...
@@ -616,11 +616,7 @@ class MapFieldTest extends PHPUnit_Framework_TestCase {
$arr
[
0
]
=
$sub_m
;
$this
->
assertSame
(
1
,
$arr
[
0
]
->
getA
());
$null
=
NULL
;
$arr
[
1
]
=
$null
;
$this
->
assertNull
(
$arr
[
1
]);
$this
->
assertEquals
(
2
,
count
(
$arr
));
$this
->
assertEquals
(
1
,
count
(
$arr
));
}
/**
...
...
@@ -653,6 +649,17 @@ class MapFieldTest extends PHPUnit_Framework_TestCase {
$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
#########################################################
...
...
php/tests/memory_leak_test.php
View file @
190b5270
...
...
@@ -83,7 +83,8 @@ $n = new TestMessage();
$n
->
mergeFromString
(
$data
);
assert
(
1
===
$n
->
getOneofMessage
()
->
getA
());
$from
=
new
TestMessage
();
$to
=
new
TestMessage
();
TestUtil
::
setTestMessage
(
$from
);
$to
->
mergeFrom
(
$from
);
# $from = new TestMessage();
# $to = new TestMessage();
# TestUtil::setTestMessage($from);
# $to->mergeFrom($from);
# TestUtil::assertTestMessage($to);
php/tests/test_util.php
View file @
190b5270
...
...
@@ -51,8 +51,6 @@ class TestUtil
public
static
function
setTestMessage
(
TestMessage
$m
)
{
$sub
=
new
TestMessage_Sub
();
$m
->
setOptionalInt32
(
-
42
);
$m
->
setOptionalInt64
(
-
43
);
$m
->
setOptionalUint32
(
42
);
...
...
@@ -69,6 +67,7 @@ class TestUtil
$m
->
setOptionalString
(
'a'
);
$m
->
setOptionalBytes
(
'b'
);
$m
->
setOptionalEnum
(
TestEnum
::
ONE
);
$sub
=
new
TestMessage_Sub
();
$m
->
setOptionalMessage
(
$sub
);
$m
->
getOptionalMessage
()
->
SetA
(
33
);
...
...
tests.sh
View file @
190b5270
...
...
@@ -371,12 +371,9 @@ use_php() {
PHP
=
`
which php
`
PHP_CONFIG
=
`
which php-config
`
PHPIZE
=
`
which phpize
`
rm
$PHP
rm
$PHP_CONFIG
rm
$PHPIZE
cp
"/usr/bin/php
$VERSION
"
$PHP
cp
"/usr/bin/php-config
$VERSION
"
$PHP_CONFIG
cp
"/usr/bin/phpize
$VERSION
"
$PHPIZE
ln
-sfn
"/usr/local/php-
${
VERSION
}
/bin/php"
$PHP
ln
-sfn
"/usr/local/php-
${
VERSION
}
/bin/php-config"
$PHP_CONFIG
ln
-sfn
"/usr/local/php-
${
VERSION
}
/bin/phpize"
$PHPIZE
generate_php_test_proto
}
...
...
@@ -403,18 +400,13 @@ use_php_bc() {
}
build_php5.5
()
{
PHP
=
`
which php
`
PHP_CONFIG
=
`
which php-config
`
PHPIZE
=
`
which phpize
`
ln
-sfn
"/usr/local/php-5.5/bin/php"
$PHP
ln
-sfn
"/usr/local/php-5.5/bin/php-config"
$PHP_CONFIG
ln
-sfn
"/usr/local/php-5.5/bin/phpize"
$PHPIZE
generate_php_test_proto
use_php 5.5
pushd
php
rm
-rf
vendor
cp
-r
/usr/local/vendor-5.5 vendor
./vendor/bin/phpunit
wget https://phar.phpunit.de/phpunit-4.8.0.phar
-O
/usr/bin/phpunit
phpunit
popd
pushd
conformance
# TODO(teboring): Add it back
...
...
@@ -423,51 +415,21 @@ build_php5.5() {
}
build_php5.5_c
()
{
PHP
=
`
which php
`
PHP_CONFIG
=
`
which php-config
`
PHPIZE
=
`
which phpize
`
ln
-sfn
"/usr/local/php-5.5/bin/php"
$PHP
ln
-sfn
"/usr/local/php-5.5/bin/php-config"
$PHP_CONFIG
ln
-sfn
"/usr/local/php-5.5/bin/phpize"
$PHPIZE
generate_php_test_proto
wget https://phar.phpunit.de/phpunit-old.phar
-O
/usr/bin/phpunit
use_php 5.5
wget https://phar.phpunit.de/phpunit-4.8.0.phar
-O
/usr/bin/phpunit
cd
php/tests
&&
/bin/bash ./test.sh
&&
cd
../..
pushd
conformance
make test_php_c
#
make test_php_c
popd
}
build_php5.5_zts_c
()
{
use_php_zts 5.5
wget https://phar.phpunit.de/phpunit-
old
.phar
-O
/usr/bin/phpunit
wget https://phar.phpunit.de/phpunit-
4.8.0
.phar
-O
/usr/bin/phpunit
cd
php/tests
&&
/bin/bash ./test.sh
&&
cd
../..
pushd
conformance
make test_php_c
popd
}
build_php5.5_32
()
{
use_php_bc 5.5
pushd
php
rm
-rf
vendor
cp
-r
/usr/local/vendor-5.5 vendor
./vendor/bin/phpunit
popd
# TODO(teboring): Add conformance test.
# pushd conformance
# make test_php
# popd
}
build_php5.5_c_32
()
{
use_php_bc 5.5
wget https://phar.phpunit.de/phpunit-old.phar
-O
/usr/bin/phpunit
cd
php/tests
&&
/bin/bash ./test.sh
&&
cd
../..
# TODO(teboring): Add conformance test.
# pushd conformance
# make test_php_c
#
popd
popd
}
build_php5.6
()
{
...
...
@@ -475,7 +437,8 @@ build_php5.6() {
pushd
php
rm
-rf
vendor
cp
-r
/usr/local/vendor-5.6 vendor
./vendor/bin/phpunit
wget https://phar.phpunit.de/phpunit-5.7.0.phar
-O
/usr/bin/phpunit
phpunit
popd
pushd
conformance
# TODO(teboring): Add it back
...
...
@@ -485,9 +448,19 @@ build_php5.6() {
build_php5.6_c
()
{
use_php 5.6
wget https://phar.phpunit.de/phpunit-5.7.0.phar
-O
/usr/bin/phpunit
cd
php/tests
&&
/bin/bash ./test.sh
&&
cd
../..
pushd
conformance
make test_php_c
# make test_php_c
popd
}
build_php5.6_zts_c
()
{
use_php_zts 5.6
wget https://phar.phpunit.de/phpunit-5.7.0.phar
-O
/usr/bin/phpunit
cd
php/tests
&&
/bin/bash ./test.sh
&&
cd
../..
pushd
conformance
# make test_php_c
popd
}
...
...
@@ -511,7 +484,7 @@ build_php5.6_mac() {
# Test
cd
php/tests
&&
/bin/bash ./test.sh
&&
cd
../..
pushd
conformance
make test_php_c
#
make test_php_c
popd
}
...
...
@@ -520,7 +493,8 @@ build_php7.0() {
pushd
php
rm
-rf
vendor
cp
-r
/usr/local/vendor-7.0 vendor
./vendor/bin/phpunit
wget https://phar.phpunit.de/phpunit-5.6.0.phar
-O
/usr/bin/phpunit
phpunit
popd
pushd
conformance
# TODO(teboring): Add it back
...
...
@@ -530,9 +504,43 @@ build_php7.0() {
build_php7.0_c
()
{
use_php 7.0
wget https://phar.phpunit.de/phpunit-5.6.0.phar
-O
/usr/bin/phpunit
cd
php/tests
&&
/bin/bash ./test.sh
&&
cd
../..
pushd
conformance
make test_php_c
# make test_php_c
popd
}
build_php7.0_zts_c
()
{
use_php_zts 7.0
wget https://phar.phpunit.de/phpunit-5.6.0.phar
-O
/usr/bin/phpunit
cd
php/tests
&&
/bin/bash ./test.sh
&&
cd
../..
pushd
conformance
# make test_php_c
popd
}
build_php7.0_mac
()
{
generate_php_test_proto
# Install PHP
curl
-s
https://php-osx.liip.ch/install.sh | bash
-s
7.0
PHP_FOLDER
=
`
find /usr/local
-type
d
-name
"php7-7.0*"
`
# The folder name may change upon time
export
PATH
=
"
$PHP_FOLDER
/bin:
$PATH
"
# Install phpunit
curl https://phar.phpunit.de/phpunit-5.6.0.phar
-L
-o
phpunit.phar
chmod
+x phpunit.phar
sudo mv
phpunit.phar /usr/local/bin/phpunit
# Install valgrind
echo
"#! /bin/bash"
>
valgrind
chmod
ug+x valgrind
sudo mv
valgrind /usr/local/bin/valgrind
# Test
cd
php/tests
&&
/bin/bash ./test.sh
&&
cd
../..
pushd
conformance
# make test_php_c
popd
}
...
...
@@ -542,13 +550,10 @@ build_php_all() {
build_php7.0
build_php5.5_c
build_php5.6_c
#
build_php7.0_c
build_php7.0_c
build_php5.5_zts_c
}
build_php_all_32
()
{
build_php5.5_32
build_php5.5_c_32
build_php5.6_zts_c
build_php7.0_zts_c
}
# Note: travis currently does not support testing more than one language so the
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment