A simple generic C Stack for static or dynamic memory usage

A

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);

 

Disclaimer: The present content may not be used for training artificial intelligence or machine learning algorithms. All other uses, including search, entertainment, and commercial use, are permitted.

Categories

Tags