Merge commit '36bca61764984ff5395653cf8377ec5daa71b709' as 'libs/protobuf'
This commit is contained in:
95
libs/protobuf/php/ext/google/protobuf/arena.c
Normal file
95
libs/protobuf/php/ext/google/protobuf/arena.c
Normal file
@@ -0,0 +1,95 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <Zend/zend_API.h>
|
||||
|
||||
#include "php-upb.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Arena
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
typedef struct Arena {
|
||||
zend_object std;
|
||||
upb_Arena* arena;
|
||||
} Arena;
|
||||
|
||||
zend_class_entry *Arena_class_entry;
|
||||
static zend_object_handlers Arena_object_handlers;
|
||||
|
||||
// PHP Object Handlers /////////////////////////////////////////////////////////
|
||||
|
||||
static zend_object* Arena_Create(zend_class_entry *class_type) {
|
||||
Arena *intern = emalloc(sizeof(Arena));
|
||||
zend_object_std_init(&intern->std, class_type);
|
||||
intern->std.handlers = &Arena_object_handlers;
|
||||
intern->arena = upb_Arena_New();
|
||||
// Skip object_properties_init(), we don't allow derived classes.
|
||||
return &intern->std;
|
||||
}
|
||||
|
||||
static void Arena_Free(zend_object* obj) {
|
||||
Arena* intern = (Arena*)obj;
|
||||
upb_Arena_Free(intern->arena);
|
||||
zend_object_std_dtor(&intern->std);
|
||||
}
|
||||
|
||||
// C Functions from arena.h ////////////////////////////////////////////////////
|
||||
|
||||
void Arena_Init(zval* val) {
|
||||
ZVAL_OBJ(val, Arena_Create(Arena_class_entry));
|
||||
}
|
||||
|
||||
upb_Arena *Arena_Get(zval *val) {
|
||||
Arena *a = (Arena*)Z_OBJ_P(val);
|
||||
return a->arena;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Module init.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// No public methods.
|
||||
static const zend_function_entry Arena_methods[] = {
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
void Arena_ModuleInit() {
|
||||
zend_class_entry tmp_ce;
|
||||
|
||||
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\Arena", Arena_methods);
|
||||
Arena_class_entry = zend_register_internal_class(&tmp_ce);
|
||||
Arena_class_entry->create_object = Arena_Create;
|
||||
Arena_class_entry->ce_flags |= ZEND_ACC_FINAL;
|
||||
|
||||
memcpy(&Arena_object_handlers, &std_object_handlers,
|
||||
sizeof(zend_object_handlers));
|
||||
Arena_object_handlers.free_obj = Arena_Free;
|
||||
}
|
||||
47
libs/protobuf/php/ext/google/protobuf/arena.h
Normal file
47
libs/protobuf/php/ext/google/protobuf/arena.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef PHP_PROTOBUF_ARENA_H_
|
||||
#define PHP_PROTOBUF_ARENA_H_
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "php-upb.h"
|
||||
|
||||
// Registers the PHP Arena class.
|
||||
void Arena_ModuleInit();
|
||||
|
||||
// Creates and returns a new arena object that wraps a new upb_Arena*.
|
||||
void Arena_Init(zval *val);
|
||||
|
||||
// Gets the underlying upb_Arena from this arena object.
|
||||
upb_Arena *Arena_Get(zval *arena);
|
||||
|
||||
#endif // PHP_PROTOBUF_ARENA_H_
|
||||
701
libs/protobuf/php/ext/google/protobuf/array.c
Normal file
701
libs/protobuf/php/ext/google/protobuf/array.c
Normal file
@@ -0,0 +1,701 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "array.h"
|
||||
|
||||
#include <Zend/zend_API.h>
|
||||
#include <Zend/zend_interfaces.h>
|
||||
|
||||
#include <ext/spl/spl_iterators.h>
|
||||
|
||||
// This is not self-contained: it must be after other Zend includes.
|
||||
#include <Zend/zend_exceptions.h>
|
||||
|
||||
#include "arena.h"
|
||||
#include "convert.h"
|
||||
#include "def.h"
|
||||
#include "message.h"
|
||||
#include "php-upb.h"
|
||||
#include "protobuf.h"
|
||||
|
||||
static void RepeatedFieldIter_make(zval *val, zval *repeated_field);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// RepeatedField
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
zend_object std;
|
||||
zval arena;
|
||||
upb_Array *array;
|
||||
TypeInfo type;
|
||||
} RepeatedField;
|
||||
|
||||
zend_class_entry *RepeatedField_class_entry;
|
||||
static zend_object_handlers RepeatedField_object_handlers;
|
||||
|
||||
// PHP Object Handlers /////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* RepeatedField_create()
|
||||
*
|
||||
* PHP class entry function to allocate and initialize a new RepeatedField
|
||||
* object.
|
||||
*/
|
||||
static zend_object* RepeatedField_create(zend_class_entry *class_type) {
|
||||
RepeatedField *intern = emalloc(sizeof(RepeatedField));
|
||||
zend_object_std_init(&intern->std, class_type);
|
||||
intern->std.handlers = &RepeatedField_object_handlers;
|
||||
Arena_Init(&intern->arena);
|
||||
intern->array = NULL;
|
||||
// Skip object_properties_init(), we don't allow derived classes.
|
||||
return &intern->std;
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedField_dtor()
|
||||
*
|
||||
* Object handler to destroy a RepeatedField. This releases all resources
|
||||
* associated with the message. Note that it is possible to access a destroyed
|
||||
* object from PHP in rare cases.
|
||||
*/
|
||||
static void RepeatedField_destructor(zend_object* obj) {
|
||||
RepeatedField* intern = (RepeatedField*)obj;
|
||||
ObjCache_Delete(intern->array);
|
||||
zval_ptr_dtor(&intern->arena);
|
||||
zend_object_std_dtor(&intern->std);
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedField_compare_objects()
|
||||
*
|
||||
* Object handler for comparing two repeated field objects. Called whenever PHP
|
||||
* code does:
|
||||
*
|
||||
* $rf1 == $rf2
|
||||
*/
|
||||
static int RepeatedField_compare_objects(zval *rf1, zval *rf2) {
|
||||
RepeatedField* intern1 = (RepeatedField*)Z_OBJ_P(rf1);
|
||||
RepeatedField* intern2 = (RepeatedField*)Z_OBJ_P(rf2);
|
||||
|
||||
return TypeInfo_Eq(intern1->type, intern2->type) &&
|
||||
ArrayEq(intern1->array, intern2->array, intern1->type)
|
||||
? 0
|
||||
: 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedField_clone_obj()
|
||||
*
|
||||
* Object handler for cloning an object in PHP. Called when PHP code does:
|
||||
*
|
||||
* $rf2 = clone $rf1;
|
||||
*/
|
||||
static zend_object *RepeatedField_clone_obj(PROTO_VAL *object) {
|
||||
RepeatedField* intern = PROTO_VAL_P(object);
|
||||
upb_Arena *arena = Arena_Get(&intern->arena);
|
||||
upb_Array *clone = upb_Array_New(arena, intern->type.type);
|
||||
size_t n = upb_Array_Size(intern->array);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
upb_MessageValue msgval = upb_Array_Get(intern->array, i);
|
||||
upb_Array_Append(clone, msgval, arena);
|
||||
}
|
||||
|
||||
zval ret;
|
||||
RepeatedField_GetPhpWrapper(&ret, clone, intern->type, &intern->arena);
|
||||
return Z_OBJ_P(&ret);
|
||||
}
|
||||
|
||||
static HashTable *RepeatedField_GetProperties(PROTO_VAL *object) {
|
||||
return NULL; // We do not have a properties table.
|
||||
}
|
||||
|
||||
static zval *RepeatedField_GetPropertyPtrPtr(PROTO_VAL *object,
|
||||
PROTO_STR *member,
|
||||
int type, void **cache_slot) {
|
||||
return NULL; // We don't offer direct references to our properties.
|
||||
}
|
||||
|
||||
// C Functions from array.h ////////////////////////////////////////////////////
|
||||
|
||||
// These are documented in the header file.
|
||||
|
||||
void RepeatedField_GetPhpWrapper(zval *val, upb_Array *arr, TypeInfo type,
|
||||
zval *arena) {
|
||||
if (!arr) {
|
||||
ZVAL_NULL(val);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ObjCache_Get(arr, val)) {
|
||||
RepeatedField *intern = emalloc(sizeof(RepeatedField));
|
||||
zend_object_std_init(&intern->std, RepeatedField_class_entry);
|
||||
intern->std.handlers = &RepeatedField_object_handlers;
|
||||
ZVAL_COPY(&intern->arena, arena);
|
||||
intern->array = arr;
|
||||
intern->type = type;
|
||||
// Skip object_properties_init(), we don't allow derived classes.
|
||||
ObjCache_Add(intern->array, &intern->std);
|
||||
ZVAL_OBJ(val, &intern->std);
|
||||
}
|
||||
}
|
||||
|
||||
upb_Array *RepeatedField_GetUpbArray(zval *val, TypeInfo type,
|
||||
upb_Arena *arena) {
|
||||
if (Z_ISREF_P(val)) {
|
||||
ZVAL_DEREF(val);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(val) == IS_ARRAY) {
|
||||
// Auto-construct, eg. [1, 2, 3] -> upb_Array([1, 2, 3]).
|
||||
upb_Array *arr = upb_Array_New(arena, type.type);
|
||||
HashTable *table = HASH_OF(val);
|
||||
HashPosition pos;
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(table, &pos);
|
||||
|
||||
while (true) {
|
||||
zval *zv = zend_hash_get_current_data_ex(table, &pos);
|
||||
upb_MessageValue val;
|
||||
|
||||
if (!zv) return arr;
|
||||
|
||||
if (!Convert_PhpToUpbAutoWrap(zv, &val, type, arena)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
upb_Array_Append(arr, val, arena);
|
||||
zend_hash_move_forward_ex(table, &pos);
|
||||
}
|
||||
} else if (Z_TYPE_P(val) == IS_OBJECT &&
|
||||
Z_OBJCE_P(val) == RepeatedField_class_entry) {
|
||||
// Unwrap existing RepeatedField object to get the upb_Array* inside.
|
||||
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(val);
|
||||
|
||||
if (!TypeInfo_Eq(intern->type, type)) {
|
||||
php_error_docref(NULL, E_USER_ERROR,
|
||||
"Wrong type for this repeated field.");
|
||||
}
|
||||
|
||||
upb_Arena_Fuse(arena, Arena_Get(&intern->arena));
|
||||
return intern->array;
|
||||
} else {
|
||||
php_error_docref(NULL, E_USER_ERROR, "Must be a repeated field");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool ArrayEq(const upb_Array *a1, const upb_Array *a2, TypeInfo type) {
|
||||
size_t i;
|
||||
size_t n;
|
||||
|
||||
if ((a1 == NULL) != (a2 == NULL)) return false;
|
||||
if (a1 == NULL) return true;
|
||||
|
||||
n = upb_Array_Size(a1);
|
||||
if (n != upb_Array_Size(a2)) return false;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
upb_MessageValue val1 = upb_Array_Get(a1, i);
|
||||
upb_MessageValue val2 = upb_Array_Get(a2, i);
|
||||
if (!ValueEq(val1, val2, type)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// RepeatedField PHP methods ///////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* RepeatedField::__construct()
|
||||
*
|
||||
* Constructs an instance of RepeatedField.
|
||||
* @param long Type of the stored element.
|
||||
* @param string Message/Enum class.
|
||||
*/
|
||||
PHP_METHOD(RepeatedField, __construct) {
|
||||
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
|
||||
upb_Arena *arena = Arena_Get(&intern->arena);
|
||||
zend_long type;
|
||||
zend_class_entry* klass = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|C", &type, &klass) != SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
intern->type.type = pbphp_dtype_to_type(type);
|
||||
intern->type.desc = Descriptor_GetFromClassEntry(klass);
|
||||
|
||||
if (intern->type.type == kUpb_CType_Message && klass == NULL) {
|
||||
php_error_docref(NULL, E_USER_ERROR,
|
||||
"Message/enum type must have concrete class.");
|
||||
return;
|
||||
}
|
||||
|
||||
intern->array = upb_Array_New(arena, intern->type.type);
|
||||
ObjCache_Add(intern->array, &intern->std);
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedField::append()
|
||||
*
|
||||
* Append element to the end of the repeated field.
|
||||
* @param object The element to be added.
|
||||
*/
|
||||
PHP_METHOD(RepeatedField, append) {
|
||||
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
|
||||
upb_Arena *arena = Arena_Get(&intern->arena);
|
||||
zval *php_val;
|
||||
upb_MessageValue msgval;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &php_val) != SUCCESS ||
|
||||
!Convert_PhpToUpb(php_val, &msgval, intern->type, arena)) {
|
||||
return;
|
||||
}
|
||||
|
||||
upb_Array_Append(intern->array, msgval, arena);
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedField::offsetExists(): bool
|
||||
*
|
||||
* Implements the ArrayAccess interface. Invoked when PHP code calls:
|
||||
*
|
||||
* isset($arr[$idx]);
|
||||
* empty($arr[$idx]);
|
||||
*
|
||||
* @param long The index to be checked.
|
||||
* @return bool True if the element at the given index exists.
|
||||
*/
|
||||
PHP_METHOD(RepeatedField, offsetExists) {
|
||||
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
|
||||
zend_long index;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_BOOL(index >= 0 && index < upb_Array_Size(intern->array));
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedField::offsetGet(): mixed
|
||||
*
|
||||
* Implements the ArrayAccess interface. Invoked when PHP code calls:
|
||||
*
|
||||
* $x = $arr[$idx];
|
||||
*
|
||||
* @param long The index of the element to be fetched.
|
||||
* @return object The stored element at given index.
|
||||
* @exception Invalid type for index.
|
||||
* @exception Non-existing index.
|
||||
*/
|
||||
PHP_METHOD(RepeatedField, offsetGet) {
|
||||
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
|
||||
zend_long index;
|
||||
upb_MessageValue msgval;
|
||||
zval ret;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < 0 || index >= upb_Array_Size(intern->array)) {
|
||||
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
|
||||
return;
|
||||
}
|
||||
|
||||
msgval = upb_Array_Get(intern->array, index);
|
||||
Convert_UpbToPhp(msgval, &ret, intern->type, &intern->arena);
|
||||
RETURN_COPY_VALUE(&ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedField::offsetSet(): void
|
||||
*
|
||||
* Implements the ArrayAccess interface. Invoked when PHP code calls:
|
||||
*
|
||||
* $arr[$idx] = $x;
|
||||
* $arr []= $x; // Append
|
||||
*
|
||||
* @param long The index of the element to be assigned.
|
||||
* @param object The element to be assigned.
|
||||
* @exception Invalid type for index.
|
||||
* @exception Non-existing index.
|
||||
* @exception Incorrect type of the element.
|
||||
*/
|
||||
PHP_METHOD(RepeatedField, offsetSet) {
|
||||
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
|
||||
upb_Arena *arena = Arena_Get(&intern->arena);
|
||||
size_t size = upb_Array_Size(intern->array);
|
||||
zval *offset, *val;
|
||||
int64_t index;
|
||||
upb_MessageValue msgval;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &offset, &val) != SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
index = size;
|
||||
} else if (!Convert_PhpToInt64(offset, &index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Convert_PhpToUpb(val, &msgval, intern->type, arena)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index > size) {
|
||||
zend_error(E_USER_ERROR, "Element at index %ld doesn't exist.\n", index);
|
||||
} else if (index == size) {
|
||||
upb_Array_Append(intern->array, msgval, Arena_Get(&intern->arena));
|
||||
} else {
|
||||
upb_Array_Set(intern->array, index, msgval);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedField::offsetUnset(): void
|
||||
*
|
||||
* Implements the ArrayAccess interface. Invoked when PHP code calls:
|
||||
*
|
||||
* unset($arr[$idx]);
|
||||
*
|
||||
* @param long The index of the element to be removed.
|
||||
* @exception Invalid type for index.
|
||||
* @exception The element to be removed is not at the end of the RepeatedField.
|
||||
*/
|
||||
PHP_METHOD(RepeatedField, offsetUnset) {
|
||||
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
|
||||
zend_long index;
|
||||
zend_long size = upb_Array_Size(intern->array);
|
||||
|
||||
// Only the element at the end of the array can be removed.
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) != SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (size == 0 || index != size - 1) {
|
||||
php_error_docref(NULL, E_USER_ERROR, "Cannot remove element at %ld.\n",
|
||||
index);
|
||||
return;
|
||||
}
|
||||
|
||||
upb_Array_Resize(intern->array, size - 1, Arena_Get(&intern->arena));
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedField::count(): int
|
||||
*
|
||||
* Implements the Countable interface. Invoked when PHP code calls:
|
||||
*
|
||||
* $len = count($arr);
|
||||
* Return the number of stored elements.
|
||||
* This will also be called for: count($arr)
|
||||
* @return long The number of stored elements.
|
||||
*/
|
||||
PHP_METHOD(RepeatedField, count) {
|
||||
RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis());
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_LONG(upb_Array_Size(intern->array));
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedField::getIterator(): Traversable
|
||||
*
|
||||
* Implements the IteratorAggregate interface. Invoked when PHP code calls:
|
||||
*
|
||||
* foreach ($arr) {}
|
||||
*
|
||||
* @return object Beginning iterator.
|
||||
*/
|
||||
PHP_METHOD(RepeatedField, getIterator) {
|
||||
zval ret;
|
||||
RepeatedFieldIter_make(&ret, getThis());
|
||||
RETURN_COPY_VALUE(&ret);
|
||||
}
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, type)
|
||||
ZEND_ARG_INFO(0, class)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, newval)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_offsetExists, 0, 0, _IS_BOOL, 0)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_offsetGet, 0, 0, IS_MIXED, 1)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_offsetSet, 0, 2, IS_VOID, 0)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_ARG_INFO(0, newval)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_offsetUnset, 0, 0, IS_VOID, 0)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_count, 0, 0, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_getIterator, 0, 0, Traversable, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static zend_function_entry repeated_field_methods[] = {
|
||||
PHP_ME(RepeatedField, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedField, append, arginfo_append, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedField, offsetExists, arginfo_offsetExists, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedField, offsetUnset, arginfo_offsetUnset, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedField, count, arginfo_count, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedField, getIterator, arginfo_getIterator, ZEND_ACC_PUBLIC)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// PHP RepeatedFieldIter
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
zend_object std;
|
||||
zval repeated_field;
|
||||
zend_long position;
|
||||
} RepeatedFieldIter;
|
||||
|
||||
zend_class_entry *RepeatedFieldIter_class_entry;
|
||||
static zend_object_handlers repeated_field_iter_object_handlers;
|
||||
|
||||
/**
|
||||
* RepeatedFieldIter_create()
|
||||
*
|
||||
* PHP class entry function to allocate and initialize a new RepeatedFieldIter
|
||||
* object.
|
||||
*/
|
||||
zend_object* RepeatedFieldIter_create(zend_class_entry *class_type) {
|
||||
RepeatedFieldIter *intern = emalloc(sizeof(RepeatedFieldIter));
|
||||
zend_object_std_init(&intern->std, class_type);
|
||||
intern->std.handlers = &repeated_field_iter_object_handlers;
|
||||
ZVAL_NULL(&intern->repeated_field);
|
||||
intern->position = 0;
|
||||
// Skip object_properties_init(), we don't allow derived classes.
|
||||
return &intern->std;
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedFieldIter_dtor()
|
||||
*
|
||||
* Object handler to destroy a RepeatedFieldIter. This releases all resources
|
||||
* associated with the message. Note that it is possible to access a destroyed
|
||||
* object from PHP in rare cases.
|
||||
*/
|
||||
static void RepeatedFieldIter_dtor(zend_object* obj) {
|
||||
RepeatedFieldIter* intern = (RepeatedFieldIter*)obj;
|
||||
zval_ptr_dtor(&intern->repeated_field);
|
||||
zend_object_std_dtor(&intern->std);
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedFieldIter_make()
|
||||
*
|
||||
* C function to create a RepeatedFieldIter.
|
||||
*/
|
||||
static void RepeatedFieldIter_make(zval *val, zval *repeated_field) {
|
||||
RepeatedFieldIter *iter;
|
||||
ZVAL_OBJ(val, RepeatedFieldIter_class_entry->create_object(
|
||||
RepeatedFieldIter_class_entry));
|
||||
iter = (RepeatedFieldIter*)Z_OBJ_P(val);
|
||||
ZVAL_COPY(&iter->repeated_field, repeated_field);
|
||||
}
|
||||
|
||||
/*
|
||||
* When a user writes:
|
||||
*
|
||||
* foreach($arr as $key => $val) {}
|
||||
*
|
||||
* PHP's iterator protocol is:
|
||||
*
|
||||
* $iter = $arr->getIterator();
|
||||
* for ($iter->rewind(); $iter->valid(); $iter->next()) {
|
||||
* $key = $iter->key();
|
||||
* $val = $iter->current();
|
||||
* }
|
||||
*/
|
||||
|
||||
/**
|
||||
* RepeatedFieldIter::rewind(): void
|
||||
*
|
||||
* Implements the Iterator interface. Sets the iterator to the first element.
|
||||
*/
|
||||
PHP_METHOD(RepeatedFieldIter, rewind) {
|
||||
RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
|
||||
intern->position = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedFieldIter::current(): mixed
|
||||
*
|
||||
* Implements the Iterator interface. Returns the current value.
|
||||
*/
|
||||
PHP_METHOD(RepeatedFieldIter, current) {
|
||||
RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
|
||||
RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field);
|
||||
upb_Array *array = field->array;
|
||||
zend_long index = intern->position;
|
||||
upb_MessageValue msgval;
|
||||
zval ret;
|
||||
|
||||
if (index < 0 || index >= upb_Array_Size(array)) {
|
||||
zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
|
||||
}
|
||||
|
||||
msgval = upb_Array_Get(array, index);
|
||||
|
||||
Convert_UpbToPhp(msgval, &ret, field->type, &field->arena);
|
||||
RETURN_COPY_VALUE(&ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedFieldIter::key(): mixed
|
||||
*
|
||||
* Implements the Iterator interface. Returns the current key.
|
||||
*/
|
||||
PHP_METHOD(RepeatedFieldIter, key) {
|
||||
RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
|
||||
RETURN_LONG(intern->position);
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedFieldIter::next(): void
|
||||
*
|
||||
* Implements the Iterator interface. Advances to the next element.
|
||||
*/
|
||||
PHP_METHOD(RepeatedFieldIter, next) {
|
||||
RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
|
||||
++intern->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* RepeatedFieldIter::valid(): bool
|
||||
*
|
||||
* Implements the Iterator interface. Returns true if this is a valid element.
|
||||
*/
|
||||
PHP_METHOD(RepeatedFieldIter, valid) {
|
||||
RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis());
|
||||
RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field);
|
||||
RETURN_BOOL(intern->position < upb_Array_Size(field->array));
|
||||
}
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_current, 0, 0, IS_MIXED, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_key, 0, 0, IS_MIXED, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_next, 0, 0, IS_VOID, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_valid, 0, 0, _IS_BOOL, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_rewind, 0, 0, IS_VOID, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static zend_function_entry repeated_field_iter_methods[] = {
|
||||
PHP_ME(RepeatedFieldIter, rewind, arginfo_rewind, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedFieldIter, current, arginfo_current, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedFieldIter, key, arginfo_key, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedFieldIter, next, arginfo_next, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(RepeatedFieldIter, valid, arginfo_valid, ZEND_ACC_PUBLIC)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Module init.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Array_ModuleInit()
|
||||
*
|
||||
* Called when the C extension is loaded to register all types.
|
||||
*/
|
||||
void Array_ModuleInit() {
|
||||
zend_class_entry tmp_ce;
|
||||
zend_object_handlers *h;
|
||||
|
||||
// RepeatedField.
|
||||
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedField",
|
||||
repeated_field_methods);
|
||||
|
||||
RepeatedField_class_entry = zend_register_internal_class(&tmp_ce);
|
||||
zend_class_implements(RepeatedField_class_entry, 3, zend_ce_arrayaccess,
|
||||
zend_ce_aggregate, zend_ce_countable);
|
||||
RepeatedField_class_entry->ce_flags |= ZEND_ACC_FINAL;
|
||||
RepeatedField_class_entry->create_object = RepeatedField_create;
|
||||
|
||||
h = &RepeatedField_object_handlers;
|
||||
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
|
||||
h->dtor_obj = RepeatedField_destructor;
|
||||
#if PHP_VERSION_ID < 80000
|
||||
h->compare_objects = RepeatedField_compare_objects;
|
||||
#else
|
||||
h->compare = RepeatedField_compare_objects;
|
||||
#endif
|
||||
h->clone_obj = RepeatedField_clone_obj;
|
||||
h->get_properties = RepeatedField_GetProperties;
|
||||
h->get_property_ptr_ptr = RepeatedField_GetPropertyPtrPtr;
|
||||
|
||||
// RepeatedFieldIter
|
||||
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedFieldIter",
|
||||
repeated_field_iter_methods);
|
||||
|
||||
RepeatedFieldIter_class_entry = zend_register_internal_class(&tmp_ce);
|
||||
zend_class_implements(RepeatedFieldIter_class_entry, 1, zend_ce_iterator);
|
||||
RepeatedFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
|
||||
RepeatedFieldIter_class_entry->create_object = RepeatedFieldIter_create;
|
||||
|
||||
h = &repeated_field_iter_object_handlers;
|
||||
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
|
||||
h->dtor_obj = RepeatedFieldIter_dtor;
|
||||
}
|
||||
67
libs/protobuf/php/ext/google/protobuf/array.h
Normal file
67
libs/protobuf/php/ext/google/protobuf/array.h
Normal file
@@ -0,0 +1,67 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef PHP_PROTOBUF_ARRAY_H_
|
||||
#define PHP_PROTOBUF_ARRAY_H_
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "def.h"
|
||||
#include "php-upb.h"
|
||||
|
||||
// Registers PHP classes for RepeatedField.
|
||||
void Array_ModuleInit();
|
||||
|
||||
// Gets a upb_Array* for the PHP object |val|:
|
||||
// * If |val| is a RepeatedField object, we first check its type and verify
|
||||
// that that the elements have the correct type for |type|. If so, we return
|
||||
// the wrapped upb_Array*. We also make sure that this array's arena is fused
|
||||
// to |arena|, so the returned upb_Array is guaranteed to live as long as
|
||||
// |arena|.
|
||||
// * If |val| is a PHP Array, we attempt to create a new upb_Array using
|
||||
// |arena| and add all of the PHP elements to it.
|
||||
//
|
||||
// If an error occurs, we raise a PHP error and return NULL.
|
||||
upb_Array *RepeatedField_GetUpbArray(zval *val, TypeInfo type,
|
||||
upb_Arena *arena);
|
||||
|
||||
// Creates a PHP RepeatedField object for the given upb_Array* and |type| and
|
||||
// returns it in |val|. The PHP object will keep a reference to this |arena| to
|
||||
// ensure the underlying array data stays alive.
|
||||
//
|
||||
// If |arr| is NULL, this will return a PHP null object.
|
||||
void RepeatedField_GetPhpWrapper(zval *val, upb_Array *arr, TypeInfo type,
|
||||
zval *arena);
|
||||
|
||||
// Returns true if the given arrays are equal. Both arrays must be of this
|
||||
// |type| and, if the type is |kUpb_CType_Message|, must have the same |m|.
|
||||
bool ArrayEq(const upb_Array *a1, const upb_Array *a2, TypeInfo type);
|
||||
|
||||
#endif // PHP_PROTOBUF_ARRAY_H_
|
||||
11
libs/protobuf/php/ext/google/protobuf/config.m4
Normal file
11
libs/protobuf/php/ext/google/protobuf/config.m4
Normal file
@@ -0,0 +1,11 @@
|
||||
PHP_ARG_ENABLE(protobuf, whether to enable Protobuf extension, [ --enable-protobuf Enable Protobuf extension])
|
||||
|
||||
if test "$PHP_PROTOBUF" != "no"; then
|
||||
|
||||
PHP_NEW_EXTENSION(
|
||||
protobuf,
|
||||
arena.c array.c convert.c def.c map.c message.c names.c php-upb.c protobuf.c third_party/utf8_range/naive.c third_party/utf8_range/range2-neon.c third_party/utf8_range/range2-sse.c,
|
||||
$ext_shared, , -std=gnu99)
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/third_party/utf8_range)
|
||||
|
||||
fi
|
||||
536
libs/protobuf/php/ext/google/protobuf/convert.c
Normal file
536
libs/protobuf/php/ext/google/protobuf/convert.c
Normal file
@@ -0,0 +1,536 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "convert.h"
|
||||
|
||||
#include <php.h>
|
||||
|
||||
// This is not self-contained: it must be after other Zend includes.
|
||||
#include <Zend/zend_exceptions.h>
|
||||
|
||||
#include "array.h"
|
||||
#include "map.h"
|
||||
#include "message.h"
|
||||
#include "php-upb.h"
|
||||
#include "protobuf.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// GPBUtil
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static zend_class_entry* GPBUtil_class_entry;
|
||||
|
||||
// The implementation of type checking for primitive fields is empty. This is
|
||||
// because type checking is done when direct assigning message fields (e.g.,
|
||||
// foo->a = 1). Functions defined here are place holders in generated code for
|
||||
// pure PHP implementation (c extension and pure PHP share the same generated
|
||||
// code).
|
||||
|
||||
PHP_METHOD(Util, checkInt32) {}
|
||||
PHP_METHOD(Util, checkUint32) {}
|
||||
PHP_METHOD(Util, checkInt64) {}
|
||||
PHP_METHOD(Util, checkUint64) {}
|
||||
PHP_METHOD(Util, checkEnum) {}
|
||||
PHP_METHOD(Util, checkFloat) {}
|
||||
PHP_METHOD(Util, checkDouble) {}
|
||||
PHP_METHOD(Util, checkBool) {}
|
||||
PHP_METHOD(Util, checkString) {}
|
||||
PHP_METHOD(Util, checkBytes) {}
|
||||
PHP_METHOD(Util, checkMessage) {}
|
||||
|
||||
// The result of checkMapField() is assigned, so we need to return the first
|
||||
// param:
|
||||
// $arr = GPBUtil::checkMapField($var,
|
||||
// \Google\Protobuf\Internal\GPBType::INT64,
|
||||
// \Google\Protobuf\Internal\GPBType::INT32);
|
||||
PHP_METHOD(Util, checkMapField) {
|
||||
zval *val, *key_type, *val_type, *klass;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|z", &val, &key_type,
|
||||
&val_type, &klass) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
RETURN_COPY(val);
|
||||
}
|
||||
|
||||
// The result of checkRepeatedField() is assigned, so we need to return the
|
||||
// first param:
|
||||
// $arr = GPBUtil::checkRepeatedField(
|
||||
// $var, \Google\Protobuf\Internal\GPBType::STRING);
|
||||
PHP_METHOD(Util, checkRepeatedField) {
|
||||
zval *val, *type, *klass;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|z", &val, &type, &klass) ==
|
||||
FAILURE) {
|
||||
return;
|
||||
}
|
||||
RETURN_COPY(val);
|
||||
}
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_checkPrimitive, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_checkString, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_ARG_INFO(0, check_utf8)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMessage, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_ARG_INFO(0, class)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMapField, 0, 0, 3)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_ARG_INFO(0, key_type)
|
||||
ZEND_ARG_INFO(0, value_type)
|
||||
ZEND_ARG_INFO(0, value_class)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_checkRepeatedField, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_ARG_INFO(0, type)
|
||||
ZEND_ARG_INFO(0, class)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static zend_function_entry util_methods[] = {
|
||||
PHP_ME(Util, checkInt32, arginfo_checkPrimitive,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkUint32, arginfo_checkPrimitive,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkInt64, arginfo_checkPrimitive,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkUint64, arginfo_checkPrimitive,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkEnum, arginfo_checkMessage,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkFloat, arginfo_checkPrimitive,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkDouble, arginfo_checkPrimitive,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkBool, arginfo_checkPrimitive,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkString, arginfo_checkString,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkBytes, arginfo_checkPrimitive,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkMessage, arginfo_checkMessage,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkMapField, arginfo_checkMapField,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME(Util, checkRepeatedField, arginfo_checkRepeatedField,
|
||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Conversion functions used from C
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
upb_CType pbphp_dtype_to_type(upb_FieldType type) {
|
||||
switch (type) {
|
||||
#define CASE(descriptor_type, type) \
|
||||
case kUpb_FieldType_##descriptor_type: \
|
||||
return kUpb_CType_##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, Int32);
|
||||
CASE(UInt64, UInt64);
|
||||
CASE(SInt32, Int32);
|
||||
CASE(SInt64, Int64);
|
||||
CASE(Fixed32, UInt32);
|
||||
CASE(Fixed64, UInt64);
|
||||
CASE(SFixed32, Int32);
|
||||
CASE(SFixed64, Int64);
|
||||
|
||||
#undef CASE
|
||||
|
||||
}
|
||||
|
||||
zend_error(E_ERROR, "Unknown field type.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool buftouint64(const char *ptr, const char *end, uint64_t *val) {
|
||||
uint64_t u64 = 0;
|
||||
while (ptr < end) {
|
||||
unsigned ch = (unsigned)(*ptr - '0');
|
||||
if (ch >= 10) break;
|
||||
if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) {
|
||||
return false;
|
||||
}
|
||||
u64 *= 10;
|
||||
u64 += ch;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (ptr != end) {
|
||||
// In PHP tradition, we allow truncation: "1.1" -> 1.
|
||||
// But we don't allow 'e', eg. '1.1e2' or any other non-numeric chars.
|
||||
if (*ptr++ != '.') return false;
|
||||
|
||||
for (;ptr < end; ptr++) {
|
||||
if (*ptr < '0' || *ptr > '9') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*val = u64;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool buftoint64(const char *ptr, const char *end, int64_t *val) {
|
||||
bool neg = false;
|
||||
uint64_t u64;
|
||||
|
||||
if (ptr != end && *ptr == '-') {
|
||||
ptr++;
|
||||
neg = true;
|
||||
}
|
||||
|
||||
if (!buftouint64(ptr, end, &u64) ||
|
||||
u64 > (uint64_t)INT64_MAX + neg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*val = neg ? -u64 : u64;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void throw_conversion_exception(const char *to, const zval *zv) {
|
||||
zval tmp;
|
||||
ZVAL_COPY(&tmp, zv);
|
||||
convert_to_string(&tmp);
|
||||
|
||||
zend_throw_exception_ex(NULL, 0, "Cannot convert '%s' to %s",
|
||||
Z_STRVAL_P(&tmp), to);
|
||||
|
||||
zval_ptr_dtor(&tmp);
|
||||
}
|
||||
|
||||
bool Convert_PhpToInt64(const zval *php_val, int64_t *i64) {
|
||||
switch (Z_TYPE_P(php_val)) {
|
||||
case IS_LONG:
|
||||
*i64 = Z_LVAL_P(php_val);
|
||||
return true;
|
||||
case IS_DOUBLE: {
|
||||
double dbl = Z_DVAL_P(php_val);
|
||||
if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) {
|
||||
zend_throw_exception_ex(NULL, 0, "Out of range");
|
||||
return false;
|
||||
}
|
||||
*i64 = dbl; /* must be guarded, overflow here is UB */
|
||||
return true;
|
||||
}
|
||||
case IS_STRING: {
|
||||
const char *buf = Z_STRVAL_P(php_val);
|
||||
// PHP would accept scientific notation here, but we're going to be a
|
||||
// little more discerning and only accept pure integers.
|
||||
bool ok = buftoint64(buf, buf + Z_STRLEN_P(php_val), i64);
|
||||
if (!ok) {
|
||||
throw_conversion_exception("integer", php_val);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
default:
|
||||
throw_conversion_exception("integer", php_val);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool to_double(zval *php_val, double *dbl) {
|
||||
switch (Z_TYPE_P(php_val)) {
|
||||
case IS_LONG:
|
||||
*dbl = Z_LVAL_P(php_val);
|
||||
return true;
|
||||
case IS_DOUBLE:
|
||||
*dbl = Z_DVAL_P(php_val);
|
||||
return true;
|
||||
case IS_STRING: {
|
||||
zend_long lval;
|
||||
switch (is_numeric_string(Z_STRVAL_P(php_val), Z_STRLEN_P(php_val), &lval,
|
||||
dbl, false)) {
|
||||
case IS_LONG:
|
||||
*dbl = lval;
|
||||
return true;
|
||||
case IS_DOUBLE:
|
||||
return true;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
default:
|
||||
fail:
|
||||
throw_conversion_exception("double", php_val);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool to_bool(zval* from, bool* to) {
|
||||
switch (Z_TYPE_P(from)) {
|
||||
case IS_TRUE:
|
||||
*to = true;
|
||||
return true;
|
||||
case IS_FALSE:
|
||||
*to = false;
|
||||
return true;
|
||||
case IS_LONG:
|
||||
*to = (Z_LVAL_P(from) != 0);
|
||||
return true;
|
||||
case IS_DOUBLE:
|
||||
*to = (Z_LVAL_P(from) != 0);
|
||||
return true;
|
||||
case IS_STRING:
|
||||
if (Z_STRLEN_P(from) == 0 ||
|
||||
(Z_STRLEN_P(from) == 1 && Z_STRVAL_P(from)[0] == '0')) {
|
||||
*to = false;
|
||||
} else {
|
||||
*to = true;
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
throw_conversion_exception("bool", from);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool to_string(zval* from) {
|
||||
if (Z_ISREF_P(from)) {
|
||||
ZVAL_DEREF(from);
|
||||
}
|
||||
|
||||
switch (Z_TYPE_P(from)) {
|
||||
case IS_STRING:
|
||||
return true;
|
||||
case IS_TRUE:
|
||||
case IS_FALSE:
|
||||
case IS_LONG:
|
||||
case IS_DOUBLE: {
|
||||
zval tmp;
|
||||
zend_make_printable_zval(from, &tmp);
|
||||
ZVAL_COPY_VALUE(from, &tmp);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
throw_conversion_exception("string", from);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Convert_PhpToUpb(zval *php_val, upb_MessageValue *upb_val, TypeInfo type,
|
||||
upb_Arena *arena) {
|
||||
int64_t i64;
|
||||
|
||||
if (Z_ISREF_P(php_val)) {
|
||||
ZVAL_DEREF(php_val);
|
||||
}
|
||||
|
||||
switch (type.type) {
|
||||
case kUpb_CType_Int64:
|
||||
return Convert_PhpToInt64(php_val, &upb_val->int64_val);
|
||||
case kUpb_CType_Int32:
|
||||
case kUpb_CType_Enum:
|
||||
if (!Convert_PhpToInt64(php_val, &i64)) {
|
||||
return false;
|
||||
}
|
||||
upb_val->int32_val = i64;
|
||||
return true;
|
||||
case kUpb_CType_UInt64:
|
||||
if (!Convert_PhpToInt64(php_val, &i64)) {
|
||||
return false;
|
||||
}
|
||||
upb_val->uint64_val = i64;
|
||||
return true;
|
||||
case kUpb_CType_UInt32:
|
||||
if (!Convert_PhpToInt64(php_val, &i64)) {
|
||||
return false;
|
||||
}
|
||||
upb_val->uint32_val = i64;
|
||||
return true;
|
||||
case kUpb_CType_Double:
|
||||
return to_double(php_val, &upb_val->double_val);
|
||||
case kUpb_CType_Float:
|
||||
if (!to_double(php_val, &upb_val->double_val)) return false;
|
||||
upb_val->float_val = upb_val->double_val;
|
||||
return true;
|
||||
case kUpb_CType_Bool:
|
||||
return to_bool(php_val, &upb_val->bool_val);
|
||||
case kUpb_CType_String:
|
||||
case kUpb_CType_Bytes: {
|
||||
char *ptr;
|
||||
size_t size;
|
||||
|
||||
if (!to_string(php_val)) return false;
|
||||
|
||||
size = Z_STRLEN_P(php_val);
|
||||
|
||||
// If arena is NULL we reference the input zval.
|
||||
// The resulting upb_StringView will only be value while the zval is alive.
|
||||
if (arena) {
|
||||
ptr = upb_Arena_Malloc(arena, size);
|
||||
memcpy(ptr, Z_STRVAL_P(php_val), size);
|
||||
} else {
|
||||
ptr = Z_STRVAL_P(php_val);
|
||||
}
|
||||
|
||||
upb_val->str_val = upb_StringView_FromDataAndSize(ptr, size);
|
||||
return true;
|
||||
}
|
||||
case kUpb_CType_Message:
|
||||
PBPHP_ASSERT(type.desc);
|
||||
return Message_GetUpbMessage(php_val, type.desc, arena,
|
||||
(upb_Message **)&upb_val->msg_val);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Convert_UpbToPhp(upb_MessageValue upb_val, zval *php_val, TypeInfo type,
|
||||
zval *arena) {
|
||||
switch (type.type) {
|
||||
case kUpb_CType_Int64:
|
||||
#if SIZEOF_ZEND_LONG == 8
|
||||
ZVAL_LONG(php_val, upb_val.int64_val);
|
||||
#else
|
||||
{
|
||||
char buf[20];
|
||||
int size = sprintf(buf, "%lld", upb_val.int64_val);
|
||||
ZVAL_NEW_STR(php_val, zend_string_init(buf, size, 0));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case kUpb_CType_UInt64:
|
||||
#if SIZEOF_ZEND_LONG == 8
|
||||
ZVAL_LONG(php_val, upb_val.uint64_val);
|
||||
#else
|
||||
{
|
||||
char buf[20];
|
||||
int size = sprintf(buf, "%lld", (int64_t)upb_val.uint64_val);
|
||||
ZVAL_NEW_STR(php_val, zend_string_init(buf, size, 0));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case kUpb_CType_Int32:
|
||||
case kUpb_CType_Enum:
|
||||
ZVAL_LONG(php_val, upb_val.int32_val);
|
||||
break;
|
||||
case kUpb_CType_UInt32: {
|
||||
// Sign-extend for consistency between 32/64-bit builds.
|
||||
zend_long val = (int32_t)upb_val.uint32_val;
|
||||
ZVAL_LONG(php_val, val);
|
||||
break;
|
||||
}
|
||||
case kUpb_CType_Double:
|
||||
ZVAL_DOUBLE(php_val, upb_val.double_val);
|
||||
break;
|
||||
case kUpb_CType_Float:
|
||||
ZVAL_DOUBLE(php_val, upb_val.float_val);
|
||||
break;
|
||||
case kUpb_CType_Bool:
|
||||
ZVAL_BOOL(php_val, upb_val.bool_val);
|
||||
break;
|
||||
case kUpb_CType_String:
|
||||
case kUpb_CType_Bytes: {
|
||||
upb_StringView str = upb_val.str_val;
|
||||
ZVAL_NEW_STR(php_val, zend_string_init(str.data, str.size, 0));
|
||||
break;
|
||||
}
|
||||
case kUpb_CType_Message:
|
||||
PBPHP_ASSERT(type.desc);
|
||||
Message_GetPhpWrapper(php_val, type.desc, (upb_Message *)upb_val.msg_val,
|
||||
arena);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the field is a well known wrapper type
|
||||
static bool IsWrapper(const upb_MessageDef* m) {
|
||||
if (!m) return false;
|
||||
switch (upb_MessageDef_WellKnownType(m)) {
|
||||
case kUpb_WellKnown_DoubleValue:
|
||||
case kUpb_WellKnown_FloatValue:
|
||||
case kUpb_WellKnown_Int64Value:
|
||||
case kUpb_WellKnown_UInt64Value:
|
||||
case kUpb_WellKnown_Int32Value:
|
||||
case kUpb_WellKnown_UInt32Value:
|
||||
case kUpb_WellKnown_StringValue:
|
||||
case kUpb_WellKnown_BytesValue:
|
||||
case kUpb_WellKnown_BoolValue:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Convert_PhpToUpbAutoWrap(zval *val, upb_MessageValue *upb_val, TypeInfo type,
|
||||
upb_Arena *arena) {
|
||||
const upb_MessageDef *subm = type.desc ? type.desc->msgdef : NULL;
|
||||
if (subm && IsWrapper(subm) && Z_TYPE_P(val) != IS_OBJECT) {
|
||||
// Assigning a scalar to a wrapper-typed value. We will automatically wrap
|
||||
// the value, so the user doesn't need to create a FooWrapper(['value': X])
|
||||
// message manually.
|
||||
upb_Message *wrapper = upb_Message_New(subm, arena);
|
||||
const upb_FieldDef *val_f = upb_MessageDef_FindFieldByNumber(subm, 1);
|
||||
upb_MessageValue msgval;
|
||||
if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(val_f), arena)) return false;
|
||||
upb_Message_Set(wrapper, val_f, msgval, arena);
|
||||
upb_val->msg_val = wrapper;
|
||||
return true;
|
||||
} else {
|
||||
// Convert_PhpToUpb doesn't auto-construct messages. This means that we only
|
||||
// allow:
|
||||
// ['foo_submsg': new Foo(['a' => 1])]
|
||||
// not:
|
||||
// ['foo_submsg': ['a' => 1]]
|
||||
return Convert_PhpToUpb(val, upb_val, type, arena);
|
||||
}
|
||||
}
|
||||
|
||||
void Convert_ModuleInit(void) {
|
||||
const char *prefix_name = "TYPE_URL_PREFIX";
|
||||
zend_class_entry class_type;
|
||||
|
||||
INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBUtil",
|
||||
util_methods);
|
||||
GPBUtil_class_entry = zend_register_internal_class(&class_type);
|
||||
|
||||
zend_declare_class_constant_string(GPBUtil_class_entry, prefix_name,
|
||||
strlen(prefix_name),
|
||||
"type.googleapis.com/");
|
||||
}
|
||||
73
libs/protobuf/php/ext/google/protobuf/convert.h
Normal file
73
libs/protobuf/php/ext/google/protobuf/convert.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef PHP_PROTOBUF_CONVERT_H_
|
||||
#define PHP_PROTOBUF_CONVERT_H_
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "php-upb.h"
|
||||
#include "def.h"
|
||||
|
||||
upb_CType pbphp_dtype_to_type(upb_FieldType type);
|
||||
|
||||
// Converts |php_val| to an int64_t. Returns false if the value cannot be
|
||||
// converted.
|
||||
bool Convert_PhpToInt64(const zval *php_val, int64_t *i64);
|
||||
|
||||
// Converts |php_val| to a upb_MessageValue according to |type|. If type is
|
||||
// kUpb_CType_Message, then |desc| must be the Descriptor for this message type.
|
||||
// If type is string, message, or bytes, then |arena| will be used to copy
|
||||
// string data or fuse this arena to the given message's arena.
|
||||
bool Convert_PhpToUpb(zval *php_val, upb_MessageValue *upb_val, TypeInfo type,
|
||||
upb_Arena *arena);
|
||||
|
||||
// Similar to Convert_PhpToUpb, but supports automatically wrapping the wrapper
|
||||
// types if a primitive is specified:
|
||||
//
|
||||
// 5 -> Int64Wrapper(value=5)
|
||||
//
|
||||
// We currently allow this implicit conversion in initializers, but not for
|
||||
// assignment.
|
||||
bool Convert_PhpToUpbAutoWrap(zval *val, upb_MessageValue *upb_val, TypeInfo type,
|
||||
upb_Arena *arena);
|
||||
|
||||
// Converts |upb_val| to a PHP zval according to |type|. This may involve
|
||||
// creating a PHP wrapper object. Any newly created wrapper object
|
||||
// will reference |arena|.
|
||||
//
|
||||
// The caller owns a reference to the returned value.
|
||||
void Convert_UpbToPhp(upb_MessageValue upb_val, zval *php_val, TypeInfo type,
|
||||
zval *arena);
|
||||
|
||||
// Registers the GPBUtil class.
|
||||
void Convert_ModuleInit(void);
|
||||
|
||||
#endif // PHP_PROTOBUF_CONVERT_H_
|
||||
1168
libs/protobuf/php/ext/google/protobuf/def.c
Normal file
1168
libs/protobuf/php/ext/google/protobuf/def.c
Normal file
File diff suppressed because it is too large
Load Diff
90
libs/protobuf/php/ext/google/protobuf/def.h
Normal file
90
libs/protobuf/php/ext/google/protobuf/def.h
Normal file
@@ -0,0 +1,90 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef PHP_PROTOBUF_DEF_H_
|
||||
#define PHP_PROTOBUF_DEF_H_
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "php-upb.h"
|
||||
|
||||
// Initializes the Def module, which defines all of the descriptor classes.
|
||||
void Def_ModuleInit();
|
||||
|
||||
// Creates a new DescriptorPool to wrap the given symtab, which must not be
|
||||
// NULL.
|
||||
void DescriptorPool_CreateWithSymbolTable(zval *zv, upb_DefPool *symtab);
|
||||
|
||||
upb_DefPool *DescriptorPool_GetSymbolTable();
|
||||
|
||||
// Returns true if the global descriptor pool already has the given filename.
|
||||
bool DescriptorPool_HasFile(const char *filename);
|
||||
|
||||
// Adds the given descriptor with the given filename to the global pool.
|
||||
void DescriptorPool_AddDescriptor(const char *filename, const char *data, int size);
|
||||
|
||||
typedef struct Descriptor {
|
||||
zend_object std;
|
||||
const upb_MessageDef *msgdef;
|
||||
zend_class_entry *class_entry;
|
||||
} Descriptor;
|
||||
|
||||
// Gets or creates a Descriptor* for the given class entry, upb_MessageDef, or
|
||||
// upb_FieldDef. The returned Descriptor* will live for the entire request,
|
||||
// so no ref is necessary to keep it alive. The caller does *not* own a ref
|
||||
// on the returned object.
|
||||
Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce);
|
||||
Descriptor* Descriptor_GetFromMessageDef(const upb_MessageDef *m);
|
||||
Descriptor* Descriptor_GetFromFieldDef(const upb_FieldDef *f);
|
||||
|
||||
// Packages up a upb_CType with a Descriptor, since many functions need
|
||||
// both.
|
||||
typedef struct {
|
||||
upb_CType type;
|
||||
const Descriptor *desc; // When type == kUpb_CType_Message.
|
||||
} TypeInfo;
|
||||
|
||||
static inline TypeInfo TypeInfo_Get(const upb_FieldDef *f) {
|
||||
TypeInfo ret = {upb_FieldDef_CType(f), Descriptor_GetFromFieldDef(f)};
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline TypeInfo TypeInfo_FromType(upb_CType type) {
|
||||
TypeInfo ret = {type};
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool TypeInfo_Eq(TypeInfo a, TypeInfo b) {
|
||||
if (a.type != b.type) return false;
|
||||
if (a.type == kUpb_CType_Message && a.desc != b.desc) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // PHP_PROTOBUF_DEF_H_
|
||||
698
libs/protobuf/php/ext/google/protobuf/map.c
Normal file
698
libs/protobuf/php/ext/google/protobuf/map.c
Normal file
@@ -0,0 +1,698 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "map.h"
|
||||
|
||||
#include <Zend/zend_API.h>
|
||||
#include <Zend/zend_interfaces.h>
|
||||
|
||||
#include <ext/spl/spl_iterators.h>
|
||||
|
||||
#include "arena.h"
|
||||
#include "convert.h"
|
||||
#include "message.h"
|
||||
#include "php-upb.h"
|
||||
#include "protobuf.h"
|
||||
|
||||
static void MapFieldIter_make(zval *val, zval *map_field);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// MapField
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
zend_object std;
|
||||
zval arena;
|
||||
upb_Map *map;
|
||||
MapField_Type type;
|
||||
} MapField;
|
||||
|
||||
zend_class_entry *MapField_class_entry;
|
||||
static zend_object_handlers MapField_object_handlers;
|
||||
|
||||
static bool MapType_Eq(MapField_Type a, MapField_Type b) {
|
||||
return a.key_type == b.key_type && TypeInfo_Eq(a.val_type, b.val_type);
|
||||
}
|
||||
|
||||
static TypeInfo KeyType(MapField_Type type) {
|
||||
TypeInfo ret = {type.key_type};
|
||||
return ret;
|
||||
}
|
||||
|
||||
MapField_Type MapType_Get(const upb_FieldDef *f) {
|
||||
const upb_MessageDef *ent = upb_FieldDef_MessageSubDef(f);
|
||||
const upb_FieldDef *key_f = upb_MessageDef_FindFieldByNumber(ent, 1);
|
||||
const upb_FieldDef *val_f = upb_MessageDef_FindFieldByNumber(ent, 2);
|
||||
MapField_Type type = {
|
||||
upb_FieldDef_CType(key_f),
|
||||
{upb_FieldDef_CType(val_f), Descriptor_GetFromFieldDef(val_f)}};
|
||||
return type;
|
||||
}
|
||||
|
||||
// PHP Object Handlers /////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* MapField_create()
|
||||
*
|
||||
* PHP class entry function to allocate and initialize a new MapField
|
||||
* object.
|
||||
*/
|
||||
static zend_object* MapField_create(zend_class_entry *class_type) {
|
||||
MapField *intern = emalloc(sizeof(MapField));
|
||||
zend_object_std_init(&intern->std, class_type);
|
||||
intern->std.handlers = &MapField_object_handlers;
|
||||
Arena_Init(&intern->arena);
|
||||
intern->map = NULL;
|
||||
// Skip object_properties_init(), we don't allow derived classes.
|
||||
return &intern->std;
|
||||
}
|
||||
|
||||
/**
|
||||
* MapField_dtor()
|
||||
*
|
||||
* Object handler to destroy a MapField. This releases all resources
|
||||
* associated with the message. Note that it is possible to access a destroyed
|
||||
* object from PHP in rare cases.
|
||||
*/
|
||||
static void MapField_destructor(zend_object* obj) {
|
||||
MapField* intern = (MapField*)obj;
|
||||
ObjCache_Delete(intern->map);
|
||||
zval_ptr_dtor(&intern->arena);
|
||||
zend_object_std_dtor(&intern->std);
|
||||
}
|
||||
|
||||
/**
|
||||
* MapField_compare_objects()
|
||||
*
|
||||
* Object handler for comparing two repeated field objects. Called whenever PHP
|
||||
* code does:
|
||||
*
|
||||
* $map1 == $map2
|
||||
*/
|
||||
static int MapField_compare_objects(zval *map1, zval *map2) {
|
||||
MapField* intern1 = (MapField*)Z_OBJ_P(map1);
|
||||
MapField* intern2 = (MapField*)Z_OBJ_P(map2);
|
||||
|
||||
return MapType_Eq(intern1->type, intern2->type) &&
|
||||
MapEq(intern1->map, intern2->map, intern1->type)
|
||||
? 0
|
||||
: 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* MapField_clone_obj()
|
||||
*
|
||||
* Object handler for cloning an object in PHP. Called when PHP code does:
|
||||
*
|
||||
* $map2 = clone $map1;
|
||||
*/
|
||||
static zend_object *MapField_clone_obj(PROTO_VAL *object) {
|
||||
MapField* intern = PROTO_VAL_P(object);
|
||||
upb_Arena *arena = Arena_Get(&intern->arena);
|
||||
upb_Map *clone =
|
||||
upb_Map_New(arena, intern->type.key_type, intern->type.val_type.type);
|
||||
size_t iter = kUpb_Map_Begin;
|
||||
|
||||
while (upb_MapIterator_Next(intern->map, &iter)) {
|
||||
upb_MessageValue key = upb_MapIterator_Key(intern->map, iter);
|
||||
upb_MessageValue val = upb_MapIterator_Value(intern->map, iter);
|
||||
upb_Map_Set(clone, key, val, arena);
|
||||
}
|
||||
|
||||
zval ret;
|
||||
MapField_GetPhpWrapper(&ret, clone, intern->type, &intern->arena);
|
||||
return Z_OBJ_P(&ret);
|
||||
}
|
||||
|
||||
static zval *Map_GetPropertyPtrPtr(PROTO_VAL *object, PROTO_STR *member,
|
||||
int type, void **cache_slot) {
|
||||
return NULL; // We don't offer direct references to our properties.
|
||||
}
|
||||
|
||||
static HashTable *Map_GetProperties(PROTO_VAL *object) {
|
||||
return NULL; // We do not have a properties table.
|
||||
}
|
||||
|
||||
// C Functions from map.h //////////////////////////////////////////////////////
|
||||
|
||||
// These are documented in the header file.
|
||||
|
||||
void MapField_GetPhpWrapper(zval *val, upb_Map *map, MapField_Type type,
|
||||
zval *arena) {
|
||||
if (!map) {
|
||||
ZVAL_NULL(val);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ObjCache_Get(map, val)) {
|
||||
MapField *intern = emalloc(sizeof(MapField));
|
||||
zend_object_std_init(&intern->std, MapField_class_entry);
|
||||
intern->std.handlers = &MapField_object_handlers;
|
||||
ZVAL_COPY(&intern->arena, arena);
|
||||
intern->map = map;
|
||||
intern->type = type;
|
||||
// Skip object_properties_init(), we don't allow derived classes.
|
||||
ObjCache_Add(intern->map, &intern->std);
|
||||
ZVAL_OBJ(val, &intern->std);
|
||||
}
|
||||
}
|
||||
|
||||
upb_Map *MapField_GetUpbMap(zval *val, MapField_Type type, upb_Arena *arena) {
|
||||
if (Z_ISREF_P(val)) {
|
||||
ZVAL_DEREF(val);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(val) == IS_ARRAY) {
|
||||
upb_Map *map = upb_Map_New(arena, type.key_type, type.val_type.type);
|
||||
HashTable *table = HASH_OF(val);
|
||||
HashPosition pos;
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(table, &pos);
|
||||
|
||||
while (true) {
|
||||
zval php_key;
|
||||
zval *php_val;
|
||||
upb_MessageValue upb_key;
|
||||
upb_MessageValue upb_val;
|
||||
|
||||
zend_hash_get_current_key_zval_ex(table, &php_key, &pos);
|
||||
php_val = zend_hash_get_current_data_ex(table, &pos);
|
||||
|
||||
if (!php_val) return map;
|
||||
|
||||
if (!Convert_PhpToUpb(&php_key, &upb_key, KeyType(type), arena) ||
|
||||
!Convert_PhpToUpbAutoWrap(php_val, &upb_val, type.val_type, arena)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
upb_Map_Set(map, upb_key, upb_val, arena);
|
||||
zend_hash_move_forward_ex(table, &pos);
|
||||
zval_dtor(&php_key);
|
||||
}
|
||||
} else if (Z_TYPE_P(val) == IS_OBJECT &&
|
||||
Z_OBJCE_P(val) == MapField_class_entry) {
|
||||
MapField *intern = (MapField*)Z_OBJ_P(val);
|
||||
|
||||
if (!MapType_Eq(intern->type, type)) {
|
||||
php_error_docref(NULL, E_USER_ERROR, "Wrong type for this map field.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
upb_Arena_Fuse(arena, Arena_Get(&intern->arena));
|
||||
return intern->map;
|
||||
} else {
|
||||
php_error_docref(NULL, E_USER_ERROR, "Must be a map");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool MapEq(const upb_Map *m1, const upb_Map *m2, MapField_Type type) {
|
||||
size_t iter = kUpb_Map_Begin;
|
||||
|
||||
if ((m1 == NULL) != (m2 == NULL)) return false;
|
||||
if (m1 == NULL) return true;
|
||||
if (upb_Map_Size(m1) != upb_Map_Size(m2)) return false;
|
||||
|
||||
while (upb_MapIterator_Next(m1, &iter)) {
|
||||
upb_MessageValue key = upb_MapIterator_Key(m1, iter);
|
||||
upb_MessageValue val1 = upb_MapIterator_Value(m1, iter);
|
||||
upb_MessageValue val2;
|
||||
|
||||
if (!upb_Map_Get(m2, key, &val2)) return false;
|
||||
if (!ValueEq(val1, val2, type.val_type)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// MapField PHP methods ////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* MapField::__construct()
|
||||
*
|
||||
* Constructs an instance of MapField.
|
||||
* @param long Key type.
|
||||
* @param long Value type.
|
||||
* @param string Message/Enum class (message/enum value types only).
|
||||
*/
|
||||
PHP_METHOD(MapField, __construct) {
|
||||
MapField *intern = (MapField*)Z_OBJ_P(getThis());
|
||||
upb_Arena *arena = Arena_Get(&intern->arena);
|
||||
zend_long key_type, val_type;
|
||||
zend_class_entry* klass = NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|C", &key_type, &val_type,
|
||||
&klass) != SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
intern->type.key_type = pbphp_dtype_to_type(key_type);
|
||||
intern->type.val_type.type = pbphp_dtype_to_type(val_type);
|
||||
intern->type.val_type.desc = Descriptor_GetFromClassEntry(klass);
|
||||
|
||||
// Check that the key type is an allowed type.
|
||||
switch (intern->type.key_type) {
|
||||
case kUpb_CType_Int32:
|
||||
case kUpb_CType_Int64:
|
||||
case kUpb_CType_UInt32:
|
||||
case kUpb_CType_UInt64:
|
||||
case kUpb_CType_Bool:
|
||||
case kUpb_CType_String:
|
||||
case kUpb_CType_Bytes:
|
||||
// These are OK.
|
||||
break;
|
||||
default:
|
||||
zend_error(E_USER_ERROR, "Invalid key type for map.");
|
||||
}
|
||||
|
||||
if (intern->type.val_type.type == kUpb_CType_Message && klass == NULL) {
|
||||
php_error_docref(NULL, E_USER_ERROR,
|
||||
"Message/enum type must have concrete class.");
|
||||
return;
|
||||
}
|
||||
|
||||
intern->map =
|
||||
upb_Map_New(arena, intern->type.key_type, intern->type.val_type.type);
|
||||
ObjCache_Add(intern->map, &intern->std);
|
||||
}
|
||||
|
||||
/**
|
||||
* MapField::offsetExists(): bool
|
||||
*
|
||||
* Implements the ArrayAccess interface. Invoked when PHP code calls:
|
||||
*
|
||||
* isset($map[$idx]);
|
||||
* empty($map[$idx]);
|
||||
*
|
||||
* @param long The index to be checked.
|
||||
* @return bool True if the element at the given index exists.
|
||||
*/
|
||||
PHP_METHOD(MapField, offsetExists) {
|
||||
MapField *intern = (MapField*)Z_OBJ_P(getThis());
|
||||
zval *key;
|
||||
upb_MessageValue upb_key;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
|
||||
!Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_BOOL(upb_Map_Get(intern->map, upb_key, NULL));
|
||||
}
|
||||
|
||||
/**
|
||||
* MapField::offsetGet(): mixed
|
||||
*
|
||||
* Implements the ArrayAccess interface. Invoked when PHP code calls:
|
||||
*
|
||||
* $x = $map[$idx];
|
||||
*
|
||||
* @param long The index of the element to be fetched.
|
||||
* @return object The stored element at given index.
|
||||
* @exception Invalid type for index.
|
||||
* @exception Non-existing index.
|
||||
*/
|
||||
PHP_METHOD(MapField, offsetGet) {
|
||||
MapField *intern = (MapField*)Z_OBJ_P(getThis());
|
||||
zval *key;
|
||||
zval ret;
|
||||
upb_MessageValue upb_key, upb_val;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
|
||||
!Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!upb_Map_Get(intern->map, upb_key, &upb_val)) {
|
||||
zend_error(E_USER_ERROR, "Given key doesn't exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
Convert_UpbToPhp(upb_val, &ret, intern->type.val_type, &intern->arena);
|
||||
RETURN_COPY_VALUE(&ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* MapField::offsetSet(): void
|
||||
*
|
||||
* Implements the ArrayAccess interface. Invoked when PHP code calls:
|
||||
*
|
||||
* $map[$idx] = $x;
|
||||
*
|
||||
* @param long The index of the element to be assigned.
|
||||
* @param object The element to be assigned.
|
||||
* @exception Invalid type for index.
|
||||
* @exception Non-existing index.
|
||||
* @exception Incorrect type of the element.
|
||||
*/
|
||||
PHP_METHOD(MapField, offsetSet) {
|
||||
MapField *intern = (MapField*)Z_OBJ_P(getThis());
|
||||
upb_Arena *arena = Arena_Get(&intern->arena);
|
||||
zval *key, *val;
|
||||
upb_MessageValue upb_key, upb_val;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &key, &val) != SUCCESS ||
|
||||
!Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL) ||
|
||||
!Convert_PhpToUpb(val, &upb_val, intern->type.val_type, arena)) {
|
||||
return;
|
||||
}
|
||||
|
||||
upb_Map_Set(intern->map, upb_key, upb_val, arena);
|
||||
}
|
||||
|
||||
/**
|
||||
* MapField::offsetUnset(): void
|
||||
*
|
||||
* Implements the ArrayAccess interface. Invoked when PHP code calls:
|
||||
*
|
||||
* unset($map[$idx]);
|
||||
*
|
||||
* @param long The index of the element to be removed.
|
||||
* @exception Invalid type for index.
|
||||
* @exception The element to be removed is not at the end of the MapField.
|
||||
*/
|
||||
PHP_METHOD(MapField, offsetUnset) {
|
||||
MapField *intern = (MapField*)Z_OBJ_P(getThis());
|
||||
zval *key;
|
||||
upb_MessageValue upb_key;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS ||
|
||||
!Convert_PhpToUpb(key, &upb_key, KeyType(intern->type), NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
upb_Map_Delete(intern->map, upb_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* MapField::count(): int
|
||||
*
|
||||
* Implements the Countable interface. Invoked when PHP code calls:
|
||||
*
|
||||
* $len = count($map);
|
||||
* Return the number of stored elements.
|
||||
* This will also be called for: count($map)
|
||||
* @return long The number of stored elements.
|
||||
*/
|
||||
PHP_METHOD(MapField, count) {
|
||||
MapField *intern = (MapField*)Z_OBJ_P(getThis());
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_LONG(upb_Map_Size(intern->map));
|
||||
}
|
||||
|
||||
/**
|
||||
* MapField::getIterator(): Traversable
|
||||
*
|
||||
* Implements the IteratorAggregate interface. Invoked when PHP code calls:
|
||||
*
|
||||
* foreach ($arr) {}
|
||||
*
|
||||
* @return object Beginning iterator.
|
||||
*/
|
||||
PHP_METHOD(MapField, getIterator) {
|
||||
zval ret;
|
||||
MapFieldIter_make(&ret, getThis());
|
||||
RETURN_COPY_VALUE(&ret);
|
||||
}
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, key_type)
|
||||
ZEND_ARG_INFO(0, value_type)
|
||||
ZEND_ARG_INFO(0, value_class)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_offsetGet, 0, 0, IS_MIXED, 1)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_offsetSet, 0, 2, IS_VOID, 0)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_ARG_INFO(0, newval)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_offsetUnset, 0, 0, IS_VOID, 0)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_offsetExists, 0, 0, _IS_BOOL, 0)
|
||||
ZEND_ARG_INFO(0, index)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_getIterator, 0, 0, Traversable, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_count, 0, 0, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static zend_function_entry MapField_methods[] = {
|
||||
PHP_ME(MapField, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MapField, offsetExists, arginfo_offsetExists, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MapField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MapField, offsetUnset, arginfo_offsetUnset, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MapField, count, arginfo_count, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MapField, getIterator, arginfo_getIterator, ZEND_ACC_PUBLIC)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// MapFieldIter
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
zend_object std;
|
||||
zval map_field;
|
||||
size_t position;
|
||||
} MapFieldIter;
|
||||
|
||||
zend_class_entry *MapFieldIter_class_entry;
|
||||
static zend_object_handlers MapFieldIter_object_handlers;
|
||||
|
||||
/**
|
||||
* MapFieldIter_create()
|
||||
*
|
||||
* PHP class entry function to allocate and initialize a new MapFieldIter
|
||||
* object.
|
||||
*/
|
||||
zend_object* MapFieldIter_create(zend_class_entry *class_type) {
|
||||
MapFieldIter *intern = emalloc(sizeof(MapFieldIter));
|
||||
zend_object_std_init(&intern->std, class_type);
|
||||
intern->std.handlers = &MapFieldIter_object_handlers;
|
||||
ZVAL_NULL(&intern->map_field);
|
||||
intern->position = 0;
|
||||
// Skip object_properties_init(), we don't allow derived classes.
|
||||
return &intern->std;
|
||||
}
|
||||
|
||||
/**
|
||||
* MapFieldIter_dtor()
|
||||
*
|
||||
* Object handler to destroy a MapFieldIter. This releases all resources
|
||||
* associated with the message. Note that it is possible to access a destroyed
|
||||
* object from PHP in rare cases.
|
||||
*/
|
||||
static void map_field_iter_dtor(zend_object* obj) {
|
||||
MapFieldIter* intern = (MapFieldIter*)obj;
|
||||
zval_ptr_dtor(&intern->map_field);
|
||||
zend_object_std_dtor(&intern->std);
|
||||
}
|
||||
|
||||
/**
|
||||
* MapFieldIter_make()
|
||||
*
|
||||
* Function to create a MapFieldIter directly from C.
|
||||
*/
|
||||
static void MapFieldIter_make(zval *val, zval *map_field) {
|
||||
MapFieldIter *iter;
|
||||
ZVAL_OBJ(val,
|
||||
MapFieldIter_class_entry->create_object(MapFieldIter_class_entry));
|
||||
iter = (MapFieldIter*)Z_OBJ_P(val);
|
||||
ZVAL_COPY(&iter->map_field, map_field);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// PHP MapFieldIter Methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* When a user writes:
|
||||
*
|
||||
* foreach($arr as $key => $val) {}
|
||||
*
|
||||
* PHP translates this into:
|
||||
*
|
||||
* $iter = $arr->getIterator();
|
||||
* for ($iter->rewind(); $iter->valid(); $iter->next()) {
|
||||
* $key = $iter->key();
|
||||
* $val = $iter->current();
|
||||
* }
|
||||
*/
|
||||
|
||||
/**
|
||||
* MapFieldIter::rewind(): void
|
||||
*
|
||||
* Implements the Iterator interface. Sets the iterator to the first element.
|
||||
*/
|
||||
PHP_METHOD(MapFieldIter, rewind) {
|
||||
MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
|
||||
MapField *map_field = (MapField*)Z_OBJ_P(&intern->map_field);
|
||||
intern->position = kUpb_Map_Begin;
|
||||
upb_MapIterator_Next(map_field->map, &intern->position);
|
||||
}
|
||||
|
||||
/**
|
||||
* MapFieldIter::current(): mixed
|
||||
*
|
||||
* Implements the Iterator interface. Returns the current value.
|
||||
*/
|
||||
PHP_METHOD(MapFieldIter, current) {
|
||||
MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
|
||||
MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
|
||||
upb_MessageValue upb_val = upb_MapIterator_Value(field->map, intern->position);
|
||||
zval ret;
|
||||
Convert_UpbToPhp(upb_val, &ret, field->type.val_type, &field->arena);
|
||||
RETURN_COPY_VALUE(&ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* MapFieldIter::key()
|
||||
*
|
||||
* Implements the Iterator interface. Returns the current key.
|
||||
*/
|
||||
PHP_METHOD(MapFieldIter, key) {
|
||||
MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
|
||||
MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
|
||||
upb_MessageValue upb_key = upb_MapIterator_Key(field->map, intern->position);
|
||||
zval ret;
|
||||
Convert_UpbToPhp(upb_key, &ret, KeyType(field->type), NULL);
|
||||
RETURN_COPY_VALUE(&ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* MapFieldIter::next(): void
|
||||
*
|
||||
* Implements the Iterator interface. Advances to the next element.
|
||||
*/
|
||||
PHP_METHOD(MapFieldIter, next) {
|
||||
MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
|
||||
MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
|
||||
upb_MapIterator_Next(field->map, &intern->position);
|
||||
}
|
||||
|
||||
/**
|
||||
* MapFieldIter::valid(): bool
|
||||
*
|
||||
* Implements the Iterator interface. Returns true if this is a valid element.
|
||||
*/
|
||||
PHP_METHOD(MapFieldIter, valid) {
|
||||
MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis());
|
||||
MapField *field = (MapField*)Z_OBJ_P(&intern->map_field);
|
||||
bool done = upb_MapIterator_Done(field->map, intern->position);
|
||||
RETURN_BOOL(!done);
|
||||
}
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_rewind, 0, 0, IS_VOID, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_current, 0, 0, IS_MIXED, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_key, 0, 0, IS_MIXED, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_next, 0, 0, IS_VOID, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_valid, 0, 0, _IS_BOOL, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
static zend_function_entry map_field_iter_methods[] = {
|
||||
PHP_ME(MapFieldIter, rewind, arginfo_rewind, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MapFieldIter, current, arginfo_current, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MapFieldIter, key, arginfo_key, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MapFieldIter, next, arginfo_next, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(MapFieldIter, valid, arginfo_valid, ZEND_ACC_PUBLIC)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Module init.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Map_ModuleInit()
|
||||
*
|
||||
* Called when the C extension is loaded to register all types.
|
||||
*/
|
||||
|
||||
void Map_ModuleInit() {
|
||||
zend_class_entry tmp_ce;
|
||||
zend_object_handlers *h;
|
||||
|
||||
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapField",
|
||||
MapField_methods);
|
||||
|
||||
MapField_class_entry = zend_register_internal_class(&tmp_ce);
|
||||
zend_class_implements(MapField_class_entry, 3, zend_ce_arrayaccess,
|
||||
zend_ce_aggregate, zend_ce_countable);
|
||||
MapField_class_entry->ce_flags |= ZEND_ACC_FINAL;
|
||||
MapField_class_entry->create_object = MapField_create;
|
||||
|
||||
h = &MapField_object_handlers;
|
||||
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
|
||||
h->dtor_obj = MapField_destructor;
|
||||
#if PHP_VERSION_ID < 80000
|
||||
h->compare_objects = MapField_compare_objects;
|
||||
#else
|
||||
h->compare = MapField_compare_objects;
|
||||
#endif
|
||||
h->clone_obj = MapField_clone_obj;
|
||||
h->get_properties = Map_GetProperties;
|
||||
h->get_property_ptr_ptr = Map_GetPropertyPtrPtr;
|
||||
|
||||
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapFieldIter",
|
||||
map_field_iter_methods);
|
||||
|
||||
MapFieldIter_class_entry = zend_register_internal_class(&tmp_ce);
|
||||
zend_class_implements(MapFieldIter_class_entry, 1, zend_ce_iterator);
|
||||
MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
|
||||
MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL;
|
||||
MapFieldIter_class_entry->create_object = MapFieldIter_create;
|
||||
|
||||
h = &MapFieldIter_object_handlers;
|
||||
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
|
||||
h->dtor_obj = map_field_iter_dtor;
|
||||
}
|
||||
70
libs/protobuf/php/ext/google/protobuf/map.h
Normal file
70
libs/protobuf/php/ext/google/protobuf/map.h
Normal file
@@ -0,0 +1,70 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef PHP_PROTOBUF_MAP_H_
|
||||
#define PHP_PROTOBUF_MAP_H_
|
||||
|
||||
#include <php.h>
|
||||
|
||||
#include "def.h"
|
||||
#include "php-upb.h"
|
||||
|
||||
void Map_ModuleInit();
|
||||
|
||||
typedef struct {
|
||||
upb_CType key_type;
|
||||
TypeInfo val_type;
|
||||
} MapField_Type;
|
||||
|
||||
MapField_Type MapType_Get(const upb_FieldDef *f);
|
||||
|
||||
// Gets a upb_Map* for the PHP object |val|:
|
||||
// * If |val| is a RepeatedField object, we first check its type and verify
|
||||
// that that the elements have the correct type for |f|. If so, we return the
|
||||
// wrapped upb_Map*. We also make sure that this map's arena is fused to
|
||||
// |arena|, so the returned upb_Map is guaranteed to live as long as
|
||||
// |arena|.
|
||||
// * If |val| is a PHP Map, we attempt to create a new upb_Map using
|
||||
// |arena| and add all of the PHP elements to it.
|
||||
//
|
||||
// If an error occurs, we raise a PHP error and return NULL.
|
||||
upb_Map *MapField_GetUpbMap(zval *val, MapField_Type type, upb_Arena *arena);
|
||||
|
||||
// Creates a PHP MapField object for the given upb_Map* and |f| and returns it
|
||||
// in |val|. The PHP object will keep a reference to this |arena| to ensure the
|
||||
// underlying array data stays alive.
|
||||
//
|
||||
// If |map| is NULL, this will return a PHP null object.
|
||||
void MapField_GetPhpWrapper(zval *val, upb_Map *arr, MapField_Type type,
|
||||
zval *arena);
|
||||
|
||||
bool MapEq(const upb_Map *m1, const upb_Map *m2, MapField_Type type);
|
||||
|
||||
#endif // PHP_PROTOBUF_MAP_H_
|
||||
1434
libs/protobuf/php/ext/google/protobuf/message.c
Normal file
1434
libs/protobuf/php/ext/google/protobuf/message.c
Normal file
File diff suppressed because it is too large
Load Diff
61
libs/protobuf/php/ext/google/protobuf/message.h
Normal file
61
libs/protobuf/php/ext/google/protobuf/message.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef PHP_PROTOBUF_MESSAGE_H_
|
||||
#define PHP_PROTOBUF_MESSAGE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "def.h"
|
||||
|
||||
// Registers the PHP Message class.
|
||||
void Message_ModuleInit();
|
||||
|
||||
// Gets a upb_Message* for the PHP object |val|, which must either be a Message
|
||||
// object or 'null'. Returns true and stores the message in |msg| if the
|
||||
// conversion succeeded (we can't return upb_Message* because null->NULL is a valid
|
||||
// conversion). Returns false and raises a PHP error if this isn't a Message
|
||||
// object or null, or if the Message object doesn't match this Descriptor.
|
||||
//
|
||||
// The given |arena| will be fused to this message's arena.
|
||||
bool Message_GetUpbMessage(zval *val, const Descriptor *desc, upb_Arena *arena,
|
||||
upb_Message **msg);
|
||||
|
||||
// Gets or creates a PHP Message object to wrap the given upb_Message* and |desc|
|
||||
// and returns it in |val|. The PHP object will keep a reference to this |arena|
|
||||
// to ensure the underlying message data stays alive.
|
||||
//
|
||||
// If |msg| is NULL, this will return a PHP null.
|
||||
void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_Message *msg,
|
||||
zval *arena);
|
||||
|
||||
bool ValueEq(upb_MessageValue val1, upb_MessageValue val2, TypeInfo type);
|
||||
|
||||
#endif // PHP_PROTOBUF_MESSAGE_H_
|
||||
287
libs/protobuf/php/ext/google/protobuf/names.c
Normal file
287
libs/protobuf/php/ext/google/protobuf/names.c
Normal file
@@ -0,0 +1,287 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "names.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "protobuf.h"
|
||||
|
||||
/* stringsink *****************************************************************/
|
||||
|
||||
typedef struct {
|
||||
char *ptr;
|
||||
size_t len, size;
|
||||
} stringsink;
|
||||
|
||||
static size_t stringsink_string(stringsink *sink, const char *ptr, size_t len) {
|
||||
size_t new_size = sink->size;
|
||||
|
||||
while (sink->len + len > new_size) {
|
||||
new_size *= 2;
|
||||
}
|
||||
|
||||
if (new_size != sink->size) {
|
||||
sink->ptr = realloc(sink->ptr, new_size);
|
||||
sink->size = new_size;
|
||||
}
|
||||
|
||||
memcpy(sink->ptr + sink->len, ptr, len);
|
||||
sink->len += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void stringsink_init(stringsink *sink) {
|
||||
sink->size = 32;
|
||||
sink->ptr = malloc(sink->size);
|
||||
PBPHP_ASSERT(sink->ptr != NULL);
|
||||
sink->len = 0;
|
||||
}
|
||||
|
||||
static void stringsink_uninit(stringsink *sink) { free(sink->ptr); }
|
||||
|
||||
/* def name -> classname ******************************************************/
|
||||
|
||||
const char *const kReservedNames[] = {
|
||||
"abstract", "and", "array", "as", "break",
|
||||
"callable", "case", "catch", "class", "clone",
|
||||
"const", "continue", "declare", "default", "die",
|
||||
"do", "echo", "else", "elseif", "empty",
|
||||
"enddeclare", "endfor", "endforeach", "endif", "endswitch",
|
||||
"endwhile", "eval", "exit", "extends", "final",
|
||||
"finally", "fn", "for", "foreach", "function",
|
||||
"if", "implements", "include", "include_once", "instanceof",
|
||||
"global", "goto", "insteadof", "interface", "isset",
|
||||
"list", "match", "namespace", "new", "object",
|
||||
"or", "parent", "print", "private", "protected",
|
||||
"public", "readonly", "require", "require_once", "return",
|
||||
"self", "static", "switch", "throw", "trait",
|
||||
"try", "unset", "use", "var", "while",
|
||||
"xor", "yield", "int", "float", "bool",
|
||||
"string", "true", "false", "null", "void",
|
||||
"iterable", NULL};
|
||||
|
||||
const char *const kPreviouslyUnreservedNames[] = {
|
||||
"readonly", NULL};
|
||||
|
||||
bool is_reserved_name(const char* name) {
|
||||
int i;
|
||||
for (i = 0; kReservedNames[i]; i++) {
|
||||
if (strcmp(kReservedNames[i], name) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_previously_unreserved_name(const char* name) {
|
||||
for (int i = 0; kPreviouslyUnreservedNames[i]; i++) {
|
||||
if (strcmp(kPreviouslyUnreservedNames[i], name) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static char nolocale_tolower(char ch) {
|
||||
if (ch >= 'A' && ch <= 'Z') {
|
||||
return ch - ('A' - 'a');
|
||||
} else {
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
||||
static char nolocale_toupper(char ch) {
|
||||
if (ch >= 'a' && ch <= 'z') {
|
||||
return ch - ('a' - 'A');
|
||||
} else {
|
||||
return ch;
|
||||
}
|
||||
}
|
||||
|
||||
static char *strdup_nolocale_lower(char *str, int length) {
|
||||
char* lower = malloc(length + 1);
|
||||
lower[length] = '\0';
|
||||
for(int i = 0; i < length; ++i) {
|
||||
lower[i] = nolocale_tolower(str[i]);
|
||||
}
|
||||
return lower;
|
||||
}
|
||||
|
||||
static bool is_reserved(const char *segment, int length, bool previous) {
|
||||
bool result;
|
||||
char* lower = strdup_nolocale_lower(segment, length);
|
||||
result = is_reserved_name(lower);
|
||||
if (result && previous && is_previously_unreserved_name(lower)) {
|
||||
result = false;
|
||||
}
|
||||
free(lower);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void fill_prefix(const char *segment, int length,
|
||||
const char *prefix_given,
|
||||
const char *package_name,
|
||||
stringsink *classname,
|
||||
bool previous) {
|
||||
if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
|
||||
stringsink_string(classname, prefix_given, strlen(prefix_given));
|
||||
} else {
|
||||
if (is_reserved(segment, length, previous)) {
|
||||
if (package_name != NULL &&
|
||||
strcmp("google.protobuf", package_name) == 0) {
|
||||
stringsink_string(classname, "GPB", 3);
|
||||
} else {
|
||||
stringsink_string(classname, "PB", 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_segment(const char *segment, int length,
|
||||
stringsink *classname, bool use_camel) {
|
||||
if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) {
|
||||
char first = nolocale_toupper(segment[0]);
|
||||
stringsink_string(classname, &first, 1);
|
||||
stringsink_string(classname, segment + 1, length - 1);
|
||||
} else {
|
||||
stringsink_string(classname, segment, length);
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_namespace(const char *package, const char *php_namespace,
|
||||
stringsink *classname, bool previous) {
|
||||
if (php_namespace != NULL) {
|
||||
if (strlen(php_namespace) != 0) {
|
||||
stringsink_string(classname, php_namespace, strlen(php_namespace));
|
||||
stringsink_string(classname, "\\", 1);
|
||||
}
|
||||
} else if (package != NULL) {
|
||||
int i = 0, j = 0;
|
||||
size_t package_len = strlen(package);
|
||||
while (i < package_len) {
|
||||
j = i;
|
||||
while (j < package_len && package[j] != '.') {
|
||||
j++;
|
||||
}
|
||||
fill_prefix(package + i, j - i, "", package, classname, previous);
|
||||
fill_segment(package + i, j - i, classname, true);
|
||||
stringsink_string(classname, "\\", 1);
|
||||
i = j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fill_classname(const char *fullname,
|
||||
const char *package,
|
||||
const char *prefix,
|
||||
stringsink *classname,
|
||||
bool previous) {
|
||||
int classname_start = 0;
|
||||
if (package != NULL) {
|
||||
size_t package_len = strlen(package);
|
||||
classname_start = package_len == 0 ? 0 : package_len + 1;
|
||||
}
|
||||
size_t fullname_len = strlen(fullname);
|
||||
|
||||
int i = classname_start, j;
|
||||
while (i < fullname_len) {
|
||||
j = i;
|
||||
while (j < fullname_len && fullname[j] != '.') {
|
||||
j++;
|
||||
}
|
||||
fill_prefix(fullname + i, j - i, prefix, package, classname, previous);
|
||||
fill_segment(fullname + i, j - i, classname, false);
|
||||
if (j != fullname_len) {
|
||||
stringsink_string(classname, "\\", 1);
|
||||
}
|
||||
i = j + 1;
|
||||
}
|
||||
}
|
||||
|
||||
char *str_view_dup(upb_StringView str) {
|
||||
char *ret = malloc(str.size + 1);
|
||||
memcpy(ret, str.data, str.size);
|
||||
ret[str.size] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *GetPhpClassname(const upb_FileDef *file, const char *fullname, bool previous) {
|
||||
// Prepend '.' to package name to make it absolute. In the 5 additional
|
||||
// bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if
|
||||
// given message is google.protobuf.Empty.
|
||||
const google_protobuf_FileOptions* opts = upb_FileDef_Options(file);
|
||||
const char *package = upb_FileDef_Package(file);
|
||||
char *php_namespace =
|
||||
google_protobuf_FileOptions_has_php_namespace(opts)
|
||||
? str_view_dup(google_protobuf_FileOptions_php_namespace(opts))
|
||||
: NULL;
|
||||
char *prefix =
|
||||
google_protobuf_FileOptions_has_php_class_prefix(opts)
|
||||
? str_view_dup(google_protobuf_FileOptions_php_class_prefix(opts))
|
||||
: NULL;
|
||||
char *ret;
|
||||
|
||||
stringsink namesink;
|
||||
stringsink_init(&namesink);
|
||||
|
||||
fill_namespace(package, php_namespace, &namesink, previous);
|
||||
fill_classname(fullname, package, prefix, &namesink, previous);
|
||||
stringsink_string(&namesink, "\0", 1);
|
||||
ret = strdup(namesink.ptr);
|
||||
stringsink_uninit(&namesink);
|
||||
free(php_namespace);
|
||||
free(prefix);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool IsPreviouslyUnreservedClassName(const char* fullname) {
|
||||
const char *classname = strrchr(fullname, '\\');
|
||||
if (classname) {
|
||||
classname += 1;
|
||||
} else {
|
||||
classname = fullname;
|
||||
}
|
||||
if (strncmp(classname, "PB", 2) != 0) {
|
||||
return false;
|
||||
}
|
||||
classname += 2;
|
||||
int length = strlen(classname);
|
||||
char* lower = strdup_nolocale_lower(classname, length);
|
||||
for (int j = 0; kPreviouslyUnreservedNames[j]; j++) {
|
||||
if (strcmp(kPreviouslyUnreservedNames[j], lower) == 0) {
|
||||
free(lower);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
free(lower);
|
||||
return false;
|
||||
}
|
||||
41
libs/protobuf/php/ext/google/protobuf/names.h
Normal file
41
libs/protobuf/php/ext/google/protobuf/names.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef PHP_PROTOBUF_NAMES_H_
|
||||
#define PHP_PROTOBUF_NAMES_H_
|
||||
|
||||
#include "php-upb.h"
|
||||
|
||||
// Translates a protobuf symbol name (eg. foo.bar.Baz) into a PHP class name
|
||||
// (eg. \Foo\Bar\Baz).
|
||||
char *GetPhpClassname(const upb_FileDef *file, const char *fullname, bool previous);
|
||||
bool IsPreviouslyUnreservedClassName(const char* fullname);
|
||||
|
||||
#endif // PHP_PROTOBUF_NAMES_H_
|
||||
1453
libs/protobuf/php/ext/google/protobuf/package.xml
Normal file
1453
libs/protobuf/php/ext/google/protobuf/package.xml
Normal file
File diff suppressed because it is too large
Load Diff
13002
libs/protobuf/php/ext/google/protobuf/php-upb.c
Normal file
13002
libs/protobuf/php/ext/google/protobuf/php-upb.c
Normal file
File diff suppressed because it is too large
Load Diff
7463
libs/protobuf/php/ext/google/protobuf/php-upb.h
Normal file
7463
libs/protobuf/php/ext/google/protobuf/php-upb.h
Normal file
File diff suppressed because it is too large
Load Diff
45
libs/protobuf/php/ext/google/protobuf/php_protobuf.h
Normal file
45
libs/protobuf/php/ext/google/protobuf/php_protobuf.h
Normal file
@@ -0,0 +1,45 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2022 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// ! THIS FILE ONLY APPROACHING IN-TREE PHP EXTENSION BUILD !
|
||||
// ! DOES NOT USE NORMALLY. !
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef PHP_PROTOBUF_H
|
||||
# define PHP_PROTOBUF_H
|
||||
|
||||
# ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
# endif
|
||||
|
||||
extern zend_module_entry protobuf_module_entry;
|
||||
# define phpext_protobuf_ptr &protobuf_module_entry
|
||||
|
||||
#endif /* PHP_PROTOBUF_H */
|
||||
357
libs/protobuf/php/ext/google/protobuf/protobuf.c
Normal file
357
libs/protobuf/php/ext/google/protobuf/protobuf.c
Normal file
@@ -0,0 +1,357 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "protobuf.h"
|
||||
|
||||
#include <php.h>
|
||||
#include <Zend/zend_interfaces.h>
|
||||
|
||||
#include "arena.h"
|
||||
#include "array.h"
|
||||
#include "convert.h"
|
||||
#include "def.h"
|
||||
#include "map.h"
|
||||
#include "message.h"
|
||||
#include "names.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Module "globals"
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Despite the name, module "globals" are really thread-locals:
|
||||
// * PROTOBUF_G(var) accesses the thread-local variable for 'var'. Either:
|
||||
// * PROTOBUF_G(var) -> protobuf_globals.var (Non-ZTS / non-thread-safe)
|
||||
// * PROTOBUF_G(var) -> <Zend magic> (ZTS / thread-safe builds)
|
||||
|
||||
#define PROTOBUF_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(protobuf, v)
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(protobuf)
|
||||
// Set by the user to make the descriptor pool persist between requests.
|
||||
zend_bool keep_descriptor_pool_after_request;
|
||||
|
||||
// Set by the user to make the descriptor pool persist between requests.
|
||||
zend_class_entry* constructing_class;
|
||||
|
||||
// A upb_DefPool that we are saving for the next request so that we don't have
|
||||
// to rebuild it from scratch. When keep_descriptor_pool_after_request==true,
|
||||
// we steal the upb_DefPool from the global DescriptorPool object just before
|
||||
// destroying it.
|
||||
upb_DefPool *global_symtab;
|
||||
|
||||
// Object cache (see interface in protobuf.h).
|
||||
HashTable object_cache;
|
||||
|
||||
// Name cache (see interface in protobuf.h).
|
||||
HashTable name_msg_cache;
|
||||
HashTable name_enum_cache;
|
||||
|
||||
// An array of descriptor objects constructed during this request. These are
|
||||
// logically referenced by the corresponding class entry, but since we can't
|
||||
// actually write a class entry destructor, we reference them here, to be
|
||||
// destroyed on request shutdown.
|
||||
HashTable descriptors;
|
||||
ZEND_END_MODULE_GLOBALS(protobuf)
|
||||
|
||||
void free_protobuf_globals(zend_protobuf_globals *globals) {
|
||||
zend_hash_destroy(&globals->name_msg_cache);
|
||||
zend_hash_destroy(&globals->name_enum_cache);
|
||||
upb_DefPool_Free(globals->global_symtab);
|
||||
globals->global_symtab = NULL;
|
||||
}
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS(protobuf)
|
||||
|
||||
upb_DefPool *get_global_symtab() {
|
||||
return PROTOBUF_G(global_symtab);
|
||||
}
|
||||
|
||||
// This is a PHP extension (not a Zend extension). What follows is a summary of
|
||||
// a PHP extension's lifetime and when various handlers are called.
|
||||
//
|
||||
// * PHP_GINIT_FUNCTION(protobuf) / PHP_GSHUTDOWN_FUNCTION(protobuf)
|
||||
// are the constructor/destructor for the globals. The sequence over the
|
||||
// course of a process lifetime is:
|
||||
//
|
||||
// # Process startup
|
||||
// GINIT(<Main Thread Globals>)
|
||||
// MINIT
|
||||
//
|
||||
// foreach request:
|
||||
// RINIT
|
||||
// # Request is processed here.
|
||||
// RSHUTDOWN
|
||||
//
|
||||
// foreach thread:
|
||||
// GINIT(<This Thread Globals>)
|
||||
// # Code for the thread runs here.
|
||||
// GSHUTDOWN(<This Thread Globals>)
|
||||
//
|
||||
// # Process Shutdown
|
||||
// #
|
||||
// # These should be running per the docs, but I have not been able to
|
||||
// # actually get the process-wide shutdown functions to run.
|
||||
// #
|
||||
// # MSHUTDOWN
|
||||
// # GSHUTDOWN(<Main Thread Globals>)
|
||||
//
|
||||
// * Threads can be created either explicitly by the user, inside a request,
|
||||
// or implicitly by the runtime, to process multiple requests concurrently.
|
||||
// If the latter is being used, then the "foreach thread" block above
|
||||
// actually looks like this:
|
||||
//
|
||||
// foreach thread:
|
||||
// GINIT(<This Thread Globals>)
|
||||
// # A non-main thread will only receive requests when using a threaded
|
||||
// # MPM with Apache
|
||||
// foreach request:
|
||||
// RINIT
|
||||
// # Request is processed here.
|
||||
// RSHUTDOWN
|
||||
// GSHUTDOWN(<This Thread Globals>)
|
||||
//
|
||||
// That said, it appears that few people use threads with PHP:
|
||||
// * The pthread package documented at
|
||||
// https://www.php.net/manual/en/class.thread.php nas not been released
|
||||
// since 2016, and the current release fails to compile against any PHP
|
||||
// newer than 7.0.33.
|
||||
// * The GitHub master branch supports 7.2+, but this has not been released
|
||||
// to PECL.
|
||||
// * Its owner has disavowed it as "broken by design" and "in an untenable
|
||||
// position for the future": https://github.com/krakjoe/pthreads/issues/929
|
||||
// * The only way to use PHP with requests in different threads is to use the
|
||||
// Apache 2 mod_php with the "worker" MPM. But this is explicitly
|
||||
// discouraged by the documentation: https://serverfault.com/a/231660
|
||||
|
||||
static PHP_GSHUTDOWN_FUNCTION(protobuf) {
|
||||
if (protobuf_globals->global_symtab) {
|
||||
free_protobuf_globals(protobuf_globals);
|
||||
}
|
||||
}
|
||||
|
||||
static PHP_GINIT_FUNCTION(protobuf) {
|
||||
protobuf_globals->global_symtab = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP_RINIT_FUNCTION(protobuf)
|
||||
*
|
||||
* This function is run at the beginning of processing each request.
|
||||
*/
|
||||
static PHP_RINIT_FUNCTION(protobuf) {
|
||||
// Create the global generated pool.
|
||||
// Reuse the symtab (if any) left to us by the last request.
|
||||
upb_DefPool *symtab = PROTOBUF_G(global_symtab);
|
||||
if (!symtab) {
|
||||
PROTOBUF_G(global_symtab) = symtab = upb_DefPool_New();
|
||||
zend_hash_init(&PROTOBUF_G(name_msg_cache), 64, NULL, NULL, 0);
|
||||
zend_hash_init(&PROTOBUF_G(name_enum_cache), 64, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
zend_hash_init(&PROTOBUF_G(object_cache), 64, NULL, NULL, 0);
|
||||
zend_hash_init(&PROTOBUF_G(descriptors), 64, NULL, ZVAL_PTR_DTOR, 0);
|
||||
PROTOBUF_G(constructing_class) = NULL;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP_RSHUTDOWN_FUNCTION(protobuf)
|
||||
*
|
||||
* This function is run at the end of processing each request.
|
||||
*/
|
||||
static PHP_RSHUTDOWN_FUNCTION(protobuf) {
|
||||
// Preserve the symtab if requested.
|
||||
if (!PROTOBUF_G(keep_descriptor_pool_after_request)) {
|
||||
free_protobuf_globals(ZEND_MODULE_GLOBALS_BULK(protobuf));
|
||||
}
|
||||
|
||||
zend_hash_destroy(&PROTOBUF_G(object_cache));
|
||||
zend_hash_destroy(&PROTOBUF_G(descriptors));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Object Cache.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void Descriptors_Add(zend_object *desc) {
|
||||
// The hash table will own a ref (it will destroy it when the table is
|
||||
// destroyed), but for some reason the insert operation does not add a ref, so
|
||||
// we do that here with ZVAL_OBJ_COPY().
|
||||
zval zv;
|
||||
ZVAL_OBJ_COPY(&zv, desc);
|
||||
zend_hash_next_index_insert(&PROTOBUF_G(descriptors), &zv);
|
||||
}
|
||||
|
||||
void ObjCache_Add(const void *upb_obj, zend_object *php_obj) {
|
||||
zend_ulong k = (zend_ulong)upb_obj;
|
||||
zend_hash_index_add_ptr(&PROTOBUF_G(object_cache), k, php_obj);
|
||||
}
|
||||
|
||||
void ObjCache_Delete(const void *upb_obj) {
|
||||
if (upb_obj) {
|
||||
zend_ulong k = (zend_ulong)upb_obj;
|
||||
int ret = zend_hash_index_del(&PROTOBUF_G(object_cache), k);
|
||||
PBPHP_ASSERT(ret == SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
bool ObjCache_Get(const void *upb_obj, zval *val) {
|
||||
zend_ulong k = (zend_ulong)upb_obj;
|
||||
zend_object *obj = zend_hash_index_find_ptr(&PROTOBUF_G(object_cache), k);
|
||||
|
||||
if (obj) {
|
||||
ZVAL_OBJ_COPY(val, obj);
|
||||
return true;
|
||||
} else {
|
||||
ZVAL_NULL(val);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Name Cache.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void NameMap_AddMessage(const upb_MessageDef *m) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
char *k = GetPhpClassname(upb_MessageDef_File(m), upb_MessageDef_FullName(m), (bool)i);
|
||||
zend_hash_str_add_ptr(&PROTOBUF_G(name_msg_cache), k, strlen(k), (void*)m);
|
||||
if (!IsPreviouslyUnreservedClassName(k)) {
|
||||
free(k);
|
||||
return;
|
||||
}
|
||||
free(k);
|
||||
}
|
||||
}
|
||||
|
||||
void NameMap_AddEnum(const upb_EnumDef *e) {
|
||||
char *k = GetPhpClassname(upb_EnumDef_File(e), upb_EnumDef_FullName(e), false);
|
||||
zend_hash_str_add_ptr(&PROTOBUF_G(name_enum_cache), k, strlen(k), (void*)e);
|
||||
free(k);
|
||||
}
|
||||
|
||||
const upb_MessageDef *NameMap_GetMessage(zend_class_entry *ce) {
|
||||
const upb_MessageDef *ret =
|
||||
zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
|
||||
|
||||
if (!ret && ce->create_object && ce != PROTOBUF_G(constructing_class)) {
|
||||
#if PHP_VERSION_ID < 80000
|
||||
zval tmp;
|
||||
zval zv;
|
||||
ZVAL_OBJ(&tmp, ce->create_object(ce));
|
||||
zend_call_method_with_0_params(&tmp, ce, NULL, "__construct", &zv);
|
||||
zval_ptr_dtor(&tmp);
|
||||
#else
|
||||
zval zv;
|
||||
zend_object *tmp = ce->create_object(ce);
|
||||
zend_call_method_with_0_params(tmp, ce, NULL, "__construct", &zv);
|
||||
OBJ_RELEASE(tmp);
|
||||
#endif
|
||||
zval_ptr_dtor(&zv);
|
||||
ret = zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const upb_EnumDef *NameMap_GetEnum(zend_class_entry *ce) {
|
||||
const upb_EnumDef *ret =
|
||||
zend_hash_find_ptr(&PROTOBUF_G(name_enum_cache), ce->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void NameMap_EnterConstructor(zend_class_entry* ce) {
|
||||
assert(!PROTOBUF_G(constructing_class));
|
||||
PROTOBUF_G(constructing_class) = ce;
|
||||
}
|
||||
|
||||
void NameMap_ExitConstructor(zend_class_entry* ce) {
|
||||
assert(PROTOBUF_G(constructing_class) == ce);
|
||||
PROTOBUF_G(constructing_class) = NULL;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Module init.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
zend_function_entry protobuf_functions[] = {
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
static const zend_module_dep protobuf_deps[] = {
|
||||
ZEND_MOD_OPTIONAL("date")
|
||||
ZEND_MOD_END
|
||||
};
|
||||
|
||||
PHP_INI_BEGIN()
|
||||
STD_PHP_INI_ENTRY("protobuf.keep_descriptor_pool_after_request", "0",
|
||||
PHP_INI_ALL, OnUpdateBool,
|
||||
keep_descriptor_pool_after_request, zend_protobuf_globals,
|
||||
protobuf_globals)
|
||||
PHP_INI_END()
|
||||
|
||||
static PHP_MINIT_FUNCTION(protobuf) {
|
||||
REGISTER_INI_ENTRIES();
|
||||
Arena_ModuleInit();
|
||||
Array_ModuleInit();
|
||||
Convert_ModuleInit();
|
||||
Def_ModuleInit();
|
||||
Map_ModuleInit();
|
||||
Message_ModuleInit();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static PHP_MSHUTDOWN_FUNCTION(protobuf) {
|
||||
UNREGISTER_INI_ENTRIES();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
zend_module_entry protobuf_module_entry = {
|
||||
STANDARD_MODULE_HEADER_EX,
|
||||
NULL,
|
||||
protobuf_deps,
|
||||
"protobuf", // extension name
|
||||
protobuf_functions, // function list
|
||||
PHP_MINIT(protobuf), // process startup
|
||||
PHP_MSHUTDOWN(protobuf), // process shutdown
|
||||
PHP_RINIT(protobuf), // request shutdown
|
||||
PHP_RSHUTDOWN(protobuf), // request shutdown
|
||||
NULL, // extension info
|
||||
PHP_PROTOBUF_VERSION, // extension version
|
||||
PHP_MODULE_GLOBALS(protobuf), // globals descriptor
|
||||
PHP_GINIT(protobuf), // globals ctor
|
||||
PHP_GSHUTDOWN(protobuf), // globals dtor
|
||||
NULL, // post deactivate
|
||||
STANDARD_MODULE_PROPERTIES_EX
|
||||
};
|
||||
|
||||
ZEND_GET_MODULE(protobuf)
|
||||
182
libs/protobuf/php/ext/google/protobuf/protobuf.h
Normal file
182
libs/protobuf/php/ext/google/protobuf/protobuf.h
Normal file
@@ -0,0 +1,182 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef PHP_PROTOBUF_H_
|
||||
#define PHP_PROTOBUF_H_
|
||||
|
||||
#include <php.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "php-upb.h"
|
||||
|
||||
upb_DefPool *get_global_symtab();
|
||||
|
||||
#if PHP_VERSION_ID < 70300
|
||||
#define GC_ADDREF(h) ++GC_REFCOUNT(h)
|
||||
#define GC_DELREF(h) --GC_REFCOUNT(h)
|
||||
#endif
|
||||
|
||||
// Since php 7.4, the write_property() object handler now returns the assigned
|
||||
// value (after possible type coercions) rather than void.
|
||||
// https://github.com/php/php-src/blob/PHP-7.4.0/UPGRADING.INTERNALS#L171-L173
|
||||
#if PHP_VERSION_ID < 70400
|
||||
#define PROTO_RETURN_VAL void
|
||||
#else
|
||||
#define PROTO_RETURN_VAL zval*
|
||||
#endif
|
||||
|
||||
// Since php 8.0, the Object Handlers API was changed to receive zend_object*
|
||||
// instead of zval* and zend_string* instead of zval* for property names.
|
||||
// https://github.com/php/php-src/blob/php-8.0.0beta1/UPGRADING.INTERNALS#L37-L39
|
||||
#if PHP_VERSION_ID < 80000
|
||||
#define PROTO_VAL zval
|
||||
#define PROTO_STR zval
|
||||
#define PROTO_VAL_P(obj) (void*)Z_OBJ_P(obj)
|
||||
#define PROTO_STRVAL_P(obj) Z_STRVAL_P(obj)
|
||||
#define PROTO_STRLEN_P(obj) Z_STRLEN_P(obj)
|
||||
#define ZVAL_OBJ_COPY(z, o) do { ZVAL_OBJ(z, o); GC_ADDREF(o); } while (0)
|
||||
#define RETVAL_OBJ_COPY(r) ZVAL_OBJ_COPY(return_value, r)
|
||||
#define RETURN_OBJ_COPY(r) do { RETVAL_OBJ_COPY(r); return; } while (0)
|
||||
#define RETURN_COPY(zv) do { ZVAL_COPY(return_value, zv); return; } while (0)
|
||||
#define RETURN_COPY_VALUE(zv) do { ZVAL_COPY_VALUE(return_value, zv); return; } while (0)
|
||||
#else
|
||||
#define PROTO_VAL zend_object
|
||||
#define PROTO_STR zend_string
|
||||
#define PROTO_VAL_P(obj) (void*)(obj)
|
||||
#define PROTO_STRVAL_P(obj) ZSTR_VAL(obj)
|
||||
#define PROTO_STRLEN_P(obj) ZSTR_LEN(obj)
|
||||
#endif
|
||||
|
||||
// In PHP 8.1, several old interfaces are removed:
|
||||
// https://github.com/php/php-src/blob/14f599ea7def7c7a59c40aff763ce8b105573e7a/UPGRADING.INTERNALS#L27-L31
|
||||
//
|
||||
// We now use the new interfaces (zend_ce_arrayaccess and zend_ce_countable).
|
||||
// However we have to polyfill zend_ce_countable, which was only introduced in
|
||||
// PHP 7.2.0.
|
||||
#if PHP_VERSION_ID < 70200
|
||||
#define zend_ce_countable spl_ce_Countable
|
||||
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
|
||||
ZEND_BEGIN_ARG_INFO_EX(name, return_reference, required_num_args, allow_null)
|
||||
#endif
|
||||
|
||||
// polyfill for ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX, which changes between 7.1 and 7.2
|
||||
#if PHP_VERSION_ID < 70200
|
||||
#define PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, /*class_name*/ 0, allow_null)
|
||||
#else
|
||||
#define PROTOBUF_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null)
|
||||
#endif
|
||||
|
||||
// In PHP 8.1, mismatched tentative return types emit a deprecation notice.
|
||||
// https://wiki.php.net/rfc/internal_method_return_types
|
||||
//
|
||||
// When compiling for earlier php versions, the return type is dropped.
|
||||
#if PHP_VERSION_ID < 80100
|
||||
#define ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
|
||||
ZEND_BEGIN_ARG_INFO_EX(name, return_reference, required_num_args, allow_null)
|
||||
#endif
|
||||
|
||||
#ifndef IS_VOID
|
||||
#define IS_VOID 99
|
||||
#endif
|
||||
|
||||
#ifndef IS_MIXED
|
||||
#define IS_MIXED 99
|
||||
#endif
|
||||
|
||||
#ifndef _IS_BOOL
|
||||
#define _IS_BOOL 99
|
||||
#endif
|
||||
|
||||
#ifndef IS_LONG
|
||||
#define IS_LONG 99
|
||||
#endif
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_void, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_setter, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, value)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define PHP_PROTOBUF_VERSION "3.21.8"
|
||||
|
||||
// ptr -> PHP object cache. This is a weak map that caches lazily-created
|
||||
// wrapper objects around upb types:
|
||||
// * upb_Message* -> Message
|
||||
// * upb_Array* -> RepeatedField
|
||||
// * upb_Map*, -> MapField
|
||||
// * upb_MessageDef* -> Descriptor
|
||||
// * upb_EnumDef* -> EnumDescriptor
|
||||
// * upb_MessageDef* -> Descriptor
|
||||
//
|
||||
// Each wrapped object should add itself to the map when it is constructed, and
|
||||
// remove itself from the map when it is destroyed. This is how we ensure that
|
||||
// the map only contains live objects. The map is weak so it does not actually
|
||||
// take references to the cached objects.
|
||||
void ObjCache_Add(const void *key, zend_object *php_obj);
|
||||
void ObjCache_Delete(const void *key);
|
||||
bool ObjCache_Get(const void *key, zval *val);
|
||||
|
||||
// PHP class name map. This is necessary because the pb_name->php_class_name
|
||||
// transformation is non-reversible, so when we need to look up a msgdef or
|
||||
// enumdef by PHP class, we can't turn the class name into a pb_name.
|
||||
// * php_class_name -> upb_MessageDef*
|
||||
// * php_class_name -> upb_EnumDef*
|
||||
void NameMap_AddMessage(const upb_MessageDef *m);
|
||||
void NameMap_AddEnum(const upb_EnumDef *m);
|
||||
const upb_MessageDef *NameMap_GetMessage(zend_class_entry *ce);
|
||||
const upb_EnumDef *NameMap_GetEnum(zend_class_entry *ce);
|
||||
void NameMap_EnterConstructor(zend_class_entry* ce);
|
||||
void NameMap_ExitConstructor(zend_class_entry* ce);
|
||||
|
||||
// Add this descriptor object to the global list of descriptors that will be
|
||||
// kept alive for the duration of the request but destroyed when the request
|
||||
// is ending.
|
||||
void Descriptors_Add(zend_object *desc);
|
||||
|
||||
// We need our own assert() because PHP takes control of NDEBUG in its headers.
|
||||
#ifdef PBPHP_ENABLE_ASSERTS
|
||||
#define PBPHP_ASSERT(x) \
|
||||
do { \
|
||||
if (!(x)) { \
|
||||
fprintf(stderr, "Assertion failure at %s:%d %s", __FILE__, __LINE__, \
|
||||
#x); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (false)
|
||||
#else
|
||||
#define PBPHP_ASSERT(x) \
|
||||
do { \
|
||||
} while (false && (x))
|
||||
#endif
|
||||
|
||||
#endif // PHP_PROTOBUF_H_
|
||||
@@ -0,0 +1,9 @@
|
||||
--TEST--
|
||||
unnecessary zval
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(new \stdClass());
|
||||
?>
|
||||
--EXPECT--
|
||||
object(stdClass)#1 (0) {
|
||||
}
|
||||
3250
libs/protobuf/php/ext/google/protobuf/wkt.inc
Normal file
3250
libs/protobuf/php/ext/google/protobuf/wkt.inc
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user