|
@@ -148,6 +148,11 @@ static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) {
|
|
|
return hd_ofs;
|
|
|
}
|
|
|
|
|
|
+typedef struct {
|
|
|
+ void* closure;
|
|
|
+ stringsink sink;
|
|
|
+} stringfields_parseframe_t;
|
|
|
+
|
|
|
typedef size_t (*encodeunknown_handlerfunc)(void* _sink, const void* hd,
|
|
|
const char* ptr, size_t len,
|
|
|
const upb_bufhandle* handle);
|
|
@@ -245,46 +250,41 @@ DEFINE_APPEND_HANDLER(int64, int64_t)
|
|
|
DEFINE_APPEND_HANDLER(uint64, uint64_t)
|
|
|
DEFINE_APPEND_HANDLER(double, double)
|
|
|
|
|
|
-// Appends a string to a repeated field.
|
|
|
+// Appends a string or 'bytes' string to a repeated field.
|
|
|
static void* appendstr_handler(void *closure,
|
|
|
const void *hd,
|
|
|
size_t size_hint) {
|
|
|
- zval* array = (zval*)closure;
|
|
|
- TSRMLS_FETCH();
|
|
|
- RepeatedField* intern = UNBOX(RepeatedField, array);
|
|
|
+ UPB_UNUSED(hd);
|
|
|
|
|
|
-#if PHP_MAJOR_VERSION < 7
|
|
|
- zval* str;
|
|
|
- MAKE_STD_ZVAL(str);
|
|
|
- PHP_PROTO_ZVAL_STRING(str, "", 1);
|
|
|
- repeated_field_push_native(intern, &str);
|
|
|
- return (void*)str;
|
|
|
-#else
|
|
|
- zend_string* str = zend_string_init("", 0, 1);
|
|
|
- repeated_field_push_native(intern, &str);
|
|
|
- return intern;
|
|
|
-#endif
|
|
|
+ stringfields_parseframe_t* frame =
|
|
|
+ (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
|
|
|
+ frame->closure = closure;
|
|
|
+ stringsink_init(&frame->sink);
|
|
|
+
|
|
|
+ return frame;
|
|
|
}
|
|
|
|
|
|
-// Appends a 'bytes' string to a repeated field.
|
|
|
-static void* appendbytes_handler(void *closure,
|
|
|
- const void *hd,
|
|
|
- size_t size_hint) {
|
|
|
- zval* array = (zval*)closure;
|
|
|
+static bool appendstr_end_handler(void *closure, const void *hd) {
|
|
|
+ stringfields_parseframe_t* frame = closure;
|
|
|
+
|
|
|
+ zval* array = (zval*)frame->closure;
|
|
|
TSRMLS_FETCH();
|
|
|
RepeatedField* intern = UNBOX(RepeatedField, array);
|
|
|
|
|
|
#if PHP_MAJOR_VERSION < 7
|
|
|
zval* str;
|
|
|
MAKE_STD_ZVAL(str);
|
|
|
- PHP_PROTO_ZVAL_STRING(str, "", 1);
|
|
|
+ PHP_PROTO_ZVAL_STRINGL(str, frame->sink.ptr, frame->sink.len, 1);
|
|
|
repeated_field_push_native(intern, &str);
|
|
|
- return (void*)str;
|
|
|
#else
|
|
|
- zend_string* str = zend_string_init("", 0, 1);
|
|
|
+ zend_string* str = zend_string_init(frame->sink.ptr, frame->sink.len, 1);
|
|
|
repeated_field_push_native(intern, &str);
|
|
|
- return intern;
|
|
|
#endif
|
|
|
+
|
|
|
+ stringsink_uninit(&frame->sink);
|
|
|
+ free(frame);
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
// Handlers that append primitive values to a repeated field.
|
|
@@ -326,64 +326,76 @@ static void *empty_php_string(zval* value_ptr) {
|
|
|
return value_ptr;
|
|
|
}
|
|
|
#endif
|
|
|
+#if PHP_MAJOR_VERSION < 7
|
|
|
+static void *empty_php_string2(zval** value_ptr) {
|
|
|
+ SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
|
|
|
+ if (Z_TYPE_PP(value_ptr) == IS_STRING &&
|
|
|
+ !IS_INTERNED(Z_STRVAL_PP(value_ptr))) {
|
|
|
+ FREE(Z_STRVAL_PP(value_ptr));
|
|
|
+ }
|
|
|
+ ZVAL_EMPTY_STRING(*value_ptr);
|
|
|
+ return (void*)(*value_ptr);
|
|
|
+}
|
|
|
+static void new_php_string(zval** value_ptr, const char* str, size_t len) {
|
|
|
+ SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
|
|
|
+ if (Z_TYPE_PP(value_ptr) == IS_STRING &&
|
|
|
+ !IS_INTERNED(Z_STRVAL_PP(value_ptr))) {
|
|
|
+ FREE(Z_STRVAL_PP(value_ptr));
|
|
|
+ }
|
|
|
+ ZVAL_EMPTY_STRING(*value_ptr);
|
|
|
+ ZVAL_STRINGL(*value_ptr, str, len, 1);
|
|
|
+}
|
|
|
+#else
|
|
|
+static void *empty_php_string2(zval* value_ptr) {
|
|
|
+ if (Z_TYPE_P(value_ptr) == IS_STRING) {
|
|
|
+ zend_string_release(Z_STR_P(value_ptr));
|
|
|
+ }
|
|
|
+ ZVAL_EMPTY_STRING(value_ptr);
|
|
|
+ return value_ptr;
|
|
|
+}
|
|
|
+static void new_php_string(zval* value_ptr, const char* str, size_t len) {
|
|
|
+ if (Z_TYPE_P(value_ptr) == IS_STRING) {
|
|
|
+ zend_string_release(Z_STR_P(value_ptr));
|
|
|
+ }
|
|
|
+ ZVAL_NEW_STR(value_ptr, zend_string_init(str, len, 0));
|
|
|
+}
|
|
|
+#endif
|
|
|
|
|
|
-// Sets a non-repeated string field in a message.
|
|
|
+// Sets a non-repeated string/bytes field in a message.
|
|
|
static void* str_handler(void *closure,
|
|
|
const void *hd,
|
|
|
size_t size_hint) {
|
|
|
- MessageHeader* msg = closure;
|
|
|
- const size_t *ofs = hd;
|
|
|
- return empty_php_string(DEREF(message_data(msg), *ofs, CACHED_VALUE*));
|
|
|
+ UPB_UNUSED(hd);
|
|
|
+
|
|
|
+ stringfields_parseframe_t* frame =
|
|
|
+ (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
|
|
|
+ frame->closure = closure;
|
|
|
+ stringsink_init(&frame->sink);
|
|
|
+
|
|
|
+ return frame;
|
|
|
}
|
|
|
|
|
|
-// Sets a non-repeated 'bytes' field in a message.
|
|
|
-static void* bytes_handler(void *closure,
|
|
|
- const void *hd,
|
|
|
- size_t size_hint) {
|
|
|
- MessageHeader* msg = closure;
|
|
|
+static bool str_end_handler(void *closure, const void *hd) {
|
|
|
+ stringfields_parseframe_t* frame = closure;
|
|
|
const size_t *ofs = hd;
|
|
|
- return empty_php_string(DEREF(message_data(msg), *ofs, CACHED_VALUE*));
|
|
|
+ MessageHeader* msg = (MessageHeader*)frame->closure;
|
|
|
+
|
|
|
+ new_php_string(DEREF(message_data(msg), *ofs, CACHED_VALUE*),
|
|
|
+ frame->sink.ptr, frame->sink.len);
|
|
|
+
|
|
|
+ stringsink_uninit(&frame->sink);
|
|
|
+ free(frame);
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
static size_t stringdata_handler(void* closure, const void* hd,
|
|
|
const char* str, size_t len,
|
|
|
const upb_bufhandle* handle) {
|
|
|
- zval* php_str = (zval*)closure;
|
|
|
-#if PHP_MAJOR_VERSION < 7
|
|
|
- // Oneof string/bytes fields may have NULL initial value, which doesn't need
|
|
|
- // to be freed.
|
|
|
- if (Z_TYPE_P(php_str) == IS_STRING && !IS_INTERNED(Z_STRVAL_P(php_str))) {
|
|
|
- FREE(Z_STRVAL_P(php_str));
|
|
|
- }
|
|
|
- ZVAL_STRINGL(php_str, str, len, 1);
|
|
|
-#else
|
|
|
- if (Z_TYPE_P(php_str) == IS_STRING) {
|
|
|
- zend_string_release(Z_STR_P(php_str));
|
|
|
- }
|
|
|
- ZVAL_NEW_STR(php_str, zend_string_init(str, len, 0));
|
|
|
-#endif
|
|
|
- return len;
|
|
|
+ stringfields_parseframe_t* frame = closure;
|
|
|
+ return stringsink_string(&frame->sink, hd, str, len, handle);
|
|
|
}
|
|
|
|
|
|
-#if PHP_MAJOR_VERSION >= 7
|
|
|
-static size_t zendstringdata_handler(void* closure, const void* hd,
|
|
|
- const char* str, size_t len,
|
|
|
- const upb_bufhandle* handle) {
|
|
|
- RepeatedField* intern = (RepeatedField*)closure;
|
|
|
-
|
|
|
- unsigned char memory[NATIVE_SLOT_MAX_SIZE];
|
|
|
- memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
|
|
|
- *(zend_string**)memory = zend_string_init(str, len, 0);
|
|
|
-
|
|
|
- HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
|
|
|
- int index = zend_hash_num_elements(ht) - 1;
|
|
|
- php_proto_zend_hash_index_update_mem(
|
|
|
- ht, index, memory, sizeof(zend_string*), NULL);
|
|
|
-
|
|
|
- return len;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
// Appends a submessage to a repeated field.
|
|
|
static void *appendsubmsg_handler(void *closure, const void *hd) {
|
|
|
zval* array = (zval*)closure;
|
|
@@ -744,13 +756,38 @@ static void *oneofbytes_handler(void *closure,
|
|
|
return empty_php_string(DEREF(
|
|
|
message_data(msg), oneofdata->ofs, CACHED_VALUE*));
|
|
|
}
|
|
|
+static bool oneofstr_end_handler(void *closure, const void *hd) {
|
|
|
+ stringfields_parseframe_t* frame = closure;
|
|
|
+ MessageHeader* msg = (MessageHeader*)frame->closure;
|
|
|
+ const oneof_handlerdata_t *oneofdata = hd;
|
|
|
+
|
|
|
+ oneof_cleanup(msg, oneofdata);
|
|
|
+
|
|
|
+ DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
|
|
|
+ oneofdata->oneof_case_num;
|
|
|
+ DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
|
|
|
+ OBJ_PROP(&msg->std, oneofdata->property_ofs);
|
|
|
+
|
|
|
+ new_php_string(DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*),
|
|
|
+ frame->sink.ptr, frame->sink.len);
|
|
|
+
|
|
|
+ stringsink_uninit(&frame->sink);
|
|
|
+ free(frame);
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
|
|
|
static void *oneofstr_handler(void *closure,
|
|
|
const void *hd,
|
|
|
size_t size_hint) {
|
|
|
- // TODO(teboring): Add it back.
|
|
|
- // rb_enc_associate(str, kRubyString8bitEncoding);
|
|
|
- return oneofbytes_handler(closure, hd, size_hint);
|
|
|
+ UPB_UNUSED(hd);
|
|
|
+
|
|
|
+ stringfields_parseframe_t* frame =
|
|
|
+ (stringfields_parseframe_t*)malloc(sizeof(stringfields_parseframe_t));
|
|
|
+ frame->closure = closure;
|
|
|
+ stringsink_init(&frame->sink);
|
|
|
+
|
|
|
+ return frame;
|
|
|
}
|
|
|
|
|
|
// Handler for a submessage field in a oneof.
|
|
@@ -822,15 +859,9 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|
|
|
|
|
case UPB_TYPE_STRING:
|
|
|
case UPB_TYPE_BYTES: {
|
|
|
- bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
|
|
|
- upb_handlers_setstartstr(h, f, is_bytes ?
|
|
|
- appendbytes_handler : appendstr_handler,
|
|
|
- NULL);
|
|
|
-#if PHP_MAJOR_VERSION < 7
|
|
|
+ upb_handlers_setstartstr(h, f, appendstr_handler, NULL);
|
|
|
upb_handlers_setstring(h, f, stringdata_handler, NULL);
|
|
|
-#else
|
|
|
- upb_handlers_setstring(h, f, zendstringdata_handler, NULL);
|
|
|
-#endif
|
|
|
+ upb_handlers_setendstr(h, f, appendstr_end_handler, &attr);
|
|
|
break;
|
|
|
}
|
|
|
case UPB_TYPE_MESSAGE: {
|
|
@@ -870,13 +901,11 @@ static void add_handlers_for_singular_field(upb_handlers *h,
|
|
|
|
|
|
case UPB_TYPE_STRING:
|
|
|
case UPB_TYPE_BYTES: {
|
|
|
- bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
|
|
|
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
|
|
upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
|
|
|
- upb_handlers_setstartstr(h, f,
|
|
|
- is_bytes ? bytes_handler : str_handler,
|
|
|
- &attr);
|
|
|
+ upb_handlers_setstartstr(h, f, str_handler, &attr);
|
|
|
upb_handlers_setstring(h, f, stringdata_handler, &attr);
|
|
|
+ upb_handlers_setendstr(h, f, str_end_handler, &attr);
|
|
|
upb_handlerattr_uninit(&attr);
|
|
|
break;
|
|
|
}
|
|
@@ -958,11 +987,9 @@ static void add_handlers_for_oneof_field(upb_handlers *h,
|
|
|
|
|
|
case UPB_TYPE_STRING:
|
|
|
case UPB_TYPE_BYTES: {
|
|
|
- bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
|
|
|
- upb_handlers_setstartstr(h, f, is_bytes ?
|
|
|
- oneofbytes_handler : oneofstr_handler,
|
|
|
- &attr);
|
|
|
+ upb_handlers_setstartstr(h, f, oneofstr_handler, &attr);
|
|
|
upb_handlers_setstring(h, f, stringdata_handler, NULL);
|
|
|
+ upb_handlers_setendstr(h, f, oneofstr_end_handler, &attr);
|
|
|
break;
|
|
|
}
|
|
|
case UPB_TYPE_MESSAGE: {
|