PHP内核分析-Zend引擎-栈结构及操作

Zend引擎对栈常量的定义:
#define ZEND_STACK_APPLY_TOPDOWN    1	//由顶部向底部对栈进行遍历操作
#define ZEND_STACK_APPLY_BOTTOMUP   2	//由底部向顶部对栈进行遍历操作
#define STACK_BLOCK_SIZE 64  //每次扩容的元素个数

看一下Zend引擎栈的数据结构定义:
typedef struct _zend_stack {
    int top;		//栈顶,用数字表示(从底到顶分别为0,1,2...)
    int max;		//栈当前最大元素个数,当栈满后会将max+STACK_BLOCK_SZE来进行扩容
    void **elements;	//栈元素指针数组
} zend_stack;

栈的常用操作如下:

//初始化栈,不包含zend_stack结构的内存分配。仅初始化top, max的值和elements的值。
ZEND_API int zend_stack_init(zend_stack *stack)
{
    stack->top = 0;
    stack->max = 0;
    stack->elements = NULL;
    return SUCCESS;
}

//以memcpy的方式将element元素复制入栈。size表示元素的大小。
ZEND_API int zend_stack_push(zend_stack *stack, const void *element, int size)
{
    if (stack->top >= stack->max) {     /* we need to allocate more memory */
        stack->elements = (void **) erealloc(stack->elements,
                   (sizeof(void **) * (stack->max += STACK_BLOCK_SIZE)));
	//当栈满后会将max+STACK_BLOCK_SZE来进行扩容
        if (!stack->elements) {
            return FAILURE;
        }
    }
    stack->elements[stack->top] = (void *) emalloc(size);
    memcpy(stack->elements[stack->top], element, size);
    return stack->top++;
}

//获取栈顶部元素的指针,并赋值给**element
ZEND_API int zend_stack_top(const zend_stack *stack, void **element)
{
    if (stack->top > 0) {
        *element = stack->elements[stack->top - 1];
        return SUCCESS;
    } else {
        *element = NULL;
        return FAILURE;
    }
}

//删除栈顶。
ZEND_API int zend_stack_del_top(zend_stack *stack)
{
    if (stack->top > 0) {
        efree(stack->elements[--stack->top]);
    }
    return SUCCESS;
}

//返回栈顶元素的指针的值
ZEND_API int zend_stack_int_top(const zend_stack *stack)
{
    int *e;

    if (zend_stack_top(stack, (void **) &e) == FAILURE) {
        return FAILURE;         /* this must be a negative number, since negative numbers can't be address numbers */
    } else {
        return *e;
    }
}

//根据stack->top的值来判断栈是否为空.stack->top用数字来表示的好处。
ZEND_API int zend_stack_is_empty(const zend_stack *stack)
{
    if (stack->top == 0) {
        return 1;
    } else {
        return 0;
    }
}

//销毁栈。其实也可以while(stack->top--){zend_stack_del_top(stack)};stack->elements = NULL;
ZEND_API int zend_stack_destroy(zend_stack *stack)
{
    int i;

    if (stack->elements) {
        for (i = 0; i < stack->top; i++) {
            efree(stack->elements[i]);
        }
        efree(stack->elements);
        stack->elements = NULL;
    }

    return SUCCESS;
}

//直接返回栈数据元素指针
ZEND_API void **zend_stack_base(const zend_stack *stack)
{
    return stack->elements;
}

//返回栈元素个数。这就是用数字来表示栈顶而不直接用指针来表示的好处。
ZEND_API int zend_stack_count(const zend_stack *stack)
{
    return stack->top;
}

//遍历栈并执行函数。注意,传入的函数返回值为int型。为0时表示函数执行成功,为1时表示函数执行失败。
ZEND_API void zend_stack_apply(zend_stack *stack, int type, int (*apply_function)(void *element))
{
    int i;

    switch (type) {
	//自顶向下执行
        case ZEND_STACK_APPLY_TOPDOWN:
            for (i=stack->top-1; i>=0; i--) {
                if (apply_function(stack->elements[i])) {
                    break;
                }
            }
            break;
	//自底向上执行
        case ZEND_STACK_APPLY_BOTTOMUP:
            for (i=0; i<stack->top; i++) {
                if (apply_function(stack->elements[i])) {
                    break;
                }
            }
            break;
    }
}

//与zend_stack_apply函数一样,都是遍历栈并执行函数。但此函数支持调用函数传递参数。
ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg)
{
    int i;

    switch (type) {
        case ZEND_STACK_APPLY_TOPDOWN:
            for (i=stack->top-1; i>=0; i--) {
                if (apply_function(stack->elements[i], arg)) {
                    break;
                }
            }
            break;
        case ZEND_STACK_APPLY_BOTTOMUP:
            for (i=0; i<stack->top; i++) {
                if (apply_function(stack->elements[i], arg)) {
                    break;
                }
            }
            break;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值