storage.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #include <stdint.h>
  31. #include <protobuf.h>
  32. #include <Zend/zend.h>
  33. #include "utf8.h"
  34. // -----------------------------------------------------------------------------
  35. // Native slot storage.
  36. // -----------------------------------------------------------------------------
  37. #define DEREF(memory, type) *(type*)(memory)
  38. size_t native_slot_size(upb_fieldtype_t type) {
  39. switch (type) {
  40. case UPB_TYPE_FLOAT: return 4;
  41. case UPB_TYPE_DOUBLE: return 8;
  42. case UPB_TYPE_BOOL: return 1;
  43. case UPB_TYPE_STRING: return sizeof(void*);
  44. case UPB_TYPE_BYTES: return sizeof(void*);
  45. case UPB_TYPE_MESSAGE: return sizeof(void*);
  46. case UPB_TYPE_ENUM: return 4;
  47. case UPB_TYPE_INT32: return 4;
  48. case UPB_TYPE_INT64: return 8;
  49. case UPB_TYPE_UINT32: return 4;
  50. case UPB_TYPE_UINT64: return 8;
  51. default: return 0;
  52. }
  53. }
  54. bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
  55. void* memory, zval* value TSRMLS_DC) {
  56. switch (type) {
  57. case UPB_TYPE_STRING:
  58. case UPB_TYPE_BYTES: {
  59. if (!protobuf_convert_to_string(value)) {
  60. return false;
  61. }
  62. if (type == UPB_TYPE_STRING &&
  63. !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) {
  64. zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
  65. return false;
  66. }
  67. if (*(zval**)memory != NULL) {
  68. REPLACE_ZVAL_VALUE((zval**)memory, value, 1);
  69. } else {
  70. // Handles repeated/map string field. Memory provided by
  71. // RepeatedField/Map is not initialized.
  72. MAKE_STD_ZVAL(DEREF(memory, zval*));
  73. ZVAL_STRINGL(DEREF(memory, zval*), Z_STRVAL_P(value), Z_STRLEN_P(value),
  74. 1);
  75. }
  76. break;
  77. }
  78. case UPB_TYPE_MESSAGE: {
  79. if (Z_TYPE_P(value) != IS_OBJECT && Z_TYPE_P(value) != IS_NULL) {
  80. zend_error(E_USER_ERROR, "Given value is not message.");
  81. return false;
  82. }
  83. if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) {
  84. zend_error(E_USER_ERROR, "Given message does not have correct class.");
  85. return false;
  86. }
  87. if (EXPECTED(DEREF(memory, zval*) != value)) {
  88. if (DEREF(memory, zval*) != NULL) {
  89. zval_ptr_dtor((zval**)memory);
  90. }
  91. DEREF(memory, zval*) = value;
  92. Z_ADDREF_P(value);
  93. }
  94. break;
  95. }
  96. #define CASE_TYPE(upb_type, type, c_type, php_type) \
  97. case UPB_TYPE_##upb_type: { \
  98. c_type type##_value; \
  99. if (protobuf_convert_to_##type(value, &type##_value)) { \
  100. DEREF(memory, c_type) = type##_value; \
  101. } \
  102. break; \
  103. }
  104. CASE_TYPE(INT32, int32, int32_t, LONG)
  105. CASE_TYPE(UINT32, uint32, uint32_t, LONG)
  106. CASE_TYPE(ENUM, int32, int32_t, LONG)
  107. CASE_TYPE(INT64, int64, int64_t, LONG)
  108. CASE_TYPE(UINT64, uint64, uint64_t, LONG)
  109. CASE_TYPE(FLOAT, float, float, DOUBLE)
  110. CASE_TYPE(DOUBLE, double, double, DOUBLE)
  111. CASE_TYPE(BOOL, bool, int8_t, BOOL)
  112. #undef CASE_TYPE
  113. default:
  114. break;
  115. }
  116. return true;
  117. }
  118. void native_slot_init(upb_fieldtype_t type, void* memory, zval** cache) {
  119. zval* tmp = NULL;
  120. switch (type) {
  121. case UPB_TYPE_FLOAT:
  122. DEREF(memory, float) = 0.0;
  123. break;
  124. case UPB_TYPE_DOUBLE:
  125. DEREF(memory, double) = 0.0;
  126. break;
  127. case UPB_TYPE_BOOL:
  128. DEREF(memory, int8_t) = 0;
  129. break;
  130. case UPB_TYPE_STRING:
  131. case UPB_TYPE_BYTES:
  132. case UPB_TYPE_MESSAGE:
  133. DEREF(memory, zval**) = cache;
  134. break;
  135. case UPB_TYPE_ENUM:
  136. case UPB_TYPE_INT32:
  137. DEREF(memory, int32_t) = 0;
  138. break;
  139. case UPB_TYPE_INT64:
  140. DEREF(memory, int64_t) = 0;
  141. break;
  142. case UPB_TYPE_UINT32:
  143. DEREF(memory, uint32_t) = 0;
  144. break;
  145. case UPB_TYPE_UINT64:
  146. DEREF(memory, uint64_t) = 0;
  147. break;
  148. default:
  149. break;
  150. }
  151. }
  152. void native_slot_get(upb_fieldtype_t type, const void* memory,
  153. zval** cache TSRMLS_DC) {
  154. switch (type) {
  155. #define CASE(upb_type, php_type, c_type) \
  156. case UPB_TYPE_##upb_type: \
  157. SEPARATE_ZVAL_IF_NOT_REF(cache); \
  158. ZVAL_##php_type(*cache, DEREF(memory, c_type)); \
  159. return;
  160. CASE(FLOAT, DOUBLE, float)
  161. CASE(DOUBLE, DOUBLE, double)
  162. CASE(BOOL, BOOL, int8_t)
  163. CASE(INT32, LONG, int32_t)
  164. CASE(ENUM, LONG, uint32_t)
  165. #undef CASE
  166. #if SIZEOF_LONG == 4
  167. #define CASE(upb_type, c_type) \
  168. case UPB_TYPE_##upb_type: { \
  169. SEPARATE_ZVAL_IF_NOT_REF(cache); \
  170. char buffer[MAX_LENGTH_OF_INT64]; \
  171. sprintf(buffer, "%lld", DEREF(memory, c_type)); \
  172. ZVAL_STRING(*cache, buffer, 1); \
  173. return; \
  174. }
  175. #else
  176. #define CASE(upb_type, c_type) \
  177. case UPB_TYPE_##upb_type: { \
  178. SEPARATE_ZVAL_IF_NOT_REF(cache); \
  179. ZVAL_LONG(*cache, DEREF(memory, c_type)); \
  180. return; \
  181. }
  182. #endif
  183. CASE(UINT64, uint64_t)
  184. CASE(INT64, int64_t)
  185. #undef CASE
  186. case UPB_TYPE_UINT32: {
  187. // Prepend bit-1 for negative numbers, so that uint32 value will be
  188. // consistent on both 32-bit and 64-bit architectures.
  189. SEPARATE_ZVAL_IF_NOT_REF(cache);
  190. int value = DEREF(memory, int32_t);
  191. if (sizeof(int) == 8) {
  192. value |= (-((value >> 31) & 0x1) & 0xFFFFFFFF00000000);
  193. }
  194. ZVAL_LONG(*cache, value);
  195. return;
  196. }
  197. case UPB_TYPE_STRING:
  198. case UPB_TYPE_BYTES: {
  199. // For optional string/bytes fields, the cache is owned by the containing
  200. // message and should have been updated during setting/decoding. However,
  201. // for repeated string/bytes fields, the cache is provided by zend engine
  202. // and has not been updated.
  203. zval* value = DEREF(memory, zval*);
  204. if (*cache != value) {
  205. ZVAL_STRINGL(*cache, Z_STRVAL_P(value), Z_STRLEN_P(value), 1);
  206. }
  207. break;
  208. }
  209. case UPB_TYPE_MESSAGE: {
  210. // Same as above for string/bytes fields.
  211. zval* value = DEREF(memory, zval*);
  212. if (*cache != value) {
  213. ZVAL_ZVAL(*cache, value, 1, 0);
  214. }
  215. return;
  216. }
  217. default:
  218. return;
  219. }
  220. }
  221. void native_slot_get_default(upb_fieldtype_t type, zval** cache TSRMLS_DC) {
  222. switch (type) {
  223. #define CASE(upb_type, php_type) \
  224. case UPB_TYPE_##upb_type: \
  225. SEPARATE_ZVAL_IF_NOT_REF(cache); \
  226. ZVAL_##php_type(*cache, 0); \
  227. return;
  228. CASE(FLOAT, DOUBLE)
  229. CASE(DOUBLE, DOUBLE)
  230. CASE(BOOL, BOOL)
  231. CASE(INT32, LONG)
  232. CASE(UINT32, LONG)
  233. CASE(ENUM, LONG)
  234. #undef CASE
  235. #if SIZEOF_LONG == 4
  236. #define CASE(upb_type) \
  237. case UPB_TYPE_##upb_type: { \
  238. SEPARATE_ZVAL_IF_NOT_REF(cache); \
  239. ZVAL_STRING(*cache, "0", 1); \
  240. return; \
  241. }
  242. #else
  243. #define CASE(upb_type) \
  244. case UPB_TYPE_##upb_type: { \
  245. SEPARATE_ZVAL_IF_NOT_REF(cache); \
  246. ZVAL_LONG(*cache, 0); \
  247. return; \
  248. }
  249. #endif
  250. CASE(UINT64)
  251. CASE(INT64)
  252. #undef CASE
  253. case UPB_TYPE_STRING:
  254. case UPB_TYPE_BYTES: {
  255. SEPARATE_ZVAL_IF_NOT_REF(cache);
  256. ZVAL_STRINGL(*cache, "", 0, 1);
  257. break;
  258. }
  259. case UPB_TYPE_MESSAGE: {
  260. SEPARATE_ZVAL_IF_NOT_REF(cache);
  261. ZVAL_NULL(*cache);
  262. return;
  263. }
  264. default:
  265. return;
  266. }
  267. }
  268. // -----------------------------------------------------------------------------
  269. // Map field utilities.
  270. // ----------------------------------------------------------------------------
  271. const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) {
  272. const upb_msgdef* subdef;
  273. if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
  274. upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
  275. return NULL;
  276. }
  277. subdef = upb_fielddef_msgsubdef(field);
  278. return upb_msgdef_mapentry(subdef) ? subdef : NULL;
  279. }
  280. const upb_msgdef* map_entry_msgdef(const upb_fielddef* field) {
  281. const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
  282. assert(subdef);
  283. return subdef;
  284. }
  285. bool is_map_field(const upb_fielddef* field) {
  286. return tryget_map_entry_msgdef(field) != NULL;
  287. }
  288. const upb_fielddef* map_field_key(const upb_fielddef* field) {
  289. const upb_msgdef* subdef = map_entry_msgdef(field);
  290. return map_entry_key(subdef);
  291. }
  292. const upb_fielddef* map_field_value(const upb_fielddef* field) {
  293. const upb_msgdef* subdef = map_entry_msgdef(field);
  294. return map_entry_value(subdef);
  295. }
  296. const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) {
  297. const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD);
  298. assert(key_field != NULL);
  299. return key_field;
  300. }
  301. const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
  302. const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD);
  303. assert(value_field != NULL);
  304. return value_field;
  305. }
  306. const zend_class_entry* field_type_class(const upb_fielddef* field TSRMLS_DC) {
  307. if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
  308. zval* desc_php = get_def_obj(upb_fielddef_subdef(field));
  309. Descriptor* desc = zend_object_store_get_object(desc_php TSRMLS_CC);
  310. return desc->klass;
  311. } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
  312. zval* desc_php = get_def_obj(upb_fielddef_subdef(field));
  313. EnumDescriptor* desc = zend_object_store_get_object(desc_php TSRMLS_CC);
  314. return desc->klass;
  315. }
  316. return NULL;
  317. }
  318. // -----------------------------------------------------------------------------
  319. // Memory layout management.
  320. // -----------------------------------------------------------------------------
  321. static size_t align_up_to(size_t offset, size_t granularity) {
  322. // Granularity must be a power of two.
  323. return (offset + granularity - 1) & ~(granularity - 1);
  324. }
  325. static void* slot_memory(MessageLayout* layout, const void* storage,
  326. const upb_fielddef* field) {
  327. return ((uint8_t*)storage) + layout->fields[upb_fielddef_index(field)].offset;
  328. }
  329. static uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage,
  330. const upb_fielddef* field) {
  331. return (uint32_t*)(((uint8_t*)storage) +
  332. layout->fields[upb_fielddef_index(field)].case_offset);
  333. }
  334. static int slot_property_cache(MessageLayout* layout, const void* storage,
  335. const upb_fielddef* field) {
  336. return layout->fields[upb_fielddef_index(field)].cache_index;
  337. }
  338. MessageLayout* create_layout(const upb_msgdef* msgdef) {
  339. MessageLayout* layout = ALLOC(MessageLayout);
  340. int nfields = upb_msgdef_numfields(msgdef);
  341. upb_msg_field_iter it;
  342. upb_msg_oneof_iter oit;
  343. size_t off = 0;
  344. int i = 0;
  345. layout->fields = ALLOC_N(MessageField, nfields);
  346. for (upb_msg_field_begin(&it, msgdef); !upb_msg_field_done(&it);
  347. upb_msg_field_next(&it)) {
  348. const upb_fielddef* field = upb_msg_iter_field(&it);
  349. size_t field_size;
  350. if (upb_fielddef_containingoneof(field)) {
  351. // Oneofs are handled separately below.
  352. continue;
  353. }
  354. // Allocate |field_size| bytes for this field in the layout.
  355. field_size = 0;
  356. if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
  357. field_size = sizeof(zval*);
  358. } else {
  359. field_size = native_slot_size(upb_fielddef_type(field));
  360. }
  361. // Align current offset up to | size | granularity.
  362. off = align_up_to(off, field_size);
  363. layout->fields[upb_fielddef_index(field)].offset = off;
  364. layout->fields[upb_fielddef_index(field)].case_offset =
  365. MESSAGE_FIELD_NO_CASE;
  366. layout->fields[upb_fielddef_index(field)].cache_index = i++;
  367. off += field_size;
  368. }
  369. // Handle oneofs now -- we iterate over oneofs specifically and allocate only
  370. // one slot per oneof.
  371. //
  372. // We assign all value slots first, then pack the 'case' fields at the end,
  373. // since in the common case (modern 64-bit platform) these are 8 bytes and 4
  374. // bytes respectively and we want to avoid alignment overhead.
  375. //
  376. // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
  377. // space for oneof cases is conceptually as wide as field tag numbers. In
  378. // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
  379. // members (8 or 16 bits respectively), so conceivably we could assign
  380. // consecutive case numbers and then pick a smaller oneof case slot size, but
  381. // the complexity to implement this indirection is probably not worthwhile.
  382. for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit);
  383. upb_msg_oneof_next(&oit)) {
  384. const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
  385. upb_oneof_iter fit;
  386. // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
  387. // all fields.
  388. size_t field_size = NATIVE_SLOT_MAX_SIZE;
  389. // Align the offset .
  390. off = align_up_to( off, field_size);
  391. // Assign all fields in the oneof this same offset.
  392. for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit);
  393. upb_oneof_next(&fit)) {
  394. const upb_fielddef* field = upb_oneof_iter_field(&fit);
  395. layout->fields[upb_fielddef_index(field)].offset = off;
  396. layout->fields[upb_fielddef_index(field)].cache_index = i;
  397. }
  398. i++;
  399. off += field_size;
  400. }
  401. // Now the case offset.
  402. for (upb_msg_oneof_begin(&oit, msgdef); !upb_msg_oneof_done(&oit);
  403. upb_msg_oneof_next(&oit)) {
  404. const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
  405. upb_oneof_iter fit;
  406. size_t field_size = sizeof(uint32_t);
  407. // Align the offset .
  408. off = (off + field_size - 1) & ~(field_size - 1);
  409. // Assign all fields in the oneof this same offset.
  410. for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit);
  411. upb_oneof_next(&fit)) {
  412. const upb_fielddef* field = upb_oneof_iter_field(&fit);
  413. layout->fields[upb_fielddef_index(field)].case_offset = off;
  414. }
  415. off += field_size;
  416. }
  417. layout->size = off;
  418. layout->msgdef = msgdef;
  419. upb_msgdef_ref(layout->msgdef, &layout->msgdef);
  420. return layout;
  421. }
  422. void free_layout(MessageLayout* layout) {
  423. FREE(layout->fields);
  424. upb_msgdef_unref(layout->msgdef, &layout->msgdef);
  425. FREE(layout);
  426. }
  427. void layout_init(MessageLayout* layout, void* storage,
  428. zval** properties_table TSRMLS_DC) {
  429. int i;
  430. upb_msg_field_iter it;
  431. for (upb_msg_field_begin(&it, layout->msgdef), i = 0; !upb_msg_field_done(&it);
  432. upb_msg_field_next(&it), i++) {
  433. const upb_fielddef* field = upb_msg_iter_field(&it);
  434. void* memory = slot_memory(layout, storage, field);
  435. uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
  436. int cache_index = slot_property_cache(layout, storage, field);
  437. zval** property_ptr = &properties_table[cache_index];
  438. if (upb_fielddef_containingoneof(field)) {
  439. memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
  440. *oneof_case = ONEOF_CASE_NONE;
  441. } else if (is_map_field(field)) {
  442. zval_ptr_dtor(property_ptr);
  443. map_field_create_with_type(map_field_type, field, property_ptr TSRMLS_CC);
  444. DEREF(memory, zval**) = property_ptr;
  445. } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
  446. zval_ptr_dtor(property_ptr);
  447. repeated_field_create_with_type(repeated_field_type, field,
  448. property_ptr TSRMLS_CC);
  449. DEREF(memory, zval**) = property_ptr;
  450. property_ptr = NULL;
  451. } else {
  452. native_slot_init(upb_fielddef_type(field), memory, property_ptr);
  453. }
  454. }
  455. }
  456. // For non-singular fields, the related memory needs to point to the actual
  457. // zval in properties table first.
  458. static void* value_memory(const upb_fielddef* field, void* memory) {
  459. switch (upb_fielddef_type(field)) {
  460. case UPB_TYPE_STRING:
  461. case UPB_TYPE_BYTES:
  462. case UPB_TYPE_MESSAGE:
  463. memory = DEREF(memory, zval**);
  464. break;
  465. default:
  466. // No operation
  467. break;
  468. }
  469. return memory;
  470. }
  471. zval* layout_get(MessageLayout* layout, const void* storage,
  472. const upb_fielddef* field, zval** cache TSRMLS_DC) {
  473. void* memory = slot_memory(layout, storage, field);
  474. uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
  475. if (upb_fielddef_containingoneof(field)) {
  476. if (*oneof_case != upb_fielddef_number(field)) {
  477. native_slot_get_default(upb_fielddef_type(field), cache TSRMLS_CC);
  478. } else {
  479. native_slot_get(upb_fielddef_type(field), value_memory(field, memory),
  480. cache TSRMLS_CC);
  481. }
  482. return *cache;
  483. } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
  484. return *cache;
  485. } else {
  486. native_slot_get(upb_fielddef_type(field), value_memory(field, memory),
  487. cache TSRMLS_CC);
  488. return *cache;
  489. }
  490. }
  491. void layout_set(MessageLayout* layout, MessageHeader* header,
  492. const upb_fielddef* field, zval* val TSRMLS_DC) {
  493. void* storage = message_data(header);
  494. void* memory = slot_memory(layout, storage, field);
  495. uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
  496. if (upb_fielddef_containingoneof(field)) {
  497. upb_fieldtype_t type = upb_fielddef_type(field);
  498. zend_class_entry *ce = NULL;
  499. // For non-singular fields, the related memory needs to point to the actual
  500. // zval in properties table first.
  501. switch (type) {
  502. case UPB_TYPE_MESSAGE: {
  503. const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
  504. zval* desc_php = get_def_obj(msg);
  505. Descriptor* desc = zend_object_store_get_object(desc_php TSRMLS_CC);
  506. ce = desc->klass;
  507. // Intentionally fall through.
  508. }
  509. case UPB_TYPE_STRING:
  510. case UPB_TYPE_BYTES: {
  511. int property_cache_index =
  512. header->descriptor->layout->fields[upb_fielddef_index(field)]
  513. .cache_index;
  514. DEREF(memory, zval**) =
  515. &(header->std.properties_table)[property_cache_index];
  516. memory = DEREF(memory, zval**);
  517. break;
  518. }
  519. default:
  520. break;
  521. }
  522. native_slot_set(type, ce, memory, val TSRMLS_CC);
  523. *oneof_case = upb_fielddef_number(field);
  524. } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
  525. // Works for both repeated and map fields
  526. memory = DEREF(memory, zval**);
  527. if (EXPECTED(DEREF(memory, zval*) != val)) {
  528. zval_ptr_dtor(memory);
  529. DEREF(memory, zval*) = val;
  530. Z_ADDREF_P(val);
  531. }
  532. } else {
  533. upb_fieldtype_t type = upb_fielddef_type(field);
  534. zend_class_entry *ce = NULL;
  535. if (type == UPB_TYPE_MESSAGE) {
  536. const upb_msgdef* msg = upb_fielddef_msgsubdef(field);
  537. zval* desc_php = get_def_obj(msg);
  538. Descriptor* desc = zend_object_store_get_object(desc_php TSRMLS_CC);
  539. ce = desc->klass;
  540. }
  541. native_slot_set(type, ce, value_memory(field, memory), val TSRMLS_CC);
  542. }
  543. }
  544. const char* layout_get_oneof_case(MessageLayout* layout, const void* storage,
  545. const upb_oneofdef* oneof TSRMLS_DC) {
  546. upb_oneof_iter i;
  547. const upb_fielddef* first_field;
  548. // Oneof is guaranteed to have at least one field. Get the first field.
  549. for(upb_oneof_begin(&i, oneof); !upb_oneof_done(&i); upb_oneof_next(&i)) {
  550. first_field = upb_oneof_iter_field(&i);
  551. break;
  552. }
  553. uint32_t* oneof_case = slot_oneof_case(layout, storage, first_field);
  554. if (*oneof_case == 0) {
  555. return "";
  556. }
  557. const upb_fielddef* field = upb_oneofdef_itof(oneof, *oneof_case);
  558. return upb_fielddef_name(field);
  559. }