mirror of
				https://github.com/msgpack/msgpack-c.git
				synced 2025-10-26 10:32:58 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			657 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			657 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|   +----------------------------------------------------------------------+
 | |
|   | PHP Version 5                                                        |
 | |
|   +----------------------------------------------------------------------+
 | |
|   | Copyright (c) 1997-2007 The PHP Group                                |
 | |
|   +----------------------------------------------------------------------+
 | |
|   | This source file is subject to version 3.01 of the PHP license,      |
 | |
|   | that is bundled with this package in the file LICENSE, and is        |
 | |
|   | available through the world-wide-web at the following url:           |
 | |
|   | http://www.php.net/license/3_01.txt                                  |
 | |
|   | If you did not receive a copy of the PHP license and are unable to   |
 | |
|   | obtain it through the world-wide-web, please send a note to          |
 | |
|   | license@php.net so we can mail you a copy immediately.               |
 | |
|   +----------------------------------------------------------------------+
 | |
|   | Author: Hideyuki TAKEI                                               |
 | |
|   +----------------------------------------------------------------------+
 | |
| */
 | |
| 
 | |
| /* $Id: header 226204 2007-01-01 19:32:10Z iliaa $ */
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
| #include "config.h"
 | |
| #endif
 | |
| 
 | |
| #include "php.h"
 | |
| #include "php_ini.h"
 | |
| #include "ext/standard/info.h"
 | |
| #include "ext/standard/php_smart_str.h"
 | |
| #include "php_msgpack.h"
 | |
| 
 | |
| #define PHP_EXT_VERSION "0.01"
 | |
| 
 | |
| #ifndef TRUE
 | |
| # define TRUE 1
 | |
| # define FALSE 0
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /* pack */
 | |
| #include "msgpack/pack_define.h"
 | |
| 
 | |
| #define msgpack_pack_inline_func(name) \
 | |
| 	    static inline void msgpack_pack ## name
 | |
| 
 | |
| #define msgpack_pack_inline_func_cint(name) \
 | |
| 	    static inline void msgpack_pack ## name
 | |
| 
 | |
| #define msgpack_pack_user smart_str*
 | |
| 
 | |
| #define msgpack_pack_append_buffer(user, buf, len) \
 | |
| 	    smart_str_appendl(user, (const void*)buf, len)
 | |
| 
 | |
| #include "msgpack/pack_template.h"
 | |
| 
 | |
| 
 | |
| /* unpack */
 | |
| #include "msgpack/unpack_define.h"
 | |
| 
 | |
| typedef struct {
 | |
| 	    int finished;
 | |
| 		char* source;
 | |
| } unpack_user;
 | |
| 
 | |
| #define msgpack_unpack_struct(name) \
 | |
| 	    struct template ## name
 | |
| 
 | |
| #define msgpack_unpack_func(ret, name) \
 | |
| 	    ret template ## name
 | |
| 
 | |
| #define msgpack_unpack_callback(name) \
 | |
| 	    template_callback ## name
 | |
| 
 | |
| #define msgpack_unpack_object zval*
 | |
| 
 | |
| #define msgpack_unpack_user unpack_user
 | |
| 
 | |
| struct template_context;
 | |
| typedef struct template_context msgpack_unpack_t;
 | |
| 
 | |
| static void template_init(msgpack_unpack_t* u);
 | |
| static msgpack_unpack_object template_data(msgpack_unpack_t* u);
 | |
| static int template_execute(msgpack_unpack_t* u,
 | |
| 		        const char* data, size_t len, size_t* off);
 | |
| 
 | |
| ZEND_BEGIN_MODULE_GLOBALS(msgpack)
 | |
| 	msgpack_unpack_t *global_mp;
 | |
| ZEND_END_MODULE_GLOBALS(msgpack)
 | |
| 
 | |
| #ifdef ZTS
 | |
| #define MSGPACK_G(v) TSRMG(msgpack_globals_id, zend_msgpack_globals *, v)
 | |
| #else
 | |
| #define MSGPACK_G(v) (msgpack_globals.v)
 | |
| #endif
 | |
| 
 | |
| static inline msgpack_unpack_object template_callback_root(unpack_user* u)
 | |
| {
 | |
| 	msgpack_unpack_object data;
 | |
| 	ALLOC_INIT_ZVAL(data);
 | |
| 	ZVAL_NULL(data);
 | |
| 	return data;
 | |
| }
 | |
| 
 | |
| static inline int template_callback_uint8(unpack_user* u, uint8_t d, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, d); return 0; }
 | |
| 
 | |
| static inline int template_callback_uint16(unpack_user* u, uint16_t d, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, d); return 0; }
 | |
| 
 | |
| static inline int template_callback_uint32(unpack_user* u, uint32_t d, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, d); return 0; }
 | |
| 
 | |
| static inline int template_callback_uint64(unpack_user* u, uint64_t d, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, d); return 0; }
 | |
| 
 | |
| static inline int template_callback_int8(unpack_user* u, int8_t d, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, (long)d); return 0; }
 | |
| 
 | |
| static inline int template_callback_int16(unpack_user* u, int16_t d, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, (long)d); return 0; }
 | |
| 
 | |
| static inline int template_callback_int32(unpack_user* u, int32_t d, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, (long)d); return 0; }
 | |
| 
 | |
| static inline int template_callback_int64(unpack_user* u, int64_t d, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, d); return 0; }
 | |
| 
 | |
| static inline int template_callback_float(unpack_user* u, float d, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_DOUBLE(*o, d); return 0; }
 | |
| 
 | |
| static inline int template_callback_double(unpack_user* u, double d, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_DOUBLE(*o, d); return 0; }
 | |
| 
 | |
| static inline int template_callback_nil(unpack_user* u, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_NULL(*o); return 0; }
 | |
| 
 | |
| static inline int template_callback_true(unpack_user* u, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_BOOL(*o, 1); return 0; }
 | |
| 
 | |
| static inline int template_callback_false(unpack_user* u, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); ZVAL_BOOL(*o, 0); return 0;}
 | |
| 
 | |
| static inline int template_callback_array(unpack_user* u, unsigned int n, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); array_init(*o); return 0; }
 | |
| 
 | |
| static inline int template_callback_array_item(unpack_user* u, msgpack_unpack_object* c, msgpack_unpack_object o)
 | |
| { add_next_index_zval(*c, o); return 0; }
 | |
| 
 | |
| static inline int template_callback_map(unpack_user* u, unsigned int n, msgpack_unpack_object* o)
 | |
| { ALLOC_INIT_ZVAL(*o); array_init(*o); return 0; }
 | |
| 
 | |
| static inline int template_callback_map_item(unpack_user* u, msgpack_unpack_object* c, msgpack_unpack_object k, msgpack_unpack_object v)
 | |
| {
 | |
| 	switch(k->type) {
 | |
| 		case IS_LONG:
 | |
| 	   	    add_index_zval(*c, Z_LVAL(*k), v);
 | |
| 			break;
 | |
| 		case IS_STRING:
 | |
| 	   		add_assoc_zval_ex(*c, Z_STRVAL(*k), Z_STRLEN(*k)+1, v);
 | |
| 			break;
 | |
| 		default:
 | |
| 			zend_error(E_WARNING, "[msgpack] (php_msgpack_decode) illegal offset type, skip this decoding");
 | |
| 			break;
 | |
| 	}
 | |
|     return 0;
 | |
| }
 | |
| 			
 | |
| 
 | |
| static inline int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_unpack_object* o)
 | |
| {
 | |
| 	ALLOC_INIT_ZVAL(*o);
 | |
| 	if (l == 0) {
 | |
| 		ZVAL_STRINGL(*o, "", 0, 1);
 | |
| 	} else {
 | |
| 		ZVAL_STRINGL(*o, p, l, 1);
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| #include "msgpack/unpack_template.h"
 | |
| 
 | |
| static PHP_GINIT_FUNCTION(msgpack);
 | |
| 
 | |
| ZEND_DECLARE_MODULE_GLOBALS(msgpack)
 | |
| 
 | |
| /* True global resources - no need for thread safety here */
 | |
| static int le_msgpack;
 | |
| 
 | |
| /* {{{ msgpack_functions[]
 | |
|  *
 | |
|  * Every user visible function must have an entry in msgpack_functions[].
 | |
|  */
 | |
| zend_function_entry msgpack_functions[] = {
 | |
| 	PHP_FE(msgpack_pack, NULL)
 | |
| 	PHP_FE(msgpack_unpack, NULL)
 | |
| 	PHP_FE(msgpack_unpack_limit, NULL)
 | |
| 	PHP_ME(msgpack, initialize, NULL, 0)
 | |
| 	PHP_ME(msgpack, execute, NULL, 0)
 | |
| 	PHP_ME(msgpack, execute_limit, NULL, 0)
 | |
| 	PHP_ME(msgpack, finished, NULL, 0)
 | |
| 	PHP_ME(msgpack, data, NULL, 0)
 | |
| 	{NULL, NULL, NULL}	/* Must be the last line in msgpack_functions[] */
 | |
| };
 | |
| /* }}} */
 | |
| 
 | |
| /* {{{ msgpack_module_entry
 | |
|  */
 | |
| zend_module_entry msgpack_module_entry = {
 | |
| #if ZEND_MODULE_API_NO >= 20010901
 | |
| 	STANDARD_MODULE_HEADER,
 | |
| #endif
 | |
| 	"msgpack",
 | |
| 	msgpack_functions,
 | |
| 	PHP_MINIT(msgpack),
 | |
| 	PHP_MSHUTDOWN(msgpack),
 | |
| 	PHP_RINIT(msgpack),		/* Replace with NULL if there's nothing to do at request start */
 | |
| 	PHP_RSHUTDOWN(msgpack),	/* Replace with NULL if there's nothing to do at request end */
 | |
| 	PHP_MINFO(msgpack),
 | |
| #if ZEND_MODULE_API_NO >= 20010901
 | |
| 	"0.1", /* Replace with version number for your extension */
 | |
| #endif
 | |
| 	PHP_MODULE_GLOBALS(msgpack),
 | |
| 	PHP_GINIT(msgpack),
 | |
| 	NULL,
 | |
| 	NULL,
 | |
| 	STANDARD_MODULE_PROPERTIES_EX
 | |
| };
 | |
| /* }}} */
 | |
| 
 | |
| #ifdef COMPILE_DL_MSGPACK
 | |
| ZEND_GET_MODULE(msgpack)
 | |
| #endif
 | |
| 
 | |
| /* {{{ PHP_GINIT_FUNCTION */
 | |
| static PHP_GINIT_FUNCTION(msgpack)
 | |
| {
 | |
| 	msgpack_globals->global_mp = NULL;
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| /* {{{ PHP_MINIT_FUNCTION
 | |
|  */
 | |
| PHP_MINIT_FUNCTION(msgpack)
 | |
| {
 | |
| 	zend_class_entry ce;
 | |
| 	INIT_CLASS_ENTRY(ce, "MessagePack", msgpack_functions);
 | |
| 	msgpack_ce = zend_register_internal_class(&ce TSRMLS_CC);
 | |
| 
 | |
| 	return SUCCESS;
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| /* {{{ PHP_MSHUTDOWN_FUNCTION
 | |
|  */
 | |
| PHP_MSHUTDOWN_FUNCTION(msgpack)
 | |
| {
 | |
| 	/* uncomment this line if you have INI entries
 | |
| 	UNREGISTER_INI_ENTRIES();
 | |
| 	*/
 | |
| 	if (MSGPACK_G(global_mp)) {
 | |
| 		efree(MSGPACK_G(global_mp));
 | |
| 		MSGPACK_G(global_mp) = NULL;
 | |
| 	}
 | |
| 
 | |
| 	return SUCCESS;
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| /* Remove if there's nothing to do at request start */
 | |
| /* {{{ PHP_RINIT_FUNCTION
 | |
|  */
 | |
| PHP_RINIT_FUNCTION(msgpack)
 | |
| {
 | |
| 	return SUCCESS;
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| /* Remove if there's nothing to do at request end */
 | |
| /* {{{ PHP_RSHUTDOWN_FUNCTION
 | |
|  */
 | |
| PHP_RSHUTDOWN_FUNCTION(msgpack)
 | |
| {
 | |
| 	return SUCCESS;
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| /* {{{ PHP_MINFO_FUNCTION
 | |
|  */
 | |
| PHP_MINFO_FUNCTION(msgpack)
 | |
| {
 | |
| 	php_info_print_table_start();
 | |
| 	php_info_print_table_header(2, "msgpack support", "enabled");
 | |
| 	php_info_print_table_row(2, "php extension version", PHP_EXT_VERSION);
 | |
| 	php_info_print_table_row(2, "author", "Hideyuki TAKEI");
 | |
| 	php_info_print_table_row(2, "homepage", "http://msgpack.sourceforge.net");
 | |
| 	php_info_print_table_row(2, "open sourced by", "KLab inc.");
 | |
| 	php_info_print_table_end();
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| PHP_MSGPACK_API int msgpack_determine_array_type(zval **val TSRMLS_DC)  /* {{{ */
 | |
| {
 | |
| 	int i;
 | |
| 	HashTable *myht = HASH_OF(*val);
 | |
| 
 | |
| 	i = myht ? zend_hash_num_elements(myht) : 0;
 | |
| 	if (i > 0) {
 | |
| 		char *key;
 | |
| 		ulong index, idx;
 | |
| 		uint key_len;
 | |
| 		HashPosition pos;
 | |
| 
 | |
| 		zend_hash_internal_pointer_reset_ex(myht, &pos);
 | |
| 		idx = 0;
 | |
| 		for (;; zend_hash_move_forward_ex(myht, &pos)) {
 | |
| 			i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
 | |
| 			if (i == HASH_KEY_NON_EXISTANT)
 | |
| 				break;
 | |
| 			if (i == HASH_KEY_IS_STRING) {
 | |
| 				return 1;
 | |
| 			} else {
 | |
| 				if (index != idx) {
 | |
| 					return 1;
 | |
| 				}
 | |
| 			}
 | |
| 			idx++;
 | |
| 		}
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| PHP_MSGPACK_API void msgpack_pack_array_hash(smart_str *pk, zval **val TSRMLS_DC) /* {{{ */	
 | |
| {
 | |
| 	int i, r;
 | |
| 	HashTable *myht;
 | |
| 
 | |
| 	if(Z_TYPE_PP(val) == IS_ARRAY){
 | |
| 		myht = HASH_OF(*val);
 | |
| 		r = msgpack_determine_array_type(val TSRMLS_CC);
 | |
| 	}
 | |
| 	else{
 | |
| 		myht = Z_OBJPROP_PP(val);
 | |
| 		r = 1;
 | |
| 	}
 | |
| 
 | |
| 	i = myht ? zend_hash_num_elements(myht) : 0;
 | |
| 
 | |
| 	if(r == 0){
 | |
| 		msgpack_pack_array(pk, i);
 | |
| 	}
 | |
| 	else{
 | |
| 		msgpack_pack_map(pk, i);
 | |
| 	}
 | |
| 
 | |
| 	if(i>0){
 | |
| 		char *key;
 | |
| 		zval **data;
 | |
| 		ulong index;
 | |
| 		uint key_len;
 | |
| 		HashPosition pos;
 | |
| 		HashTable *tmp_ht;
 | |
| 		int need_comma = 0;
 | |
| 
 | |
| 		zend_hash_internal_pointer_reset_ex(myht, &pos);
 | |
| 		for(;; zend_hash_move_forward_ex(myht, &pos)){
 | |
| 			i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos);
 | |
| 			if(i==HASH_KEY_NON_EXISTANT)
 | |
| 				break;
 | |
| 			if(zend_hash_get_current_data_ex(myht, (void **) &data, &pos) == SUCCESS){
 | |
| 				tmp_ht = HASH_OF(*data);
 | |
| 				if (tmp_ht)
 | |
| 					tmp_ht->nApplyCount++;
 | |
| 
 | |
| 				if(r==0)
 | |
| 					php_msgpack_pack(pk, *data TSRMLS_CC);
 | |
| 				else if(r==1){
 | |
| 					if(i==HASH_KEY_IS_STRING){
 | |
| 						if(key[0]=='\0' && Z_TYPE_PP(val)==IS_OBJECT){
 | |
| 							// Skip protected and private members.
 | |
| 							if(tmp_ht)
 | |
| 								tmp_ht->nApplyCount--;
 | |
| 							continue;
 | |
| 						}
 | |
| 						msgpack_pack_raw(pk, key_len-1);
 | |
| 						msgpack_pack_raw_body(pk, key, key_len-1);
 | |
| 						php_msgpack_pack(pk, *data TSRMLS_CC);
 | |
| 					}
 | |
| 					else{
 | |
| 						msgpack_pack_long(pk, index);
 | |
| 						php_msgpack_pack(pk, *data TSRMLS_CC);
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				if(tmp_ht){
 | |
| 					tmp_ht->nApplyCount--;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| PHP_MSGPACK_API void php_msgpack_pack(smart_str *pk, zval *val TSRMLS_DC) /* {{{ */
 | |
| {
 | |
| 	switch(Z_TYPE_P(val)){
 | |
| 		case IS_NULL:
 | |
| 			msgpack_pack_nil(pk);
 | |
| 			break;
 | |
| 		case IS_BOOL:
 | |
| 			if (Z_BVAL_P(val))
 | |
| 				msgpack_pack_true(pk);
 | |
| 			else
 | |
| 				msgpack_pack_false(pk);
 | |
| 			break;
 | |
| 		case IS_LONG:
 | |
| 			msgpack_pack_long(pk, Z_LVAL_P(val));
 | |
| 			break;
 | |
| 		case IS_DOUBLE:
 | |
| 			{
 | |
| 				double dbl = Z_DVAL_P(val);
 | |
| 				if (zend_isinf(dbl) || zend_isnan(dbl)) {
 | |
| 					zend_error(E_WARNING, "[msgpack] (php_msgpack_pack) double %.9g does not conform to the MSGPACK spec, encoded as 0", dbl);
 | |
| 					ZVAL_LONG(val, 0);
 | |
| 				}
 | |
| 				msgpack_pack_double(pk, Z_DVAL_P(val));
 | |
| 			}
 | |
| 			break;
 | |
| 		case IS_STRING:
 | |
| 			msgpack_pack_raw(pk, Z_STRLEN_P(val));
 | |
| 			msgpack_pack_raw_body(pk, Z_STRVAL_P(val), Z_STRLEN_P(val));
 | |
| 			break;
 | |
| 		case IS_ARRAY:
 | |
| 		case IS_OBJECT:
 | |
| 			msgpack_pack_array_hash(pk, &val TSRMLS_CC);
 | |
| 			break;
 | |
| 		defalut:
 | |
| 			zend_error(E_WARNING, "[msgpack] (php_msgpack_pack) type is unsupported, encoded as null");
 | |
| 			msgpack_pack_nil(pk);
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	return;
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| PHP_MSGPACK_API void php_msgpack_unpack_limit(zval *return_value, const char *buf, int len, zend_bool assoc TSRMLS_DC) /* {{{ */
 | |
| {
 | |
| 	if (len<=0) {
 | |
| 		RETURN_NUL();
 | |
| 	}
 | |
| 
 | |
| 	msgpack_unpack_t mp;
 | |
| 	template_init(&mp);
 | |
| 	unpack_user u = {0, ""};
 | |
| 
 | |
| 	size_t from = 0;
 | |
| 	char* dptr = (char*)buf;
 | |
| 	long dlen = len;
 | |
| 	int ret;
 | |
| 
 | |
| 	(&mp)->user.source = (char*)buf;
 | |
| 	ret = template_execute(&mp, dptr, (size_t)dlen, &from);
 | |
| 	(&mp)->user.source = "";
 | |
| 
 | |
| 	if(ret < 0) {
 | |
| 		zend_error(E_WARNING, "[msgpack] (php_msgpack_unpack) parse error");
 | |
| 	} else if(ret == 0) {
 | |
| 		zend_error(E_WARNING, "[msgpack] (php_msgpack_unpack) insufficient bytes");
 | |
| 	} else {
 | |
| 		if(from < dlen) {
 | |
| 			zend_error(E_WARNING, "[msgpack] (php_msgpack_unpack) extra bytes");
 | |
| 		}
 | |
| 
 | |
| 		*return_value = *template_data(&mp);
 | |
| 		FREE_ZVAL(template_data(&mp));
 | |
| 	}
 | |
| }	
 | |
| /* }}} */
 | |
| 
 | |
| 
 | |
| PHP_FUNCTION(msgpack_pack)
 | |
| {
 | |
| 	zval *parameter;
 | |
| 	smart_str buf = {0};
 | |
| 
 | |
| 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	php_msgpack_pack(&buf, parameter TSRMLS_CC);
 | |
| 
 | |
| 	ZVAL_STRINGL(return_value, buf.c, buf.len, 1);
 | |
| 
 | |
| 	smart_str_free(&buf);
 | |
| }
 | |
| 
 | |
| PHP_FUNCTION(msgpack_unpack)
 | |
| {
 | |
| 	char *parameter;
 | |
| 	int parameter_len;
 | |
| 	zend_bool assoc = 0;
 | |
| 
 | |
| 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b",
 | |
| 	   ¶meter, ¶meter_len, &assoc) == FAILURE) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (!parameter_len) {
 | |
| 		RETURN_NULL();
 | |
| 	}
 | |
| 
 | |
| 	php_msgpack_unpack_limit(return_value, parameter, parameter_len, assoc TSRMLS_CC);
 | |
| }
 | |
| 
 | |
| PHP_FUNCTION(msgpack_unpack_limit)
 | |
| {
 | |
| 	char *parameter;
 | |
| 	int parameter_len;
 | |
| 	int limit;
 | |
| 	zend_bool assoc = 0;
 | |
| 
 | |
| 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|b",
 | |
| 	   ¶meter, ¶meter_len, &limit, &assoc) == FAILURE) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (!parameter_len) {
 | |
| 		RETURN_NULL();
 | |
| 	}
 | |
| 	else if (parameter_len < limit) {
 | |
| 		zend_error(E_WARNING, "[msgpack] (php_msgpack_unpack) limit greater than data_len");
 | |
| 		limit = parameter_len;
 | |
| 	}
 | |
| 
 | |
| 	php_msgpack_unpack_limit(return_value, parameter, limit, assoc TSRMLS_CC);
 | |
| }
 | |
| 
 | |
| 
 | |
| PHP_MSGPACK_API void php_msgpack_unpacker_execute_limit(zval *return_value, const char *buf, int off, int len, zend_bool assoc TSRMLS_DC) /* {{{ */
 | |
| {
 | |
| 	if (len<=0) {
 | |
| 		RETURN_NUL();
 | |
| 	}
 | |
| 
 | |
| 	size_t from = off;
 | |
| 	char* dptr = (char*)buf;
 | |
| 	long dlen = len;
 | |
| 	int ret;
 | |
| 
 | |
| 	if(from >= dlen) {
 | |
| 		zend_error(E_WARNING, "[msgpack] (php_msgpack_unpacker_execute_limit) offset is bigger than data buffer size");
 | |
|     }
 | |
| 
 | |
| 	MSGPACK_G(global_mp)->user.source = (char*)buf;
 | |
| 	ret = template_execute(MSGPACK_G(global_mp), dptr, (size_t)dlen, &from);
 | |
| 	MSGPACK_G(global_mp)->user.source = "";
 | |
| 
 | |
| 	if(ret < 0) {
 | |
| 		zend_error(E_WARNING, "[msgpack] (php_msgpack_unpacker_execute_limit) parse error");
 | |
| 	} else if(ret > 0) {
 | |
| 		MSGPACK_G(global_mp)->user.finished = 1;
 | |
| 		RETVAL_LONG(from);
 | |
| 	} else {
 | |
| 		MSGPACK_G(global_mp)->user.finished = 0;
 | |
| 		RETVAL_LONG(from);
 | |
| 	}
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| PHP_MSGPACK_API void php_msgpack_unpacker_reset(TSRMLS_D) /* {{{ */
 | |
| {
 | |
| 	if(MSGPACK_G(global_mp)) {
 | |
| 		efree(MSGPACK_G(global_mp));
 | |
| 		MSGPACK_G(global_mp) = NULL;
 | |
| 	}
 | |
| 	MSGPACK_G(global_mp) = safe_emalloc(sizeof(msgpack_unpack_t), 1, 0);
 | |
| 
 | |
| 	template_init(MSGPACK_G(global_mp));
 | |
| 	unpack_user u = {0, ""};
 | |
| 	MSGPACK_G(global_mp)->user = u;
 | |
| 	return;
 | |
| }
 | |
| /* }}} */
 | |
| 
 | |
| PHP_METHOD(msgpack, initialize)
 | |
| {
 | |
| 	php_msgpack_unpacker_reset(TSRMLS_C);
 | |
| 	return;
 | |
| }
 | |
| 
 | |
| PHP_METHOD(msgpack, execute)
 | |
| {
 | |
| 	char *data;
 | |
| 	int off;
 | |
| 	int data_len;
 | |
| 	zend_bool assoc = 0;
 | |
| 
 | |
| 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|b",
 | |
| 	   &data, &data_len, &off, &assoc) == FAILURE) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (!data_len) {
 | |
| 		RETURN_NULL();
 | |
| 	}
 | |
| 
 | |
| 	php_msgpack_unpacker_execute_limit(return_value, data, off, data_len, assoc TSRMLS_CC);
 | |
| }
 | |
| 
 | |
| PHP_METHOD(msgpack, execute_limit)
 | |
| {
 | |
| 	char *data;
 | |
| 	int off;
 | |
| 	int data_len;
 | |
| 	int limit;
 | |
| 	zend_bool assoc = 0;
 | |
| 
 | |
| 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll|b",
 | |
| 	   &data, &data_len, &off, &limit, &assoc) == FAILURE) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (!data_len) {
 | |
| 		RETURN_NULL();
 | |
| 	}
 | |
| 	else if (data_len < limit) {
 | |
| 		zend_error(E_WARNING, "[msgpack] (php_msgpack_unpack) limit greater than (data+off)_len");
 | |
| 		limit = data_len;
 | |
| 	}
 | |
| 
 | |
| 	php_msgpack_unpacker_execute_limit(return_value, data, off, limit, assoc TSRMLS_CC);
 | |
| }
 | |
| 
 | |
| PHP_METHOD(msgpack, finished)
 | |
| {
 | |
| 	if(MSGPACK_G(global_mp)->user.finished == 1) {
 | |
| 		RETURN_TRUE;
 | |
| 	}
 | |
| 	RETURN_FALSE;
 | |
| }
 | |
| 
 | |
| PHP_METHOD(msgpack, data)
 | |
| {
 | |
| 	*return_value = *template_data(MSGPACK_G(global_mp));
 | |
| 	return;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Local variables:
 | |
|  * tab-width: 4
 | |
|  * c-basic-offset: 4
 | |
|  * End:
 | |
|  * vim600: noet sw=4 ts=4 fdm=marker
 | |
|  * vim<600: noet sw=4 ts=4
 | |
|  */
 | 
