/php/msgpack_convert.c

https://github.com/mostlygeek/msgpack · C · 794 lines · 684 code · 92 blank · 18 comment · 117 complexity · 7b9adaae675371038f8774a1eb3b831b MD5 · raw file

  1. #include "php.h"
  2. #include "php_msgpack.h"
  3. #include "msgpack_convert.h"
  4. #include "msgpack_errors.h"
  5. #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3)
  6. # define Z_REFCOUNT_P(pz) ((pz)->refcount)
  7. # define Z_SET_ISREF_P(pz) (pz)->is_ref = 1
  8. # define Z_UNSET_ISREF_P(pz) (pz)->is_ref = 0
  9. #endif
  10. #define MSGPACK_CONVERT_COPY_ZVAL(_pz, _ppz) \
  11. ALLOC_INIT_ZVAL(_pz); \
  12. *(_pz) = **(_ppz); \
  13. if (PZVAL_IS_REF(*(_ppz))) { \
  14. if (Z_REFCOUNT_P(*(_ppz)) > 0) { \
  15. zval_copy_ctor(_pz); \
  16. } else { \
  17. FREE_ZVAL(*(_ppz)); \
  18. } \
  19. INIT_PZVAL(_pz); \
  20. Z_SET_ISREF_P(_pz); \
  21. } else { \
  22. zval_copy_ctor(_pz); \
  23. INIT_PZVAL(_pz); \
  24. }
  25. #define MSGPACK_CONVERT_UPDATE_PROPERTY(_ht, _key, _key_len, _val, _var) \
  26. if (zend_symtable_update( \
  27. _ht, _key, _key_len, &_val, sizeof(_val), NULL) == SUCCESS) { \
  28. zend_hash_add(_var, _key, _key_len, &_val, sizeof(_val), NULL); \
  29. return SUCCESS; \
  30. }
  31. inline int msgpack_convert_long_to_properties(
  32. HashTable *ht, HashTable **properties, HashPosition *prop_pos,
  33. uint key_index, zval *val, HashTable *var)
  34. {
  35. TSRMLS_FETCH();
  36. if (*properties != NULL)
  37. {
  38. char *prop_key;
  39. uint prop_key_len;
  40. ulong prop_key_index;
  41. zval **data = NULL;
  42. zval *tplval = NULL;
  43. zval **dataval = NULL;
  44. for (;; zend_hash_move_forward_ex(*properties, prop_pos))
  45. {
  46. if (zend_hash_get_current_key_ex(
  47. *properties, &prop_key, &prop_key_len,
  48. &prop_key_index, 0, prop_pos) == HASH_KEY_IS_STRING)
  49. {
  50. if (var == NULL ||
  51. !zend_hash_exists(var, prop_key, prop_key_len))
  52. {
  53. if (zend_hash_find(
  54. ht, prop_key, prop_key_len,
  55. (void **)&data) == SUCCESS)
  56. {
  57. switch (Z_TYPE_PP(data))
  58. {
  59. case IS_ARRAY:
  60. {
  61. HashTable *dataht;
  62. dataht = HASH_OF(val);
  63. if (zend_hash_index_find(
  64. dataht, prop_key_index,
  65. (void **)dataval) != SUCCESS)
  66. {
  67. MSGPACK_WARNING(
  68. "[msgpack] (%s) "
  69. "can't get data value by index",
  70. __FUNCTION__);
  71. return FAILURE;
  72. }
  73. ALLOC_INIT_ZVAL(tplval);
  74. if (msgpack_convert_array(
  75. tplval, *data, dataval) == SUCCESS)
  76. {
  77. zend_hash_move_forward_ex(
  78. *properties, prop_pos);
  79. return zend_symtable_update(
  80. ht, prop_key, prop_key_len,
  81. &tplval, sizeof(tplval), NULL);
  82. }
  83. // TODO: de we need to call dtor?
  84. return FAILURE;
  85. break;
  86. }
  87. case IS_OBJECT:
  88. {
  89. ALLOC_INIT_ZVAL(tplval);
  90. if (msgpack_convert_object(
  91. tplval, *data, &val) == SUCCESS)
  92. {
  93. zend_hash_move_forward_ex(
  94. *properties, prop_pos);
  95. return zend_symtable_update(
  96. ht, prop_key, prop_key_len,
  97. &tplval, sizeof(tplval), NULL);
  98. }
  99. // TODO: de we need to call dtor?
  100. return FAILURE;
  101. break;
  102. }
  103. default:
  104. zend_hash_move_forward_ex(*properties, prop_pos);
  105. return zend_symtable_update(
  106. ht, prop_key, prop_key_len,
  107. &val, sizeof(val), NULL);
  108. break;
  109. }
  110. }
  111. }
  112. }
  113. else
  114. {
  115. break;
  116. }
  117. }
  118. *properties = NULL;
  119. }
  120. return zend_hash_index_update(ht, key_index, &val, sizeof(val), NULL);
  121. }
  122. inline int msgpack_convert_string_to_properties(
  123. zval *object, char *key, uint key_len, zval *val, HashTable *var)
  124. {
  125. zval **data = NULL;
  126. HashTable *ht;
  127. zend_class_entry *ce;
  128. char *prot_name, *priv_name;
  129. int prop_name_len;
  130. TSRMLS_FETCH();
  131. ht = HASH_OF(object);
  132. ce = zend_get_class_entry(object TSRMLS_CC);
  133. /* private */
  134. zend_mangle_property_name(
  135. &priv_name, &prop_name_len, ce->name, ce->name_length, key, key_len, 1);
  136. if (zend_hash_find(
  137. ht, priv_name, prop_name_len, (void **)&data) == SUCCESS)
  138. {
  139. MSGPACK_CONVERT_UPDATE_PROPERTY(ht, priv_name, prop_name_len, val, var);
  140. }
  141. /* protected */
  142. zend_mangle_property_name(
  143. &prot_name, &prop_name_len, "*", 1, key, key_len, 1);
  144. if (zend_hash_find(
  145. ht, prot_name, prop_name_len, (void **)&data) == SUCCESS)
  146. {
  147. MSGPACK_CONVERT_UPDATE_PROPERTY(ht, prot_name, prop_name_len, val, var);
  148. }
  149. /* public */
  150. MSGPACK_CONVERT_UPDATE_PROPERTY(ht, key, key_len, val, var);
  151. return FAILURE;
  152. }
  153. int msgpack_convert_array(zval *return_value, zval *tpl, zval **value)
  154. {
  155. TSRMLS_FETCH();
  156. if (Z_TYPE_P(tpl) == IS_ARRAY)
  157. {
  158. char *key;
  159. uint key_len;
  160. int key_type;
  161. ulong key_index;
  162. zval **data, **arydata;
  163. HashPosition pos, valpos;
  164. HashTable *ht, *htval;
  165. int num;
  166. ht = HASH_OF(tpl);
  167. // TODO: maybe need to release memory?
  168. array_init(return_value);
  169. num = zend_hash_num_elements(ht);
  170. if (num <= 0)
  171. {
  172. MSGPACK_WARNING(
  173. "[msgpack] (%s) template array length is 0",
  174. __FUNCTION__);
  175. zval_ptr_dtor(value);
  176. return FAILURE;
  177. }
  178. /* string */
  179. if (ht->nNumOfElements != ht->nNextFreeElement)
  180. {
  181. htval = HASH_OF(*value);
  182. if (!htval)
  183. {
  184. MSGPACK_WARNING(
  185. "[msgpack] (%s) input data is not array",
  186. __FUNCTION__);
  187. zval_ptr_dtor(value);
  188. return FAILURE;
  189. }
  190. zend_hash_internal_pointer_reset_ex(ht, &pos);
  191. zend_hash_internal_pointer_reset_ex(htval, &valpos);
  192. for (;; zend_hash_move_forward_ex(ht, &pos),
  193. zend_hash_move_forward_ex(htval, &valpos))
  194. {
  195. key_type = zend_hash_get_current_key_ex(
  196. ht, &key, &key_len, &key_index, 0, &pos);
  197. if (key_type == HASH_KEY_NON_EXISTANT)
  198. {
  199. break;
  200. }
  201. if (zend_hash_get_current_data_ex(
  202. ht, (void *)&data, &pos) != SUCCESS)
  203. {
  204. continue;
  205. }
  206. if (key_type == HASH_KEY_IS_STRING)
  207. {
  208. int (*convert_function)(zval *, zval *, zval **) = NULL;
  209. zval **dataval, *val;
  210. switch (Z_TYPE_PP(data))
  211. {
  212. case IS_ARRAY:
  213. convert_function = msgpack_convert_array;
  214. break;
  215. case IS_OBJECT:
  216. // case IS_STRING:
  217. convert_function = msgpack_convert_object;
  218. break;
  219. default:
  220. break;
  221. }
  222. if (zend_hash_get_current_data_ex(
  223. htval, (void *)&dataval, &valpos) != SUCCESS)
  224. {
  225. MSGPACK_WARNING(
  226. "[msgpack] (%s) can't get data",
  227. __FUNCTION__);
  228. zval_ptr_dtor(value);
  229. return FAILURE;
  230. }
  231. MSGPACK_CONVERT_COPY_ZVAL(val, dataval);
  232. if (convert_function)
  233. {
  234. zval *rv;
  235. ALLOC_INIT_ZVAL(rv);
  236. if (convert_function(rv, *data, &val) != SUCCESS)
  237. {
  238. zval_ptr_dtor(&val);
  239. return FAILURE;
  240. }
  241. add_assoc_zval_ex(return_value, key, key_len, rv);
  242. }
  243. else
  244. {
  245. add_assoc_zval_ex(return_value, key, key_len, val);
  246. }
  247. }
  248. }
  249. zval_ptr_dtor(value);
  250. return SUCCESS;
  251. }
  252. else
  253. {
  254. /* index */
  255. int (*convert_function)(zval *, zval *, zval **) = NULL;
  256. if (Z_TYPE_PP(value) != IS_ARRAY)
  257. {
  258. MSGPACK_WARNING(
  259. "[msgpack] (%s) unserialized data must be array.",
  260. __FUNCTION__);
  261. zval_ptr_dtor(value);
  262. return FAILURE;
  263. }
  264. zend_hash_internal_pointer_reset_ex(ht, &pos);
  265. key_type = zend_hash_get_current_key_ex(
  266. ht, &key, &key_len, &key_index, 0, &pos);
  267. if (key_type == HASH_KEY_NON_EXISTANT)
  268. {
  269. MSGPACK_WARNING(
  270. "[msgpack] (%s) first element in template array is empty",
  271. __FUNCTION__);
  272. zval_ptr_dtor(value);
  273. return FAILURE;
  274. }
  275. if (zend_hash_get_current_data_ex(
  276. ht, (void *)&data, &pos) != SUCCESS)
  277. {
  278. MSGPACK_WARNING(
  279. "[msgpack] (%s) invalid template: empty array?",
  280. __FUNCTION__);
  281. zval_ptr_dtor(value);
  282. return FAILURE;
  283. }
  284. switch (Z_TYPE_PP(data))
  285. {
  286. case IS_ARRAY:
  287. convert_function = msgpack_convert_array;
  288. break;
  289. case IS_OBJECT:
  290. case IS_STRING:
  291. convert_function = msgpack_convert_object;
  292. break;
  293. default:
  294. break;
  295. }
  296. htval = HASH_OF(*value);
  297. num = zend_hash_num_elements(htval);
  298. if (num <= 0)
  299. {
  300. MSGPACK_WARNING(
  301. "[msgpack] (%s) array length is 0 in unserialized data",
  302. __FUNCTION__);
  303. zval_ptr_dtor(value);
  304. return FAILURE;
  305. }
  306. zend_hash_internal_pointer_reset_ex(htval, &valpos);
  307. for (;; zend_hash_move_forward_ex(htval, &valpos))
  308. {
  309. key_type = zend_hash_get_current_key_ex(
  310. htval, &key, &key_len, &key_index, 0, &valpos);
  311. if (key_type == HASH_KEY_NON_EXISTANT)
  312. {
  313. break;
  314. }
  315. if (zend_hash_get_current_data_ex(
  316. htval, (void *)&arydata, &valpos) != SUCCESS)
  317. {
  318. MSGPACK_WARNING(
  319. "[msgpack] (%s) can't get next data in indexed array",
  320. __FUNCTION__);
  321. continue;
  322. }
  323. switch (key_type)
  324. {
  325. case HASH_KEY_IS_LONG:
  326. {
  327. zval *aryval, *rv;
  328. ALLOC_INIT_ZVAL(rv);
  329. MSGPACK_CONVERT_COPY_ZVAL(aryval, arydata);
  330. if (convert_function)
  331. {
  332. if (convert_function(rv, *data, &aryval) != SUCCESS)
  333. {
  334. zval_ptr_dtor(&aryval);
  335. MSGPACK_WARNING(
  336. "[msgpack] (%s) "
  337. "convert failure in HASH_KEY_IS_LONG "
  338. "in indexed array",
  339. __FUNCTION__);
  340. zval_ptr_dtor(value);
  341. return FAILURE;
  342. }
  343. add_next_index_zval(return_value, rv);
  344. }
  345. else
  346. {
  347. add_next_index_zval(return_value, aryval);
  348. }
  349. break;
  350. }
  351. case HASH_KEY_IS_STRING:
  352. MSGPACK_WARNING(
  353. "[msgpack] (%s) key is string",
  354. __FUNCTION__);
  355. zval_ptr_dtor(value);
  356. return FAILURE;
  357. default:
  358. MSGPACK_WARNING(
  359. "[msgpack] (%s) key is not string nor array",
  360. __FUNCTION__);
  361. zval_ptr_dtor(value);
  362. return FAILURE;
  363. }
  364. }
  365. zval_ptr_dtor(value);
  366. return SUCCESS;
  367. }
  368. }
  369. else
  370. {
  371. // shouldn't reach
  372. MSGPACK_WARNING(
  373. "[msgpack] (%s) template is not array",
  374. __FUNCTION__);
  375. zval_ptr_dtor(value);
  376. return FAILURE;
  377. }
  378. // shouldn't reach
  379. zval_ptr_dtor(value);
  380. return FAILURE;
  381. }
  382. int msgpack_convert_object(zval *return_value, zval *tpl, zval **value)
  383. {
  384. zend_class_entry *ce, **pce;
  385. TSRMLS_FETCH();
  386. switch (Z_TYPE_P(tpl))
  387. {
  388. case IS_STRING:
  389. if (zend_lookup_class(
  390. Z_STRVAL_P(tpl), Z_STRLEN_P(tpl),
  391. &pce TSRMLS_CC) != SUCCESS)
  392. {
  393. MSGPACK_ERROR("[msgpack] (%s) Class '%s' not found",
  394. __FUNCTION__, Z_STRVAL_P(tpl));
  395. return FAILURE;
  396. }
  397. ce = *pce;
  398. break;
  399. case IS_OBJECT:
  400. ce = zend_get_class_entry(tpl TSRMLS_CC);
  401. break;
  402. default:
  403. MSGPACK_ERROR("[msgpack] (%s) object type is unsupported",
  404. __FUNCTION__);
  405. return FAILURE;
  406. }
  407. if (Z_TYPE_PP(value) == IS_OBJECT)
  408. {
  409. zend_class_entry *vce;
  410. vce = zend_get_class_entry(*value TSRMLS_CC);
  411. if (strcmp(ce->name, vce->name) == 0)
  412. {
  413. *return_value = **value;
  414. zval_copy_ctor(return_value);
  415. zval_ptr_dtor(value);
  416. return SUCCESS;
  417. }
  418. }
  419. object_init_ex(return_value, ce);
  420. /* Run the constructor if there is one */
  421. if (ce->constructor
  422. && (ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC))
  423. {
  424. zval *retval_ptr = NULL;
  425. zval ***params = NULL;
  426. int num_args = 0;
  427. zend_fcall_info fci;
  428. zend_fcall_info_cache fcc;
  429. #if ZEND_MODULE_API_NO >= 20090626
  430. fci.size = sizeof(fci);
  431. fci.function_table = EG(function_table);
  432. fci.function_name = NULL;
  433. fci.symbol_table = NULL;
  434. fci.object_ptr = return_value;
  435. fci.retval_ptr_ptr = &retval_ptr;
  436. fci.param_count = num_args;
  437. fci.params = params;
  438. fci.no_separation = 1;
  439. fcc.initialized = 1;
  440. fcc.function_handler = ce->constructor;
  441. fcc.calling_scope = EG(scope);
  442. fcc.called_scope = Z_OBJCE_P(return_value);
  443. fcc.object_ptr = return_value;
  444. #else
  445. fci.size = sizeof(fci);
  446. fci.function_table = EG(function_table);
  447. fci.function_name = NULL;
  448. fci.symbol_table = NULL;
  449. fci.object_pp = &return_value;
  450. fci.retval_ptr_ptr = &retval_ptr;
  451. fci.param_count = num_args;
  452. fci.params = params;
  453. fci.no_separation = 1;
  454. fcc.initialized = 1;
  455. fcc.function_handler = ce->constructor;
  456. fcc.calling_scope = EG(scope);
  457. fcc.object_pp = &return_value;
  458. #endif
  459. if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE)
  460. {
  461. if (params)
  462. {
  463. efree(params);
  464. }
  465. if (retval_ptr)
  466. {
  467. zval_ptr_dtor(&retval_ptr);
  468. }
  469. MSGPACK_WARNING(
  470. "[msgpack] (%s) Invocation of %s's constructor failed",
  471. __FUNCTION__, ce->name);
  472. return FAILURE;
  473. }
  474. if (retval_ptr)
  475. {
  476. zval_ptr_dtor(&retval_ptr);
  477. }
  478. if (params)
  479. {
  480. efree(params);
  481. }
  482. }
  483. switch (Z_TYPE_PP(value))
  484. {
  485. case IS_ARRAY:
  486. {
  487. char *key;
  488. uint key_len;
  489. int key_type;
  490. ulong key_index;
  491. zval **data;
  492. HashPosition pos;
  493. HashTable *ht, *ret;
  494. HashTable *var = NULL;
  495. int num;
  496. ht = HASH_OF(*value);
  497. ret = HASH_OF(return_value);
  498. num = zend_hash_num_elements(ht);
  499. if (num <= 0)
  500. {
  501. zval_ptr_dtor(value);
  502. break;
  503. }
  504. /* string - php_only mode? */
  505. if (ht->nNumOfElements != ht->nNextFreeElement
  506. || ht->nNumOfElements != ret->nNumOfElements)
  507. {
  508. HashTable *properties = NULL;
  509. HashPosition prop_pos;
  510. ALLOC_HASHTABLE(var);
  511. zend_hash_init(var, num, NULL, NULL, 0);
  512. zend_hash_internal_pointer_reset_ex(ht, &pos);
  513. for (;; zend_hash_move_forward_ex(ht, &pos))
  514. {
  515. key_type = zend_hash_get_current_key_ex(
  516. ht, &key, &key_len, &key_index, 0, &pos);
  517. if (key_type == HASH_KEY_NON_EXISTANT)
  518. {
  519. break;
  520. }
  521. if (zend_hash_get_current_data_ex(
  522. ht, (void *)&data, &pos) != SUCCESS)
  523. {
  524. continue;
  525. }
  526. if (key_type == HASH_KEY_IS_STRING)
  527. {
  528. zval *val;
  529. MSGPACK_CONVERT_COPY_ZVAL(val, data);
  530. if (msgpack_convert_string_to_properties(
  531. return_value, key, key_len, val, var) != SUCCESS)
  532. {
  533. zval_ptr_dtor(&val);
  534. MSGPACK_WARNING(
  535. "[msgpack] (%s) "
  536. "illegal offset type, skip this decoding",
  537. __FUNCTION__);
  538. }
  539. }
  540. }
  541. /* index */
  542. properties = Z_OBJ_HT_P(return_value)->get_properties(
  543. return_value TSRMLS_CC);
  544. if (HASH_OF(tpl))
  545. {
  546. properties = HASH_OF(tpl);
  547. }
  548. zend_hash_internal_pointer_reset_ex(properties, &prop_pos);
  549. zend_hash_internal_pointer_reset_ex(ht, &pos);
  550. for (;; zend_hash_move_forward_ex(ht, &pos))
  551. {
  552. key_type = zend_hash_get_current_key_ex(
  553. ht, &key, &key_len, &key_index, 0, &pos);
  554. if (key_type == HASH_KEY_NON_EXISTANT)
  555. {
  556. break;
  557. }
  558. if (zend_hash_get_current_data_ex(
  559. ht, (void *)&data, &pos) != SUCCESS)
  560. {
  561. continue;
  562. }
  563. switch (key_type)
  564. {
  565. case HASH_KEY_IS_LONG:
  566. {
  567. zval *val;
  568. MSGPACK_CONVERT_COPY_ZVAL(val, data);
  569. if (msgpack_convert_long_to_properties(
  570. ret, &properties, &prop_pos,
  571. key_index, val, var) != SUCCESS)
  572. {
  573. zval_ptr_dtor(&val);
  574. MSGPACK_WARNING(
  575. "[msgpack] (%s) "
  576. "illegal offset type, skip this decoding",
  577. __FUNCTION__);
  578. }
  579. break;
  580. }
  581. case HASH_KEY_IS_STRING:
  582. break;
  583. default:
  584. MSGPACK_WARNING(
  585. "[msgpack] (%s) key is not string nor array",
  586. __FUNCTION__);
  587. break;
  588. }
  589. }
  590. zend_hash_destroy(var);
  591. FREE_HASHTABLE(var);
  592. }
  593. else
  594. {
  595. HashPosition valpos;
  596. int (*convert_function)(zval *, zval *, zval **) = NULL;
  597. zval **arydata, *aryval;
  598. /* index */
  599. zend_hash_internal_pointer_reset_ex(ret, &pos);
  600. zend_hash_internal_pointer_reset_ex(ht, &valpos);
  601. for (;; zend_hash_move_forward_ex(ret, &pos),
  602. zend_hash_move_forward_ex(ht, &valpos))
  603. {
  604. key_type = zend_hash_get_current_key_ex(
  605. ret, &key, &key_len, &key_index, 0, &pos);
  606. if (key_type == HASH_KEY_NON_EXISTANT)
  607. {
  608. break;
  609. }
  610. if (zend_hash_get_current_data_ex(
  611. ret, (void *)&data, &pos) != SUCCESS)
  612. {
  613. continue;
  614. }
  615. switch (Z_TYPE_PP(data))
  616. {
  617. case IS_ARRAY:
  618. convert_function = msgpack_convert_array;
  619. break;
  620. case IS_OBJECT:
  621. //case IS_STRING: -- may have default values of
  622. // class members, so it's not wise to allow
  623. convert_function = msgpack_convert_object;
  624. break;
  625. default:
  626. break;
  627. }
  628. if (zend_hash_get_current_data_ex(
  629. ht, (void *)&arydata, &valpos) != SUCCESS)
  630. {
  631. MSGPACK_WARNING(
  632. "[msgpack] (%s) can't get data value by index",
  633. __FUNCTION__);
  634. return FAILURE;
  635. }
  636. MSGPACK_CONVERT_COPY_ZVAL(aryval, arydata);
  637. if (convert_function)
  638. {
  639. zval *rv;
  640. ALLOC_INIT_ZVAL(rv);
  641. if (convert_function(rv, *data, &aryval) != SUCCESS)
  642. {
  643. zval_ptr_dtor(&aryval);
  644. MSGPACK_WARNING(
  645. "[msgpack] (%s) "
  646. "convert failure in convert_object",
  647. __FUNCTION__);
  648. return FAILURE;
  649. }
  650. zend_symtable_update(
  651. ret, key, key_len, &rv, sizeof(rv), NULL);
  652. }
  653. else
  654. {
  655. zend_symtable_update(
  656. ret, key, key_len, &aryval, sizeof(aryval), NULL);
  657. }
  658. }
  659. }
  660. zval_ptr_dtor(value);
  661. break;
  662. }
  663. default:
  664. {
  665. HashTable *properties = NULL;
  666. HashPosition prop_pos;
  667. properties = Z_OBJ_HT_P(return_value)->get_properties(
  668. return_value TSRMLS_CC);
  669. zend_hash_internal_pointer_reset_ex(properties, &prop_pos);
  670. if (msgpack_convert_long_to_properties(
  671. HASH_OF(return_value), &properties, &prop_pos,
  672. 0, *value, NULL) != SUCCESS)
  673. {
  674. MSGPACK_WARNING(
  675. "[msgpack] (%s) illegal offset type, skip this decoding",
  676. __FUNCTION__);
  677. }
  678. break;
  679. }
  680. }
  681. return SUCCESS;
  682. }
  683. int msgpack_convert_template(zval *return_value, zval *tpl, zval **value)
  684. {
  685. TSRMLS_FETCH();
  686. switch (Z_TYPE_P(tpl))
  687. {
  688. case IS_ARRAY:
  689. return msgpack_convert_array(return_value, tpl, value);
  690. break;
  691. case IS_STRING:
  692. case IS_OBJECT:
  693. return msgpack_convert_object(return_value, tpl, value);
  694. break;
  695. default:
  696. MSGPACK_ERROR("[msgpack] (%s) Template type is unsupported",
  697. __FUNCTION__);
  698. return FAILURE;
  699. }
  700. // shouldn't reach
  701. return FAILURE;
  702. }