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
cba04b19
Commit
cba04b19
authored
Feb 08, 2017
by
Paul Yang
Committed by
GitHub
Feb 08, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement json encoding decoding for php. (#2682)
parent
c0027431
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
179 additions
and
14 deletions
+179
-14
conformance_php.php
conformance/conformance_php.php
+13
-3
failure_list_php_c.txt
conformance/failure_list_php_c.txt
+0
-0
def.c
php/ext/google/protobuf/def.c
+15
-0
encode_decode.c
php/ext/google/protobuf/encode_decode.c
+105
-6
message.c
php/ext/google/protobuf/message.c
+18
-0
protobuf.h
php/ext/google/protobuf/protobuf.h
+5
-0
storage.c
php/ext/google/protobuf/storage.c
+1
-0
encode_decode_test.php
php/tests/encode_decode_test.php
+14
-1
tests.sh
tests.sh
+8
-4
No files found.
conformance/conformance_php.php
View file @
cba04b19
...
...
@@ -45,9 +45,19 @@ function doTest($request)
$test_message
=
new
\Protobuf_test_messages\Proto3\TestAllTypes
();
$response
=
new
\Conformance\ConformanceResponse
();
if
(
$request
->
getPayload
()
==
"protobuf_payload"
)
{
$test_message
->
encode
(
$request
->
getProtobufPayload
());
try
{
$test_message
->
decode
(
$request
->
getProtobufPayload
());
}
catch
(
Exception
$e
)
{
$response
->
setParseError
(
$e
->
getMessage
());
return
$response
;
}
}
elseif
(
$request
->
getPayload
()
==
"json_payload"
)
{
// TODO(teboring): Implmement json decoding.
try
{
$test_message
->
jsonDecode
(
$request
->
getJsonPayload
());
}
catch
(
Exception
$e
)
{
$response
->
setParseError
(
$e
->
getMessage
());
return
$response
;
}
}
else
{
trigger_error
(
"Request didn't have payload."
,
E_USER_ERROR
);
}
...
...
@@ -57,7 +67,7 @@ function doTest($request)
}
elseif
(
$request
->
getRequestedOutputFormat
()
==
WireFormat
::
PROTOBUF
)
{
$response
->
setProtobufPayload
(
$test_message
->
encode
());
}
elseif
(
$request
->
getRequestedOutputFormat
()
==
WireFormat
::
JSON
)
{
// TODO(teboring): Implmement json encoding.
$response
->
setJsonPayload
(
$test_message
->
jsonEncode
());
}
return
$response
;
...
...
conformance/failure_list_php_c.txt
View file @
cba04b19
This diff is collapsed.
Click to expand it.
php/ext/google/protobuf/def.c
View file @
cba04b19
...
...
@@ -398,10 +398,22 @@ static void descriptor_free_c(Descriptor *self TSRMLS_DC) {
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
)
{
...
...
@@ -411,7 +423,10 @@ static void descriptor_init_c_instance(Descriptor *desc TSRMLS_DC) {
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
;
}
// -----------------------------------------------------------------------------
...
...
php/ext/google/protobuf/encode_decode.c
View file @
cba04b19
...
...
@@ -103,6 +103,7 @@ static void stackenv_uninit(stackenv* se);
// Callback invoked by upb if any error occurs during parsing or serialization.
static
bool
env_error_func
(
void
*
ud
,
const
upb_status
*
status
)
{
char
err_msg
[
100
]
=
""
;
stackenv
*
se
=
ud
;
// Free the env -- zend_error will longjmp up the stack past the
// encode/decode function so it would not otherwise have been freed.
...
...
@@ -110,7 +111,9 @@ static bool env_error_func(void* ud, const upb_status* status) {
// TODO(teboring): have a way to verify that this is actually a parse error,
// instead of just throwing "parse error" unconditionally.
zend_error
(
E_ERROR
,
se
->
php_error_template
,
upb_status_errmsg
(
status
));
sprintf
(
err_msg
,
se
->
php_error_template
,
upb_status_errmsg
(
status
));
TSRMLS_FETCH
();
zend_throw_exception
(
NULL
,
err_msg
,
0
TSRMLS_CC
);
// Never reached.
return
false
;
}
...
...
@@ -866,6 +869,14 @@ static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
return
desc
->
fill_method
;
}
static
const
upb_json_parsermethod
*
msgdef_jsonparsermethod
(
Descriptor
*
desc
)
{
if
(
desc
->
json_fill_method
==
NULL
)
{
desc
->
json_fill_method
=
upb_json_parsermethod_new
(
desc
->
msgdef
,
&
desc
->
json_fill_method
);
}
return
desc
->
json_fill_method
;
}
// -----------------------------------------------------------------------------
// Serializing.
// -----------------------------------------------------------------------------
...
...
@@ -883,8 +894,8 @@ static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink* sink,
static
void
putarray
(
zval
*
array
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
);
static
void
putmap
(
zval
*
map
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
);
static
void
putmap
(
zval
*
map
,
const
upb_fielddef
*
f
,
upb_sink
*
sink
,
int
depth
TSRMLS_DC
);
static
upb_selector_t
getsel
(
const
upb_fielddef
*
f
,
upb_handlertype_t
type
)
{
upb_selector_t
ret
;
...
...
@@ -961,10 +972,13 @@ static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink,
const
upb_fielddef
*
key_field
;
const
upb_fielddef
*
value_field
;
MapIter
it
;
int
len
;
int
len
,
size
;
if
(
map
==
NULL
)
return
;
self
=
UNBOX
(
Map
,
map
);
assert
(
map
!=
NULL
);
Map
*
intern
=
(
Map
*
)
zend_object_store_get_object
(
map
TSRMLS_CC
);
size
=
upb_strtable_count
(
&
intern
->
table
);
if
(
size
==
0
)
return
;
upb_sink_startseq
(
sink
,
getsel
(
f
,
UPB_HANDLER_STARTSEQ
),
&
subsink
);
...
...
@@ -1197,6 +1211,25 @@ static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
return
desc
->
pb_serialize_handlers
;
}
static
const
upb_handlers
*
msgdef_json_serialize_handlers
(
Descriptor
*
desc
,
bool
preserve_proto_fieldnames
)
{
if
(
preserve_proto_fieldnames
)
{
if
(
desc
->
json_serialize_handlers
==
NULL
)
{
desc
->
json_serialize_handlers
=
upb_json_printer_newhandlers
(
desc
->
msgdef
,
true
,
&
desc
->
json_serialize_handlers
);
}
return
desc
->
json_serialize_handlers
;
}
else
{
if
(
desc
->
json_serialize_handlers_preserve
==
NULL
)
{
desc
->
json_serialize_handlers_preserve
=
upb_json_printer_newhandlers
(
desc
->
msgdef
,
false
,
&
desc
->
json_serialize_handlers_preserve
);
}
return
desc
->
json_serialize_handlers_preserve
;
}
}
// -----------------------------------------------------------------------------
// PHP encode/decode methods
// -----------------------------------------------------------------------------
...
...
@@ -1255,3 +1288,69 @@ PHP_METHOD(Message, decode) {
stackenv_uninit
(
&
se
);
}
}
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
);
zend_bool
preserve_proto_fieldnames
=
false
;
if
(
zend_parse_parameters
(
ZEND_NUM_ARGS
()
TSRMLS_CC
,
"|b"
,
&
preserve_proto_fieldnames
)
==
FAILURE
)
{
return
;
}
stringsink
sink
;
stringsink_init
(
&
sink
);
{
const
upb_handlers
*
serialize_handlers
=
msgdef_json_serialize_handlers
(
desc
,
preserve_proto_fieldnames
);
upb_json_printer
*
printer
;
stackenv
se
;
stackenv_init
(
&
se
,
"Error occurred during encoding: %s"
);
printer
=
upb_json_printer_create
(
&
se
.
env
,
serialize_handlers
,
&
sink
.
sink
);
putmsg
(
getThis
(),
desc
,
upb_json_printer_input
(
printer
),
0
TSRMLS_CC
);
RETVAL_STRINGL
(
sink
.
ptr
,
sink
.
len
,
1
);
stackenv_uninit
(
&
se
);
stringsink_uninit
(
&
sink
);
}
}
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
);
char
*
data
=
NULL
;
int
data_len
;
if
(
zend_parse_parameters
(
ZEND_NUM_ARGS
()
TSRMLS_CC
,
"s"
,
&
data
,
&
data_len
)
==
FAILURE
)
{
return
;
}
// TODO(teboring): Check and respect string encoding. If not UTF-8, we need to
// convert, because string handlers pass data directly to message string
// fields.
// TODO(teboring): Clear message.
{
const
upb_json_parsermethod
*
method
=
msgdef_jsonparsermethod
(
desc
);
stackenv
se
;
upb_sink
sink
;
upb_json_parser
*
parser
;
stackenv_init
(
&
se
,
"Error occurred during parsing: %s"
);
upb_sink_reset
(
&
sink
,
get_fill_handlers
(
desc
),
msg
);
parser
=
upb_json_parser_create
(
&
se
.
env
,
method
,
&
sink
);
upb_bufsrc_putbuf
(
data
,
data_len
,
upb_json_parser_input
(
parser
));
stackenv_uninit
(
&
se
);
}
}
php/ext/google/protobuf/message.c
View file @
cba04b19
...
...
@@ -30,6 +30,7 @@
#include <php.h>
#include <stdlib.h>
#include <ext/json/php_json.h>
#include "protobuf.h"
...
...
@@ -39,6 +40,8 @@ zend_object_handlers* message_handlers;
static
zend_function_entry
message_methods
[]
=
{
PHP_ME
(
Message
,
encode
,
NULL
,
ZEND_ACC_PUBLIC
)
PHP_ME
(
Message
,
decode
,
NULL
,
ZEND_ACC_PUBLIC
)
PHP_ME
(
Message
,
jsonEncode
,
NULL
,
ZEND_ACC_PUBLIC
)
PHP_ME
(
Message
,
jsonDecode
,
NULL
,
ZEND_ACC_PUBLIC
)
PHP_ME
(
Message
,
readOneof
,
NULL
,
ZEND_ACC_PROTECTED
)
PHP_ME
(
Message
,
writeOneof
,
NULL
,
ZEND_ACC_PROTECTED
)
PHP_ME
(
Message
,
whichOneof
,
NULL
,
ZEND_ACC_PROTECTED
)
...
...
@@ -54,6 +57,8 @@ 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
);
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
);
...
...
@@ -74,6 +79,8 @@ void message_init(TSRMLS_D) {
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
;
}
static
void
message_set_property
(
zval
*
object
,
zval
*
member
,
zval
*
value
,
...
...
@@ -144,6 +151,17 @@ static zval** message_get_property_ptr_ptr(zval* object, zval* member, int type,
return
NULL
;
}
static
HashTable
*
message_get_properties
(
zval
*
object
TSRMLS_DC
)
{
return
NULL
;
}
static
HashTable
*
message_get_gc
(
zval
*
object
,
zval
***
table
,
int
*
n
TSRMLS_DC
)
{
zend_object
*
zobj
=
Z_OBJ_P
(
object
);
*
table
=
zobj
->
properties_table
;
*
n
=
zobj
->
ce
->
default_properties_count
;
return
NULL
;
}
// -----------------------------------------------------------------------------
// C Message Utilities
// -----------------------------------------------------------------------------
...
...
php/ext/google/protobuf/protobuf.h
View file @
cba04b19
...
...
@@ -122,7 +122,10 @@ struct Descriptor {
zend_class_entry
*
klass
;
// begins as NULL
const
upb_handlers
*
fill_handlers
;
const
upb_pbdecodermethod
*
fill_method
;
const
upb_json_parsermethod
*
json_fill_method
;
const
upb_handlers
*
pb_serialize_handlers
;
const
upb_handlers
*
json_serialize_handlers
;
const
upb_handlers
*
json_serialize_handlers_preserve
;
};
extern
zend_class_entry
*
descriptor_type
;
...
...
@@ -261,6 +264,8 @@ const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc,
PHP_METHOD
(
Message
,
encode
);
PHP_METHOD
(
Message
,
decode
);
PHP_METHOD
(
Message
,
jsonEncode
);
PHP_METHOD
(
Message
,
jsonDecode
);
// -----------------------------------------------------------------------------
// Type check / conversion.
...
...
php/ext/google/protobuf/storage.c
View file @
cba04b19
...
...
@@ -482,6 +482,7 @@ void layout_init(MessageLayout* layout, void* storage,
repeated_field_create_with_type
(
repeated_field_type
,
field
,
property_ptr
TSRMLS_CC
);
DEREF
(
memory
,
zval
**
)
=
property_ptr
;
property_ptr
=
NULL
;
}
else
{
native_slot_init
(
upb_fielddef_type
(
field
),
memory
,
property_ptr
);
}
...
...
php/tests/encode_decode_test.php
View file @
cba04b19
...
...
@@ -168,9 +168,22 @@ class EncodeDecodeTest extends TestBase
}
}
public
function
testDecodeFieldNonExist
()
{
public
function
testDecodeFieldNonExist
()
{
$data
=
hex2bin
(
'c80501'
);
$m
=
new
TestMessage
();
$m
->
decode
(
$data
);
}
# TODO(teboring): Add test back when php implementation is ready for json
# encode/decode.
# public function testJsonEncode()
# {
# $from = new TestMessage();
# $this->setFields($from);
# $data = $from->jsonEncode();
# $to = new TestMessage();
# $to->jsonDecode($data);
# $this->expectFields($to);
# }
}
tests.sh
View file @
cba04b19
...
...
@@ -406,7 +406,8 @@ build_php5.5() {
./vendor/bin/phpunit
popd
pushd
conformance
make test_php
# TODO(teboring): Add it back
# make test_php
popd
}
...
...
@@ -445,7 +446,8 @@ build_php5.5_c_32() {
wget https://phar.phpunit.de/phpunit-old.phar
-O
/usr/bin/phpunit
cd
php/tests
&&
/bin/bash ./test.sh
&&
cd
../..
pushd
conformance
make test_php_c
# TODO(teboring): Add conformance test.
# make test_php_c
popd
}
...
...
@@ -457,7 +459,8 @@ build_php5.6() {
./vendor/bin/phpunit
popd
pushd
conformance
make test_php
# TODO(teboring): Add it back
# make test_php
popd
}
...
...
@@ -501,7 +504,8 @@ build_php7.0() {
./vendor/bin/phpunit
popd
pushd
conformance
make test_php
# TODO(teboring): Add it back
# make test_php
popd
}
...
...
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