Protocol Buffers - Google's data interchange format (grpc依赖)
https://developers.google.com/protocol-buffers/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1153 lines
35 KiB
1153 lines
35 KiB
// Protocol Buffers - Google's data interchange format |
|
// Copyright 2008 Google Inc. All rights reserved. |
|
// |
|
// Use of this source code is governed by a BSD-style |
|
// license that can be found in the LICENSE file or at |
|
// https://developers.google.com/open-source/licenses/bsd |
|
|
|
#include "def.h" |
|
|
|
#include <php.h> |
|
|
|
// This is not self-contained: it must be after other Zend includes. |
|
#include <Zend/zend_exceptions.h> |
|
|
|
#include "names.h" |
|
#include "php-upb.h" |
|
#include "protobuf.h" |
|
|
|
static void CheckUpbStatus(const upb_Status* status, const char* msg) { |
|
if (!upb_Status_IsOk(status)) { |
|
zend_error(E_ERROR, "%s: %s\n", msg, upb_Status_ErrorMessage(status)); |
|
} |
|
} |
|
|
|
static void FieldDescriptor_FromFieldDef(zval* val, const upb_FieldDef* f); |
|
|
|
// We use this for objects that should not be created directly from PHP. |
|
static zend_object* CreateHandler_ReturnNull(zend_class_entry* class_type) { |
|
return NULL; // Nobody should call this. |
|
} |
|
|
|
// clang-format off |
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_getByIndex, 0, 0, 1) |
|
ZEND_ARG_INFO(0, index) |
|
ZEND_END_ARG_INFO() |
|
// clang-format on |
|
|
|
// ----------------------------------------------------------------------------- |
|
// EnumValueDescriptor |
|
// ----------------------------------------------------------------------------- |
|
|
|
typedef struct { |
|
zend_object std; |
|
const char* name; |
|
int32_t number; |
|
} EnumValueDescriptor; |
|
|
|
zend_class_entry* EnumValueDescriptor_class_entry; |
|
static zend_object_handlers EnumValueDescriptor_object_handlers; |
|
|
|
/* |
|
* EnumValueDescriptor_Make() |
|
* |
|
* Function to create an EnumValueDescriptor object from C. |
|
*/ |
|
static void EnumValueDescriptor_Make(zval* val, const char* name, |
|
int32_t number) { |
|
EnumValueDescriptor* intern = emalloc(sizeof(EnumValueDescriptor)); |
|
zend_object_std_init(&intern->std, EnumValueDescriptor_class_entry); |
|
intern->std.handlers = &EnumValueDescriptor_object_handlers; |
|
intern->name = name; |
|
intern->number = number; |
|
// Skip object_properties_init(), we don't allow derived classes. |
|
ZVAL_OBJ(val, &intern->std); |
|
} |
|
|
|
/* |
|
* EnumValueDescriptor::getName() |
|
* |
|
* Returns the name for this enum value. |
|
*/ |
|
PHP_METHOD(EnumValueDescriptor, getName) { |
|
EnumValueDescriptor* intern = (EnumValueDescriptor*)Z_OBJ_P(getThis()); |
|
RETURN_STRING(intern->name); |
|
} |
|
|
|
/* |
|
* EnumValueDescriptor::getNumber() |
|
* |
|
* Returns the number for this enum value. |
|
*/ |
|
PHP_METHOD(EnumValueDescriptor, getNumber) { |
|
EnumValueDescriptor* intern = (EnumValueDescriptor*)Z_OBJ_P(getThis()); |
|
RETURN_LONG(intern->number); |
|
} |
|
|
|
// clang-format off |
|
static zend_function_entry EnumValueDescriptor_methods[] = { |
|
PHP_ME(EnumValueDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(EnumValueDescriptor, getNumber, arginfo_void, ZEND_ACC_PUBLIC) |
|
ZEND_FE_END |
|
}; |
|
// clang-format on |
|
|
|
// ----------------------------------------------------------------------------- |
|
// EnumDescriptor |
|
// ----------------------------------------------------------------------------- |
|
|
|
typedef struct { |
|
zend_object std; |
|
const upb_EnumDef* enumdef; |
|
void* cache_key; |
|
} EnumDescriptor; |
|
|
|
zend_class_entry* EnumDescriptor_class_entry; |
|
static zend_object_handlers EnumDescriptor_object_handlers; |
|
|
|
static void EnumDescriptor_destructor(zend_object* obj) { |
|
EnumDescriptor* intern = (EnumDescriptor*)obj; |
|
ObjCache_Delete(intern->cache_key); |
|
} |
|
|
|
// Caller owns a ref on the returned zval. |
|
static void EnumDescriptor_FromClassEntry(zval* val, zend_class_entry* ce) { |
|
// To differentiate enums from classes, we pointer-tag the class entry. |
|
void* key = (void*)((uintptr_t)ce | 1); |
|
PBPHP_ASSERT(key != ce); |
|
|
|
if (ce == NULL) { |
|
ZVAL_NULL(val); |
|
return; |
|
} |
|
|
|
if (!ObjCache_Get(key, val)) { |
|
const upb_EnumDef* e = NameMap_GetEnum(ce); |
|
if (!e) { |
|
ZVAL_NULL(val); |
|
return; |
|
} |
|
EnumDescriptor* ret = emalloc(sizeof(EnumDescriptor)); |
|
zend_object_std_init(&ret->std, EnumDescriptor_class_entry); |
|
ret->std.handlers = &EnumDescriptor_object_handlers; |
|
ret->enumdef = e; |
|
ret->cache_key = key; |
|
ObjCache_Add(key, &ret->std); |
|
ZVAL_OBJ(val, &ret->std); |
|
} |
|
} |
|
|
|
// Caller owns a ref on the returned zval. |
|
static void EnumDescriptor_FromEnumDef(zval* val, const upb_EnumDef* m) { |
|
if (!m) { |
|
ZVAL_NULL(val); |
|
} else { |
|
char* classname = |
|
GetPhpClassname(upb_EnumDef_File(m), upb_EnumDef_FullName(m), false); |
|
zend_string* str = zend_string_init(classname, strlen(classname), 0); |
|
zend_class_entry* ce = zend_lookup_class(str); // May autoload the class. |
|
|
|
zend_string_release(str); |
|
|
|
if (!ce) { |
|
zend_error(E_ERROR, "Couldn't load generated class %s", classname); |
|
} |
|
|
|
free(classname); |
|
EnumDescriptor_FromClassEntry(val, ce); |
|
} |
|
} |
|
|
|
/* |
|
* EnumDescriptor::getValue() |
|
* |
|
* Returns an EnumValueDescriptor for this index. Note: we are not looking |
|
* up by numeric enum value, but by the index in the list of enum values. |
|
*/ |
|
PHP_METHOD(EnumDescriptor, getValue) { |
|
EnumDescriptor* intern = (EnumDescriptor*)Z_OBJ_P(getThis()); |
|
zend_long index; |
|
zval ret; |
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { |
|
zend_error(E_USER_ERROR, "Expect integer for index.\n"); |
|
return; |
|
} |
|
|
|
if (index < 0 || index >= upb_EnumDef_ValueCount(intern->enumdef)) { |
|
zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); |
|
return; |
|
} |
|
|
|
const upb_EnumValueDef* ev = upb_EnumDef_Value(intern->enumdef, index); |
|
EnumValueDescriptor_Make(&ret, upb_EnumValueDef_Name(ev), |
|
upb_EnumValueDef_Number(ev)); |
|
RETURN_COPY_VALUE(&ret); |
|
} |
|
|
|
/* |
|
* EnumDescriptor::getValueCount() |
|
* |
|
* Returns the number of values in this enum. |
|
*/ |
|
PHP_METHOD(EnumDescriptor, getValueCount) { |
|
EnumDescriptor* intern = (EnumDescriptor*)Z_OBJ_P(getThis()); |
|
RETURN_LONG(upb_EnumDef_ValueCount(intern->enumdef)); |
|
} |
|
|
|
/* |
|
* EnumDescriptor::getPublicDescriptor() |
|
* |
|
* Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not |
|
* have two separate EnumDescriptor classes. We use a single class for both |
|
* the public and private descriptor. |
|
*/ |
|
PHP_METHOD(EnumDescriptor, getPublicDescriptor) { RETURN_COPY(getThis()); } |
|
|
|
// clang-format off |
|
static zend_function_entry EnumDescriptor_methods[] = { |
|
PHP_ME(EnumDescriptor, getPublicDescriptor, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(EnumDescriptor, getValueCount, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(EnumDescriptor, getValue, arginfo_getByIndex, ZEND_ACC_PUBLIC) |
|
ZEND_FE_END |
|
}; |
|
// clang-format on |
|
|
|
// ----------------------------------------------------------------------------- |
|
// Oneof |
|
// ----------------------------------------------------------------------------- |
|
|
|
typedef struct { |
|
zend_object std; |
|
const upb_OneofDef* oneofdef; |
|
} OneofDescriptor; |
|
|
|
zend_class_entry* OneofDescriptor_class_entry; |
|
static zend_object_handlers OneofDescriptor_object_handlers; |
|
|
|
static void OneofDescriptor_destructor(zend_object* obj) { |
|
OneofDescriptor* intern = (OneofDescriptor*)obj; |
|
ObjCache_Delete(intern->oneofdef); |
|
} |
|
|
|
static void OneofDescriptor_FromOneofDef(zval* val, const upb_OneofDef* o) { |
|
if (o == NULL) { |
|
ZVAL_NULL(val); |
|
return; |
|
} |
|
|
|
if (!ObjCache_Get(o, val)) { |
|
OneofDescriptor* ret = emalloc(sizeof(OneofDescriptor)); |
|
zend_object_std_init(&ret->std, OneofDescriptor_class_entry); |
|
ret->std.handlers = &OneofDescriptor_object_handlers; |
|
ret->oneofdef = o; |
|
ObjCache_Add(o, &ret->std); |
|
ZVAL_OBJ(val, &ret->std); |
|
} |
|
} |
|
|
|
/* |
|
* OneofDescriptor::getName() |
|
* |
|
* Returns the name of this oneof. |
|
*/ |
|
PHP_METHOD(OneofDescriptor, getName) { |
|
OneofDescriptor* intern = (OneofDescriptor*)Z_OBJ_P(getThis()); |
|
RETURN_STRING(upb_OneofDef_Name(intern->oneofdef)); |
|
} |
|
|
|
/* |
|
* OneofDescriptor::getField() |
|
* |
|
* Returns a field from this oneof. The given index must be in the range |
|
* [0, getFieldCount() - 1]. |
|
*/ |
|
PHP_METHOD(OneofDescriptor, getField) { |
|
OneofDescriptor* intern = (OneofDescriptor*)Z_OBJ_P(getThis()); |
|
zend_long index; |
|
zval ret; |
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { |
|
zend_error(E_USER_ERROR, "Expect integer for index.\n"); |
|
return; |
|
} |
|
|
|
if (index < 0 || index >= upb_OneofDef_FieldCount(intern->oneofdef)) { |
|
zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); |
|
return; |
|
} |
|
|
|
const upb_FieldDef* field = upb_OneofDef_Field(intern->oneofdef, index); |
|
FieldDescriptor_FromFieldDef(&ret, field); |
|
RETURN_COPY_VALUE(&ret); |
|
} |
|
|
|
/* |
|
* OneofDescriptor::getFieldCount() |
|
* |
|
* Returns the number of fields in this oneof. |
|
*/ |
|
PHP_METHOD(OneofDescriptor, getFieldCount) { |
|
OneofDescriptor* intern = (OneofDescriptor*)Z_OBJ_P(getThis()); |
|
RETURN_LONG(upb_OneofDef_FieldCount(intern->oneofdef)); |
|
} |
|
|
|
// clang-format off |
|
static zend_function_entry OneofDescriptor_methods[] = { |
|
PHP_ME(OneofDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(OneofDescriptor, getField, arginfo_getByIndex, ZEND_ACC_PUBLIC) |
|
PHP_ME(OneofDescriptor, getFieldCount, arginfo_void, ZEND_ACC_PUBLIC) |
|
ZEND_FE_END |
|
}; |
|
// clang-format on |
|
|
|
// ----------------------------------------------------------------------------- |
|
// FieldDescriptor |
|
// ----------------------------------------------------------------------------- |
|
|
|
typedef struct { |
|
zend_object std; |
|
const upb_FieldDef* fielddef; |
|
} FieldDescriptor; |
|
|
|
zend_class_entry* FieldDescriptor_class_entry; |
|
static zend_object_handlers FieldDescriptor_object_handlers; |
|
|
|
static void FieldDescriptor_destructor(zend_object* obj) { |
|
FieldDescriptor* intern = (FieldDescriptor*)obj; |
|
ObjCache_Delete(intern->fielddef); |
|
} |
|
|
|
// Caller owns a ref on the returned zval. |
|
static void FieldDescriptor_FromFieldDef(zval* val, const upb_FieldDef* f) { |
|
if (f == NULL) { |
|
ZVAL_NULL(val); |
|
return; |
|
} |
|
|
|
if (!ObjCache_Get(f, val)) { |
|
FieldDescriptor* ret = emalloc(sizeof(FieldDescriptor)); |
|
zend_object_std_init(&ret->std, FieldDescriptor_class_entry); |
|
ret->std.handlers = &FieldDescriptor_object_handlers; |
|
ret->fielddef = f; |
|
ObjCache_Add(f, &ret->std); |
|
ZVAL_OBJ(val, &ret->std); |
|
} |
|
} |
|
|
|
upb_CType to_fieldtype(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, UInt32); |
|
CASE(UInt64, UInt64); |
|
CASE(SInt32, Int32); |
|
CASE(SInt64, Int64); |
|
CASE(Fixed32, UInt32); |
|
CASE(Fixed64, UInt64); |
|
CASE(SFixed32, Int32); |
|
CASE(SFixed64, Int64); |
|
|
|
#undef CONVERT |
|
} |
|
|
|
zend_error(E_ERROR, "Unknown field type."); |
|
return 0; |
|
} |
|
|
|
/* |
|
* FieldDescriptor::getName() |
|
* |
|
* Returns the name of this field. |
|
*/ |
|
PHP_METHOD(FieldDescriptor, getName) { |
|
FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis()); |
|
RETURN_STRING(upb_FieldDef_Name(intern->fielddef)); |
|
} |
|
|
|
/* |
|
* FieldDescriptor::getNumber() |
|
* |
|
* Returns the number of this field. |
|
*/ |
|
PHP_METHOD(FieldDescriptor, getNumber) { |
|
FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis()); |
|
RETURN_LONG(upb_FieldDef_Number(intern->fielddef)); |
|
} |
|
|
|
/* |
|
* FieldDescriptor::getLabel() |
|
* |
|
* Returns the label of this field as an integer. |
|
*/ |
|
PHP_METHOD(FieldDescriptor, getLabel) { |
|
FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis()); |
|
RETURN_LONG(upb_FieldDef_Label(intern->fielddef)); |
|
} |
|
|
|
/* |
|
* FieldDescriptor::getType() |
|
* |
|
* Returns the type of this field as an integer. |
|
*/ |
|
PHP_METHOD(FieldDescriptor, getType) { |
|
FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis()); |
|
RETURN_LONG(upb_FieldDef_Type(intern->fielddef)); |
|
} |
|
|
|
/* |
|
* FieldDescriptor::isMap() |
|
* |
|
* Returns true if this field is a map. |
|
*/ |
|
PHP_METHOD(FieldDescriptor, isMap) { |
|
FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis()); |
|
RETURN_BOOL(upb_FieldDef_IsMap(intern->fielddef)); |
|
} |
|
|
|
/* |
|
* FieldDescriptor::getEnumType() |
|
* |
|
* Returns the EnumDescriptor for this field, which must be an enum. |
|
*/ |
|
PHP_METHOD(FieldDescriptor, getEnumType) { |
|
FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis()); |
|
const upb_EnumDef* e = upb_FieldDef_EnumSubDef(intern->fielddef); |
|
zval ret; |
|
|
|
if (!e) { |
|
zend_throw_exception_ex(NULL, 0, |
|
"Cannot get enum type for non-enum field '%s'", |
|
upb_FieldDef_Name(intern->fielddef)); |
|
return; |
|
} |
|
|
|
EnumDescriptor_FromEnumDef(&ret, e); |
|
RETURN_COPY_VALUE(&ret); |
|
} |
|
|
|
/* |
|
* FieldDescriptor::getContainingOneof() |
|
* |
|
* Returns the OneofDescriptor for this field, or null if it is not inside |
|
* a oneof. |
|
*/ |
|
PHP_METHOD(FieldDescriptor, getContainingOneof) { |
|
FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis()); |
|
const upb_OneofDef* o = upb_FieldDef_ContainingOneof(intern->fielddef); |
|
zval ret; |
|
|
|
if (!o) { |
|
RETURN_NULL(); |
|
} |
|
|
|
OneofDescriptor_FromOneofDef(&ret, o); |
|
RETURN_COPY_VALUE(&ret); |
|
} |
|
|
|
/* |
|
* FieldDescriptor::getRealContainingOneof() |
|
* |
|
* Returns the non-synthetic OneofDescriptor for this field, or null if it is |
|
* not inside a oneof. |
|
*/ |
|
PHP_METHOD(FieldDescriptor, getRealContainingOneof) { |
|
FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis()); |
|
const upb_OneofDef* o = upb_FieldDef_RealContainingOneof(intern->fielddef); |
|
zval ret; |
|
|
|
if (!o) { |
|
RETURN_NULL(); |
|
} |
|
|
|
OneofDescriptor_FromOneofDef(&ret, o); |
|
RETURN_COPY_VALUE(&ret); |
|
} |
|
|
|
/* |
|
* FieldDescriptor::getMessageType() |
|
* |
|
* Returns the Descriptor for this field, which must be a message. |
|
*/ |
|
PHP_METHOD(FieldDescriptor, getMessageType) { |
|
FieldDescriptor* intern = (FieldDescriptor*)Z_OBJ_P(getThis()); |
|
Descriptor* desc = Descriptor_GetFromFieldDef(intern->fielddef); |
|
|
|
if (!desc) { |
|
zend_throw_exception_ex( |
|
NULL, 0, "Cannot get message type for non-message field '%s'", |
|
upb_FieldDef_Name(intern->fielddef)); |
|
return; |
|
} |
|
|
|
RETURN_OBJ_COPY(&desc->std); |
|
} |
|
|
|
// clang-format off |
|
static zend_function_entry FieldDescriptor_methods[] = { |
|
PHP_ME(FieldDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(FieldDescriptor, getNumber, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(FieldDescriptor, getLabel, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(FieldDescriptor, getType, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(FieldDescriptor, isMap, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(FieldDescriptor, getEnumType, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(FieldDescriptor, getContainingOneof, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(FieldDescriptor, getRealContainingOneof, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(FieldDescriptor, getMessageType, arginfo_void, ZEND_ACC_PUBLIC) |
|
ZEND_FE_END |
|
}; |
|
// clang-format on |
|
|
|
// ----------------------------------------------------------------------------- |
|
// Descriptor |
|
// ----------------------------------------------------------------------------- |
|
|
|
zend_class_entry* Descriptor_class_entry; |
|
static zend_object_handlers Descriptor_object_handlers; |
|
|
|
static void Descriptor_destructor(zend_object* obj) { |
|
// We don't really need to do anything here, we don't allow this to be |
|
// collected before the end of the request. |
|
} |
|
|
|
static zend_class_entry* Descriptor_GetGeneratedClass(const upb_MessageDef* m) { |
|
for (int i = 0; i < 2; ++i) { |
|
char* classname = GetPhpClassname(upb_MessageDef_File(m), |
|
upb_MessageDef_FullName(m), (bool)i); |
|
zend_string* str = zend_string_init(classname, strlen(classname), 0); |
|
zend_class_entry* ce = zend_lookup_class(str); // May autoload the class. |
|
|
|
zend_string_release(str); |
|
free(classname); |
|
|
|
if (ce) { |
|
return ce; |
|
} |
|
} |
|
|
|
char* classname = GetPhpClassname(upb_MessageDef_File(m), |
|
upb_MessageDef_FullName(m), false); |
|
zend_error(E_ERROR, "Couldn't load generated class %s", classname); |
|
return NULL; |
|
} |
|
|
|
void Descriptor_FromMessageDef(zval* val, const upb_MessageDef* m) { |
|
if (m == NULL) { |
|
ZVAL_NULL(val); |
|
return; |
|
} |
|
|
|
if (!ObjCache_Get(m, val)) { |
|
zend_class_entry* ce = NULL; |
|
if (!upb_MessageDef_IsMapEntry(m)) { // Map entries don't have a class. |
|
ce = Descriptor_GetGeneratedClass(m); |
|
if (!ce) { |
|
ZVAL_NULL(val); |
|
return; |
|
} |
|
} |
|
Descriptor* ret = emalloc(sizeof(Descriptor)); |
|
zend_object_std_init(&ret->std, Descriptor_class_entry); |
|
ret->std.handlers = &Descriptor_object_handlers; |
|
ret->class_entry = ce; |
|
ret->msgdef = m; |
|
ObjCache_Add(m, &ret->std); |
|
Descriptors_Add(&ret->std); |
|
ZVAL_OBJ(val, &ret->std); |
|
} |
|
} |
|
|
|
static void Descriptor_FromClassEntry(zval* val, zend_class_entry* ce) { |
|
if (ce) { |
|
Descriptor_FromMessageDef(val, NameMap_GetMessage(ce)); |
|
} else { |
|
ZVAL_NULL(val); |
|
} |
|
} |
|
|
|
static Descriptor* Descriptor_GetFromZval(zval* val) { |
|
if (Z_TYPE_P(val) == IS_NULL) { |
|
return NULL; |
|
} else { |
|
zend_object* ret = Z_OBJ_P(val); |
|
zval_ptr_dtor(val); |
|
return (Descriptor*)ret; |
|
} |
|
} |
|
|
|
// C Functions from def.h ////////////////////////////////////////////////////// |
|
|
|
// These are documented in the header file. |
|
|
|
Descriptor* Descriptor_GetFromClassEntry(zend_class_entry* ce) { |
|
zval desc; |
|
Descriptor_FromClassEntry(&desc, ce); |
|
return Descriptor_GetFromZval(&desc); |
|
} |
|
|
|
Descriptor* Descriptor_GetFromMessageDef(const upb_MessageDef* m) { |
|
zval desc; |
|
Descriptor_FromMessageDef(&desc, m); |
|
return Descriptor_GetFromZval(&desc); |
|
} |
|
|
|
Descriptor* Descriptor_GetFromFieldDef(const upb_FieldDef* f) { |
|
return Descriptor_GetFromMessageDef(upb_FieldDef_MessageSubDef(f)); |
|
} |
|
|
|
/* |
|
* Descriptor::getPublicDescriptor() |
|
* |
|
* Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not |
|
* have two separate EnumDescriptor classes. We use a single class for both |
|
* the public and private descriptor. |
|
*/ |
|
PHP_METHOD(Descriptor, getPublicDescriptor) { RETURN_COPY(getThis()); } |
|
|
|
/* |
|
* Descriptor::getFullName() |
|
* |
|
* Returns the full name for this message type. |
|
*/ |
|
PHP_METHOD(Descriptor, getFullName) { |
|
Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis()); |
|
RETURN_STRING(upb_MessageDef_FullName(intern->msgdef)); |
|
} |
|
|
|
/* |
|
* Descriptor::getField() |
|
* |
|
* Returns a FieldDescriptor for the given index, which must be in the range |
|
* [0, getFieldCount()-1]. |
|
*/ |
|
PHP_METHOD(Descriptor, getField) { |
|
Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis()); |
|
int count = upb_MessageDef_FieldCount(intern->msgdef); |
|
zval ret; |
|
zend_long index; |
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { |
|
zend_error(E_USER_ERROR, "Expect integer for index.\n"); |
|
return; |
|
} |
|
|
|
if (index < 0 || index >= count) { |
|
zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); |
|
return; |
|
} |
|
|
|
FieldDescriptor_FromFieldDef(&ret, |
|
upb_MessageDef_Field(intern->msgdef, index)); |
|
RETURN_COPY_VALUE(&ret); |
|
} |
|
|
|
/* |
|
* Descriptor::getFieldCount() |
|
* |
|
* Returns the number of fields in this message. |
|
*/ |
|
PHP_METHOD(Descriptor, getFieldCount) { |
|
Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis()); |
|
RETURN_LONG(upb_MessageDef_FieldCount(intern->msgdef)); |
|
} |
|
|
|
/* |
|
* Descriptor::getOneofDecl() |
|
* |
|
* Returns a OneofDescriptor for the given index, which must be in the range |
|
* [0, getOneofDeclCount()]. |
|
*/ |
|
PHP_METHOD(Descriptor, getOneofDecl) { |
|
Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis()); |
|
zend_long index; |
|
zval ret; |
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { |
|
zend_error(E_USER_ERROR, "Expect integer for index.\n"); |
|
return; |
|
} |
|
|
|
if (index < 0 || index >= upb_MessageDef_OneofCount(intern->msgdef)) { |
|
zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); |
|
return; |
|
} |
|
|
|
OneofDescriptor_FromOneofDef(&ret, |
|
upb_MessageDef_Oneof(intern->msgdef, index)); |
|
RETURN_COPY_VALUE(&ret); |
|
} |
|
|
|
/* |
|
* Descriptor::getOneofDeclCount() |
|
* |
|
* Returns the number of oneofs in this message. |
|
*/ |
|
PHP_METHOD(Descriptor, getOneofDeclCount) { |
|
Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis()); |
|
RETURN_LONG(upb_MessageDef_OneofCount(intern->msgdef)); |
|
} |
|
|
|
/* |
|
* Descriptor::getClass() |
|
* |
|
* Returns the name of the PHP class for this message. |
|
*/ |
|
PHP_METHOD(Descriptor, getClass) { |
|
Descriptor* intern = (Descriptor*)Z_OBJ_P(getThis()); |
|
const char* classname = ZSTR_VAL(intern->class_entry->name); |
|
RETURN_STRING(classname); |
|
} |
|
|
|
// clang-format off |
|
static zend_function_entry Descriptor_methods[] = { |
|
PHP_ME(Descriptor, getClass, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(Descriptor, getFullName, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(Descriptor, getField, arginfo_getByIndex, ZEND_ACC_PUBLIC) |
|
PHP_ME(Descriptor, getFieldCount, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(Descriptor, getOneofDecl, arginfo_getByIndex, ZEND_ACC_PUBLIC) |
|
PHP_ME(Descriptor, getOneofDeclCount, arginfo_void, ZEND_ACC_PUBLIC) |
|
PHP_ME(Descriptor, getPublicDescriptor, arginfo_void, ZEND_ACC_PUBLIC) |
|
ZEND_FE_END |
|
}; |
|
// clang-format on |
|
|
|
// ----------------------------------------------------------------------------- |
|
// DescriptorPool |
|
// ----------------------------------------------------------------------------- |
|
|
|
typedef struct DescriptorPool { |
|
zend_object std; |
|
upb_DefPool* symtab; |
|
} DescriptorPool; |
|
|
|
zend_class_entry* DescriptorPool_class_entry; |
|
static zend_object_handlers DescriptorPool_object_handlers; |
|
|
|
static DescriptorPool* GetPool(const zval* this_ptr) { |
|
return (DescriptorPool*)Z_OBJ_P(this_ptr); |
|
} |
|
|
|
/** |
|
* Object handler to free an DescriptorPool. |
|
*/ |
|
static void DescriptorPool_destructor(zend_object* obj) { |
|
DescriptorPool* intern = (DescriptorPool*)obj; |
|
|
|
// We can't free our underlying symtab here, because user code may create |
|
// messages from destructors that will refer to it. The symtab will be freed |
|
// by our RSHUTDOWN() handler in protobuf.c |
|
|
|
zend_object_std_dtor(&intern->std); |
|
} |
|
|
|
void DescriptorPool_CreateWithSymbolTable(zval* zv, upb_DefPool* symtab) { |
|
DescriptorPool* intern = emalloc(sizeof(DescriptorPool)); |
|
zend_object_std_init(&intern->std, DescriptorPool_class_entry); |
|
intern->std.handlers = &DescriptorPool_object_handlers; |
|
intern->symtab = symtab; |
|
|
|
ZVAL_OBJ(zv, &intern->std); |
|
} |
|
|
|
upb_DefPool* DescriptorPool_GetSymbolTable() { return get_global_symtab(); } |
|
|
|
/* |
|
* DescriptorPool::getGeneratedPool() |
|
* |
|
* Returns the generated DescriptorPool. |
|
*/ |
|
PHP_METHOD(DescriptorPool, getGeneratedPool) { |
|
DescriptorPool_CreateWithSymbolTable(return_value, get_global_symtab()); |
|
} |
|
|
|
/* |
|
* DescriptorPool::getDescriptorByClassName() |
|
* |
|
* Returns a Descriptor object for the given PHP class name. |
|
*/ |
|
PHP_METHOD(DescriptorPool, getDescriptorByClassName) { |
|
char* classname = NULL; |
|
zend_long classname_len; |
|
zend_class_entry* ce; |
|
zend_string* str; |
|
zval ret; |
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) == |
|
FAILURE) { |
|
return; |
|
} |
|
|
|
str = zend_string_init(classname, strlen(classname), 0); |
|
ce = zend_lookup_class(str); // May autoload the class. |
|
zend_string_release(str); |
|
|
|
if (!ce) { |
|
RETURN_NULL(); |
|
} |
|
|
|
Descriptor_FromClassEntry(&ret, ce); |
|
RETURN_COPY_VALUE(&ret); |
|
} |
|
|
|
/* |
|
* DescriptorPool::getEnumDescriptorByClassName() |
|
* |
|
* Returns a EnumDescriptor object for the given PHP class name. |
|
*/ |
|
PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) { |
|
char* classname = NULL; |
|
zend_long classname_len; |
|
zend_class_entry* ce; |
|
zend_string* str; |
|
zval ret; |
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) == |
|
FAILURE) { |
|
return; |
|
} |
|
|
|
str = zend_string_init(classname, strlen(classname), 0); |
|
ce = zend_lookup_class(str); // May autoload the class. |
|
zend_string_release(str); |
|
|
|
if (!ce) { |
|
RETURN_NULL(); |
|
} |
|
|
|
EnumDescriptor_FromClassEntry(&ret, ce); |
|
RETURN_COPY_VALUE(&ret); |
|
} |
|
|
|
/* |
|
* DescriptorPool::getEnumDescriptorByProtoName() |
|
* |
|
* Returns a Descriptor object for the given protobuf message name. |
|
*/ |
|
PHP_METHOD(DescriptorPool, getDescriptorByProtoName) { |
|
DescriptorPool* intern = GetPool(getThis()); |
|
char* protoname = NULL; |
|
zend_long protoname_len; |
|
const upb_MessageDef* m; |
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &protoname, &protoname_len) == |
|
FAILURE) { |
|
return; |
|
} |
|
|
|
if (*protoname == '.') protoname++; |
|
|
|
m = upb_DefPool_FindMessageByName(intern->symtab, protoname); |
|
|
|
if (m) { |
|
RETURN_OBJ_COPY(&Descriptor_GetFromMessageDef(m)->std); |
|
} else { |
|
RETURN_NULL(); |
|
} |
|
} |
|
|
|
/* |
|
* depends_on_descriptor() |
|
* |
|
* Returns true if this FileDescriptorProto depends on descriptor.proto. |
|
*/ |
|
bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) { |
|
const upb_StringView* deps; |
|
upb_StringView name = |
|
upb_StringView_FromString("google/protobuf/descriptor.proto"); |
|
size_t i, n; |
|
|
|
deps = google_protobuf_FileDescriptorProto_dependency(file, &n); |
|
for (i = 0; i < n; i++) { |
|
if (upb_StringView_IsEqual(deps[i], name)) { |
|
return true; |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
static void add_message_name_mappings(const upb_MessageDef* message) { |
|
NameMap_AddMessage(message); |
|
int msg_n = upb_MessageDef_NestedMessageCount(message); |
|
for (int i = 0; i < msg_n; i++) { |
|
add_message_name_mappings(upb_MessageDef_NestedMessage(message, i)); |
|
} |
|
int enum_n = upb_MessageDef_NestedEnumCount(message); |
|
for (int i = 0; i < enum_n; i++) { |
|
NameMap_AddEnum(upb_MessageDef_NestedEnum(message, i)); |
|
} |
|
} |
|
|
|
/* |
|
* add_name_mappings() |
|
* |
|
* Adds the messages and enums in this file to the NameMap. |
|
*/ |
|
static void add_name_mappings(const upb_FileDef* file) { |
|
for (int i = 0; i < upb_FileDef_TopLevelMessageCount(file); i++) { |
|
add_message_name_mappings(upb_FileDef_TopLevelMessage(file, i)); |
|
} |
|
|
|
for (int i = 0; i < upb_FileDef_TopLevelEnumCount(file); i++) { |
|
NameMap_AddEnum(upb_FileDef_TopLevelEnum(file, i)); |
|
} |
|
} |
|
|
|
static void add_descriptor(upb_DefPool* symtab, |
|
const google_protobuf_FileDescriptorProto* file) { |
|
upb_StringView name = google_protobuf_FileDescriptorProto_name(file); |
|
upb_Status status; |
|
const upb_FileDef* file_def; |
|
upb_Status_Clear(&status); |
|
|
|
if (upb_DefPool_FindFileByNameWithSize(symtab, name.data, name.size)) { |
|
// Already added. |
|
// TODO: Re-enable this warning when aggregate metadata is |
|
// deprecated. |
|
// zend_error(E_USER_WARNING, |
|
// "proto descriptor was previously loaded (included in multiple |
|
// " "metadata bundles?): " UPB_STRINGVIEW_FORMAT, |
|
// UPB_STRINGVIEW_ARGS(name)); |
|
return; |
|
} |
|
|
|
// The PHP code generator currently special-cases descriptor.proto. It |
|
// doesn't add it as a dependency even if the proto file actually does |
|
// depend on it. |
|
if (depends_on_descriptor(file)) { |
|
google_protobuf_FileDescriptorProto_getmsgdef(symtab); |
|
} |
|
|
|
file_def = upb_DefPool_AddFile(symtab, file, &status); |
|
CheckUpbStatus(&status, "Unable to load descriptor"); |
|
add_name_mappings(file_def); |
|
} |
|
|
|
/* |
|
* add_descriptor() |
|
* |
|
* Adds the given descriptor data to this DescriptorPool. |
|
*/ |
|
static void add_descriptor_set(upb_DefPool* symtab, const char* data, |
|
int data_len, upb_Arena* arena) { |
|
size_t i, n; |
|
google_protobuf_FileDescriptorSet* set; |
|
const google_protobuf_FileDescriptorProto* const* files; |
|
|
|
set = google_protobuf_FileDescriptorSet_parse(data, data_len, arena); |
|
|
|
if (!set) { |
|
zend_error(E_ERROR, "Failed to parse binary descriptor\n"); |
|
return; |
|
} |
|
|
|
files = google_protobuf_FileDescriptorSet_file(set, &n); |
|
|
|
for (i = 0; i < n; i++) { |
|
const google_protobuf_FileDescriptorProto* file = files[i]; |
|
add_descriptor(symtab, file); |
|
} |
|
} |
|
|
|
bool DescriptorPool_HasFile(const char* filename) { |
|
return upb_DefPool_FindFileByName(get_global_symtab(), filename) != NULL; |
|
} |
|
|
|
void DescriptorPool_AddDescriptor(const char* filename, const char* data, |
|
int size) { |
|
upb_Arena* arena = upb_Arena_New(); |
|
const google_protobuf_FileDescriptorProto* file = |
|
google_protobuf_FileDescriptorProto_parse(data, size, arena); |
|
|
|
if (!file) { |
|
zend_error(E_ERROR, "Failed to parse binary descriptor for %s\n", filename); |
|
return; |
|
} |
|
|
|
add_descriptor(get_global_symtab(), file); |
|
upb_Arena_Free(arena); |
|
} |
|
|
|
/* |
|
* DescriptorPool::internalAddGeneratedFile() |
|
* |
|
* Adds the given descriptor data to this DescriptorPool. |
|
*/ |
|
PHP_METHOD(DescriptorPool, internalAddGeneratedFile) { |
|
DescriptorPool* intern = GetPool(getThis()); |
|
char* data = NULL; |
|
zend_long data_len; |
|
zend_bool use_nested_submsg = false; |
|
upb_Arena* arena; |
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len, |
|
&use_nested_submsg) != SUCCESS) { |
|
return; |
|
} |
|
|
|
arena = upb_Arena_New(); |
|
add_descriptor_set(intern->symtab, data, data_len, arena); |
|
upb_Arena_Free(arena); |
|
} |
|
|
|
// clang-format off |
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_lookupByName, 0, 0, 1) |
|
ZEND_ARG_INFO(0, name) |
|
ZEND_END_ARG_INFO() |
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_addgeneratedfile, 0, 0, 2) |
|
ZEND_ARG_INFO(0, data) |
|
ZEND_ARG_INFO(0, data_len) |
|
ZEND_END_ARG_INFO() |
|
|
|
static zend_function_entry DescriptorPool_methods[] = { |
|
PHP_ME(DescriptorPool, getGeneratedPool, arginfo_void, |
|
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) |
|
PHP_ME(DescriptorPool, getDescriptorByClassName, arginfo_lookupByName, ZEND_ACC_PUBLIC) |
|
PHP_ME(DescriptorPool, getDescriptorByProtoName, arginfo_lookupByName, ZEND_ACC_PUBLIC) |
|
PHP_ME(DescriptorPool, getEnumDescriptorByClassName, arginfo_lookupByName, ZEND_ACC_PUBLIC) |
|
PHP_ME(DescriptorPool, internalAddGeneratedFile, arginfo_addgeneratedfile, ZEND_ACC_PUBLIC) |
|
ZEND_FE_END |
|
}; |
|
// clang-format on |
|
|
|
// ----------------------------------------------------------------------------- |
|
// InternalDescriptorPool |
|
// ----------------------------------------------------------------------------- |
|
|
|
// For the C extension, Google\Protobuf\Internal\DescriptorPool is not a |
|
// separate instantiable object, it just returns a |
|
// Google\Protobuf\DescriptorPool. |
|
|
|
zend_class_entry* InternalDescriptorPool_class_entry; |
|
|
|
/* |
|
* InternalDescriptorPool::getGeneratedPool() |
|
* |
|
* Returns the generated DescriptorPool. Note that this is identical to |
|
* DescriptorPool::getGeneratedPool(), and in fact returns a DescriptorPool |
|
* instance. |
|
*/ |
|
PHP_METHOD(InternalDescriptorPool, getGeneratedPool) { |
|
DescriptorPool_CreateWithSymbolTable(return_value, get_global_symtab()); |
|
} |
|
|
|
// clang-format off |
|
static zend_function_entry InternalDescriptorPool_methods[] = { |
|
PHP_ME(InternalDescriptorPool, getGeneratedPool, arginfo_void, |
|
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) |
|
ZEND_FE_END |
|
}; |
|
// clang-format on |
|
|
|
// ----------------------------------------------------------------------------- |
|
// GPBType |
|
// ----------------------------------------------------------------------------- |
|
|
|
zend_class_entry* gpb_type_type; |
|
|
|
static zend_function_entry gpb_type_methods[] = {ZEND_FE_END}; |
|
|
|
// ----------------------------------------------------------------------------- |
|
// Module Init |
|
// ----------------------------------------------------------------------------- |
|
|
|
void Def_ModuleInit() { |
|
zend_class_entry tmp_ce; |
|
zend_object_handlers* h; |
|
|
|
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\OneofDescriptor", |
|
OneofDescriptor_methods); |
|
OneofDescriptor_class_entry = zend_register_internal_class(&tmp_ce); |
|
OneofDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; |
|
OneofDescriptor_class_entry->create_object = CreateHandler_ReturnNull; |
|
h = &OneofDescriptor_object_handlers; |
|
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); |
|
h->dtor_obj = &OneofDescriptor_destructor; |
|
|
|
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValueDescriptor", |
|
EnumValueDescriptor_methods); |
|
EnumValueDescriptor_class_entry = zend_register_internal_class(&tmp_ce); |
|
EnumValueDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; |
|
EnumValueDescriptor_class_entry->create_object = CreateHandler_ReturnNull; |
|
h = &EnumValueDescriptor_object_handlers; |
|
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); |
|
|
|
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumDescriptor", |
|
EnumDescriptor_methods); |
|
EnumDescriptor_class_entry = zend_register_internal_class(&tmp_ce); |
|
EnumDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; |
|
EnumDescriptor_class_entry->create_object = CreateHandler_ReturnNull; |
|
h = &EnumDescriptor_object_handlers; |
|
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); |
|
h->dtor_obj = &EnumDescriptor_destructor; |
|
|
|
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Descriptor", Descriptor_methods); |
|
|
|
Descriptor_class_entry = zend_register_internal_class(&tmp_ce); |
|
Descriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; |
|
Descriptor_class_entry->create_object = CreateHandler_ReturnNull; |
|
h = &Descriptor_object_handlers; |
|
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); |
|
h->dtor_obj = Descriptor_destructor; |
|
|
|
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldDescriptor", |
|
FieldDescriptor_methods); |
|
FieldDescriptor_class_entry = zend_register_internal_class(&tmp_ce); |
|
FieldDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; |
|
FieldDescriptor_class_entry->create_object = CreateHandler_ReturnNull; |
|
h = &FieldDescriptor_object_handlers; |
|
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); |
|
h->dtor_obj = &FieldDescriptor_destructor; |
|
|
|
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\DescriptorPool", |
|
DescriptorPool_methods); |
|
DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce); |
|
DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL; |
|
DescriptorPool_class_entry->create_object = CreateHandler_ReturnNull; |
|
h = &DescriptorPool_object_handlers; |
|
memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); |
|
h->dtor_obj = DescriptorPool_destructor; |
|
|
|
INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool", |
|
InternalDescriptorPool_methods); |
|
InternalDescriptorPool_class_entry = zend_register_internal_class(&tmp_ce); |
|
|
|
// GPBType. |
|
#define STR(str) (str), strlen(str) |
|
zend_class_entry class_type; |
|
INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType", |
|
gpb_type_methods); |
|
gpb_type_type = zend_register_internal_class(&class_type); |
|
zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1); |
|
zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2); |
|
zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3); |
|
zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4); |
|
zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5); |
|
zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6); |
|
zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7); |
|
zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8); |
|
zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9); |
|
zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10); |
|
zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11); |
|
zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12); |
|
zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13); |
|
zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14); |
|
zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"), 15); |
|
zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"), 16); |
|
zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17); |
|
zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18); |
|
#undef STR |
|
}
|
|
|