php扩展开发-数组处理(二)

上篇文章主要介绍了一维数组的处理方法,使用ZEND API结合递归算法遍历处理多维数组也不是什么难事。处理多维数组首先要了解一下ZEND API:

MAKE_STD_ZVAL();//注册zval变量
SEPARATE_ZVAL_IF_NOT_REF()//如果没有分支则分离变量
add_assoc_string_ex//添加字符串数组元素

现需要开发一个PHP扩展,将多维数组元素url编码然后返回。修改mytools.c文件,添加函数(流程请参照上篇文章:php扩展开发-数组处理(一),这里不再赘述)。

static void php_array_urlencode(zval **array_input, zval *return_value, char *childkey TSRMLS_CC){
	char *key;
        uint key_len;
        ulong index;
        HashPosition pos;
        zval **data;
		zval *childvalue;

		MAKE_STD_ZVAL(childvalue);
		array_init(childvalue);

		for (
              zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(array_input), &pos);
             zend_hash_get_current_data_ex(Z_ARRVAL_PP(array_input), (void **) &data, &pos) == SUCCESS;
             zend_hash_move_forward_ex(Z_ARRVAL_PP(array_input), &pos)
        ) {


				if (zend_hash_get_current_key_ex(Z_ARRVAL_PP(array_input), &key, &key_len, &index, 0, &pos) != HASH_KEY_IS_STRING) {

					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Numeric keys are not allowed in the definition array");

					zval_dtor(return_value);

					RETURN_FALSE;

				}
				
				if (Z_ARRVAL_PP(data)->nApplyCount > 1) {
							return;
				}
	 
				if (Z_TYPE_PP(data) == IS_ARRAY) {
						SEPARATE_ZVAL_IF_NOT_REF(data);
						Z_ARRVAL_PP(data)->nApplyCount++;
						php_array_urlencode(data, return_value, key TSRMLS_CC);
						Z_ARRVAL_PP(data)->nApplyCount--;
				}else{
					SEPARATE_ZVAL(data);
					if (Z_TYPE_PP(data) == IS_OBJECT) {

						zend_class_entry *ce;

						ce = Z_OBJCE_PP(data);

						if (!ce->__tostring) {

							ZVAL_FALSE(*data);

							php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array's value contain object and can not be converted to string ");

							return;

						}

					}

		 
					convert_to_string(*data);

		 

					char *out_str;

					int str_len = strlen(Z_STRVAL_PP(data));

					int out_str_len;

					out_str = php_url_encode((const char*)(Z_STRVAL_PP(data)), str_len, &out_str_len);
					
					if(childkey != NULL){
						add_assoc_string_ex(childvalue, key, key_len, out_str, 1);
					}else{
						add_assoc_string_ex(return_value, key, key_len, out_str, 1);
					}
			}

	}


	childkey != NULL && add_assoc_zval_ex(return_value, childkey, strlen(childkey)+1, childvalue);
}


修改PHP_FUNCTION(array_urlencode)

PHP_FUNCTION(array_urlencode)
{
	zval **array_input;
	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &array_input) == FAILURE){ 
        return;
    }
	
	SEPARATE_ZVAL(array_input);
	if (Z_TYPE_PP(array_input) == IS_ARRAY) {
			array_init(return_value);
			php_array_urlencode(array_input, return_value, NULL TSRMLS_CC);
	}else{
			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter is not array type");
			return;
	}

}
处理多维数组和一位数组的原理一样,主要是遍历数组元素,处理后按原来的数据结构返回。在循环遍历数组的时候zend HashTable结构体中nApplyCount成员作为访问标志,防止对同一个HashTable同时进行多次遍历 。每次进入遍历函数时将nApplyCount值加1,退出遍历函数时将nApplyCount值减1。开始遍历之前如果发现nApplyCount > 3就直接报告错误信息并退出遍历。


如果您要转载此文章请注明出处:http://my.oschina.net/u/554660/blog/169630

转载于:https://my.oschina.net/u/554660/blog/169630

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值