1b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Protocol Buffers - Google's data interchange format 2b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Copyright 2014 Google Inc. All rights reserved. 3b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// https://developers.google.com/protocol-buffers/ 4b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 5b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Redistribution and use in source and binary forms, with or without 6b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// modification, are permitted provided that the following conditions are 7b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// met: 8b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 9b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Redistributions of source code must retain the above copyright 10b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// notice, this list of conditions and the following disclaimer. 11b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Redistributions in binary form must reproduce the above 12b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// copyright notice, this list of conditions and the following disclaimer 13b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// in the documentation and/or other materials provided with the 14b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// distribution. 15b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Neither the name of Google Inc. nor the names of its 16b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// contributors may be used to endorse or promote products derived from 17b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// this software without specific prior written permission. 18b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 19b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 31b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <php.h> 32b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 33b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include "protobuf.h" 34b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 35b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// ----------------------------------------------------------------------------- 36b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Class/module creation from msgdefs and enumdefs, respectively. 37b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// ----------------------------------------------------------------------------- 38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 39b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid* message_data(void* msg) { 40b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return ((uint8_t *)msg) + sizeof(MessageHeader); 41b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 42b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 43b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid message_set_property(zval* object, zval* field_name, zval* value, 44b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer const zend_literal* key TSRMLS_DC) { 45b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer const upb_fielddef* field; 46b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 47b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer MessageHeader* self = zend_object_store_get_object(object TSRMLS_CC); 48b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 49b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer CHECK_TYPE(field_name, IS_STRING); 50b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(field_name)); 51b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (field == NULL) { 52b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zend_error(E_ERROR, "Unknown field: %s", Z_STRVAL_P(field_name)); 53b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 54b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer layout_set(self->descriptor->layout, message_data(self), field, value); 55b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 56b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 57b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerzval* message_get_property(zval* object, zval* member, int type, 58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer const zend_literal* key TSRMLS_DC) { 59b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer MessageHeader* self = 60b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer (MessageHeader*)zend_object_store_get_object(object TSRMLS_CC); 61b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer CHECK_TYPE(member, IS_STRING); 62b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 63b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer const upb_fielddef* field; 64b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member)); 65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (field == NULL) { 66b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return EG(uninitialized_zval_ptr); 67b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zval* retval = layout_get(self->descriptor->layout, message_data(self), field TSRMLS_CC); 69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return retval; 70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic zend_function_entry message_methods[] = { 73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer PHP_ME(Message, encode, NULL, ZEND_ACC_PUBLIC) 74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer {NULL, NULL, NULL} 75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}; 76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* stringsink *****************************************************************/ 78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// This should probably be factored into a common upb component. 80b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 81b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct { 82b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_byteshandler handler; 83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_bytessink sink; 84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer char *ptr; 85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer size_t len, size; 86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} stringsink; 87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 88b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *stringsink_start(void *_sink, const void *hd, size_t size_hint) { 89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer stringsink *sink = _sink; 90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sink->len = 0; 91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return sink; 92b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 93b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t stringsink_string(void *_sink, const void *hd, const char *ptr, 95b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer size_t len, const upb_bufhandle *handle) { 96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer stringsink *sink = _sink; 97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer size_t new_size = sink->size; 98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UPB_UNUSED(hd); 100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer UPB_UNUSED(handle); 101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (sink->len + len > new_size) { 103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer new_size *= 2; 104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (new_size != sink->size) { 107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sink->ptr = realloc(sink->ptr, new_size); 108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sink->size = new_size; 109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer memcpy(sink->ptr + sink->len, ptr, len); 112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sink->len += len; 113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return len; 115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid stringsink_init(stringsink *sink) { 118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_byteshandler_init(&sink->handler); 119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL); 120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL); 121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_bytessink_reset(&sink->sink, &sink->handler, sink); 123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sink->size = 32; 125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sink->ptr = malloc(sink->size); 126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sink->len = 0; 127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid stringsink_uninit(stringsink *sink) { free(sink->ptr); } 130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Stack-allocated context during an encode/decode operation. Contains the upb 132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// environment and its stack-based allocator, an initial buffer for allocations 133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// to avoid malloc() when possible, and a template for PHP exception messages 134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// if any error occurs. 135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define STACK_ENV_STACKBYTES 4096 136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct { 137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_env env; 138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_seededalloc alloc; 139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer const char *php_error_template; 140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer char allocbuf[STACK_ENV_STACKBYTES]; 141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} stackenv; 142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void stackenv_init(stackenv* se, const char* errmsg); 144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void stackenv_uninit(stackenv* se); 145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Callback invoked by upb if any error occurs during parsing or serialization. 147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool env_error_func(void* ud, const upb_status* status) { 148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer stackenv* se = ud; 149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Free the env -- rb_raise will longjmp up the stack past the encode/decode 150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // function so it would not otherwise have been freed. 151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer stackenv_uninit(se); 152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(teboring): have a way to verify that this is actually a parse error, 154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // instead of just throwing "parse error" unconditionally. 155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zend_error(E_ERROR, se->php_error_template); 156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Never reached. 157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return false; 158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void stackenv_init(stackenv* se, const char* errmsg) { 161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer se->php_error_template = errmsg; 162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_env_init(&se->env); 163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_seededalloc_init(&se->alloc, &se->allocbuf, STACK_ENV_STACKBYTES); 164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_env_setallocfunc(&se->env, upb_seededalloc_getallocfunc(&se->alloc), 165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer &se->alloc); 166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_env_seterrorfunc(&se->env, env_error_func, se); 167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void stackenv_uninit(stackenv* se) { 170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_env_uninit(&se->env); 171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_seededalloc_uninit(&se->alloc); 172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// ----------------------------------------------------------------------------- 175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Message 176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// ----------------------------------------------------------------------------- 177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { 179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (desc->pb_serialize_handlers == NULL) { 180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer desc->pb_serialize_handlers = 181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers); 182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return desc->pb_serialize_handlers; 184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerPHP_METHOD(Message, encode) { 187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptor* desc = (Descriptor*)zend_object_store_get_object( 188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer CE_STATIC_MEMBERS(Z_OBJCE_P(getThis()))[0] TSRMLS_CC); 189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer stringsink sink; 191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer stringsink_init(&sink); 192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer const upb_handlers* serialize_handlers = msgdef_pb_serialize_handlers(desc); 195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer stackenv se; 197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer upb_pb_encoder* encoder; 198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer stackenv_init(&se, "Error occurred during encoding: %s"); 200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink); 201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer putmsg(getThis(), desc, upb_pb_encoder_input(encoder), 0); 203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer RETVAL_STRINGL(sink.ptr, sink.len, 1); 205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer stackenv_uninit(&se); 207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer stringsink_uninit(&sink); 208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid message_free(void * object TSRMLS_DC) { 212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer FREE(object); 213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerzend_object_value message_create(zend_class_entry* ce TSRMLS_DC) { 216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zend_object_value return_value; 217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zval* php_descriptor = get_def_obj(ce); 219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptor* desc = zend_object_store_get_object(php_descriptor TSRMLS_CC); 221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer MessageHeader* msg = (MessageHeader*)ALLOC_N( 222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer uint8_t, sizeof(MessageHeader) + desc->layout->size); 223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer memset(message_data(msg), 0, desc->layout->size); 224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // We wrap first so that everything in the message object is GC-rooted in case 226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // a collection happens during object creation in layout_init(). 227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer msg->descriptor = desc; 228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer layout_init(desc->layout, message_data(msg)); 230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zend_object_std_init(&msg->std, ce TSRMLS_CC); 231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return_value.handle = zend_objects_store_put( 233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer msg, (zend_objects_store_dtor_t)zend_objects_destroy_object, 234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer message_free, NULL TSRMLS_CC); 235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return_value.handlers = PROTOBUF_G(message_handlers); 237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return return_value; 238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst zend_class_entry* build_class_from_descriptor( 241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zval* php_descriptor TSRMLS_DC) { 242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Descriptor* desc = php_to_descriptor(php_descriptor); 243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (desc->layout == NULL) { 244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer MessageLayout* layout = create_layout(desc->msgdef); 245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer desc->layout = layout; 246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO(teboring): Add it back. 248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // if (desc->fill_method == NULL) { 249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method); 250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // } 251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer const char* name = upb_msgdef_fullname(desc->msgdef); 253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (name == NULL) { 254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zend_error(E_ERROR, "Descriptor does not have assigned name."); 255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zend_class_entry class_entry; 258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer INIT_CLASS_ENTRY_EX(class_entry, name, strlen(name), message_methods); 259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zend_class_entry* registered_ce = 260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer zend_register_internal_class(&class_entry TSRMLS_CC); 261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer add_def_obj(registered_ce, php_descriptor); 263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (PROTOBUF_G(message_handlers) == NULL) { 265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer PROTOBUF_G(message_handlers) = ALLOC(zend_object_handlers); 266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer memcpy(PROTOBUF_G(message_handlers), zend_get_std_object_handlers(), 267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer sizeof(zend_object_handlers)); 268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer PROTOBUF_G(message_handlers)->write_property = message_set_property; 269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer PROTOBUF_G(message_handlers)->read_property = message_get_property; 270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer registered_ce->create_object = message_create; 273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 274