Following the previous post about Queues, In this post i publish a simple modular stack written in C which can be used either by assigning a static space for the elements of a dynamic one (malloc etc).
In computer science, a stack is an abstract data type that serves as a collection of elements, with two principal operations:
- push, which adds an element to the collection, and
- pop, which removes the most recently added element that was not yet removed.
The order in which elements come off a stack gives rise to its alternative name, LIFO (last in, first out). Additionally, a peek operation may give access to the top without modifying the stack.
/****************************************************************************** * SOF - Header | By: Io.D ******************************************************************************/ #ifndef LIBRARIES_IQUEUE_H_ /****************************************************************************** * Definitions ******************************************************************************/ #define LIBRARIES_IQUEUE_H_ /****************************************************************************** * Includes ******************************************************************************/ #include <stdint.h> #include <string.h> /****************************************************************************** * Enumerations, structures & External Variables ******************************************************************************/ typedef enum { I_OK = 0x00, I_ERROR = 0x01, I_FULL = 0x60, I_EMPTY = 0x61 }I_Status_Stack; typedef struct { volatile void * storage; volatile void * last; volatile void * next; volatile size_t element_size; volatile uint32_t max_elements; } istack_t; /****************************************************************************** * Public Functions (API) ******************************************************************************/ I_Status_Stack istack_init(istack_t * _stack, int _max_elements, size_t _element_size, void * _storage); I_Status_Stack istack_push(istack_t * _stack, void * _element); I_Status_Stack istack_pop(istack_t * _stack, void * _element); I_Status_Stack istack_size(istack_t * _stack, uint32_t * _size); /****************************************************************************** * EOF - Header ******************************************************************************/ #endif
/****************************************************************************** * SOF - Source | By: Io.D ******************************************************************************/ /****************************************************************************** * Includes ******************************************************************************/ #include "istack.h" /****************************************************************************** * Declarations ******************************************************************************/ /****************************************************************************** * Public functions ******************************************************************************/ I_Status_Stack istack_init(istack_t * _stack, int _max_elements, size_t _element_size, void * _storage) { if (_stack == NULL) return I_ERROR; memset(_storage, 0x00, _element_size*_max_elements); _stack->element_size = _element_size; _stack->max_elements = _max_elements; _stack->storage = _storage; _stack->last = (void *)0; _stack->next = (uint8_t *)_stack->storage + ((_max_elements - 1) * _element_size); return I_OK; } I_Status_Stack istack_push(istack_t * _stack, void * _element) { if (_stack->last == _stack->next) return I_FULL; memmove((void*)_stack->next, (void*)_element, _stack->element_size); _stack->last = _stack->last == (void*)0 ? _stack->next : _stack->last; _stack->next = (uint8_t *)_stack->next == (uint8_t *)_stack->storage ? (uint8_t *)_stack->storage + ((_stack->max_elements - 1) * _stack->element_size) : (uint8_t *)_stack->next - _stack->element_size; return I_OK; } I_Status_Stack istack_pop(istack_t * _stack, void * _element) { if (_stack->last == (void*)0) return I_EMPTY; _stack->next = (uint8_t *)_stack->next == (uint8_t *)_stack->storage + ((_stack->max_elements - 1) * _stack->element_size) ? (uint8_t *)_stack->storage : (uint8_t *)_stack->next + _stack->element_size; memmove((void*)_element, (void*)_stack->next, _stack->element_size); memset((uint8_t*)_stack->next, 0x00, _stack->element_size); _stack->last = _stack->last == _stack->next ? (void*)0 : _stack->last; return I_OK; } I_Status_Stack istack_size(istack_t * _stack, uint32_t * _size) { *_size = _stack->last == (void*)0 ? 0 : _stack->last > _stack->next ? ((uintptr_t)_stack->last - (uintptr_t)_stack->next) / _stack->element_size : _stack->max_elements - (((uintptr_t)_stack->next - (uintptr_t)_stack->last) / _stack->element_size); return I_OK; } /****************************************************************************** * Static functions ******************************************************************************/ /****************************************************************************** * EOF - Source ******************************************************************************/
Usage:
// Create a stack handle istack_t stack; // Set a memory space to save the elements uint32_t storage[5]; // Initialize the stack istack_init(&stack, 5, sizeof(uint32_t), storage); .. .. // Add an element uint32_t element = 31; if (istack_push(&stack, &element) == I_FULL) { // Stack is full condition } .. .. // Retrieve an element uint32_t element; if (istack_pop(&stack, &element) == I_EMPTY) { // Stack is full empty } .. .. // Get the size uint32_t size; istack_size(&stack, &size);