#ifndef _UTIL_STACK_H #define _UTIL_STACK_H #include #include #include template struct Stack { T* base; T* top; size_t capacity; size_t inc_step; }; /** * @brief Initailize stack and allocate memory for it. * @param stack Stack * @param capacity Default capacity */ template bool init_stack(struct Stack& stack, size_t capacity = 1, size_t inc_step = 1) { if (inc_step < 1) inc_step = 1; if (capacity < 1) capacity = 1; stack.base = (T*)malloc(capacity * sizeof(T)); if (!stack.base) return false; stack.top = stack.base; stack.capacity = capacity; stack.inc_step = inc_step; return true; } template void free_stack(struct Stack& stack, std::function free_func = std::function()) { if (!stack.base) return; if (free_func) { stack_iter(stack, free_func); } free(stack.base); stack.base = nullptr; stack.top = nullptr; stack.capacity = 0; stack.inc_step = 0; } template inline void free_stack(struct Stack& stack, F free_func) { free_stack(stack, std::function(free_func)); } template void clear_stack(struct Stack& stack, std::function free_func = std::function()) { if (!stack.base) return; if (free_func) { stack_iter(stack, free_func); } stack.top = stack.base; } template inline void clear_stack(struct Stack& stack, F free_func) { clear_stack(stack, std::function(free_func)); } template bool stack_is_empty(struct Stack& stack) { if (!stack.base) return true; return stack.base == stack.top; } template size_t stack_length(struct Stack& stack) { if (!stack.base) return 0; return stack.top - stack.base; } template bool stack_get_top(struct Stack& stack, T& ele) { if (!stack.base) return false; if (stack.base == stack.top) return false; ele = *(stack.top - 1); return true; } template bool stack_push(struct Stack& stack, T ele) { if (!stack.base) return false; if (stack.top - stack.base >= stack.capacity) { T* obase = stack.base; stack.base = (T*)realloc(stack.base, (stack.capacity + stack.inc_step) * sizeof(T)); if (!stack.base) { /// Free original buffer free(obase); stack.top = nullptr; stack.capacity = 0; stack.inc_step = 0; return false; } stack.top = stack.base + stack.capacity; stack.capacity += stack.inc_step; } *(stack.top++) = ele; return true; } template bool stack_pop(struct Stack& stack, T& ele) { if (!stack.base) return false; if (stack.top == stack.base) return false; ele = *(--stack.top); return true; } template void stack_iter(struct Stack& stack, std::function callback, Args... args) { if (!stack.base || !callback) return; if (stack.top == stack.base) return; T* now = stack.top; while (now > stack.base) { now -= 1; callback(*now, args...); } } template inline void stack_iter(struct Stack& stack, F callback, Args... args) { stack_iter(stack, std::function(callback), args...); } #endif