BinaryStack

Interface to a stack which supports objects of differing size.

Summary
BinaryStackInterface to a stack which supports objects of differing size.
CopyrightThis program is free software.
Files
C-kern/api/ds/inmem/binarystack.hHeader file BinaryStack.
C-kern/ds/inmem/binarystack.cImplementation file BinaryStack impl.
Types
struct binarystack_tExport binarystack_t into global namespace.
Functions
test
unittest_ds_inmem_binarystackTest binarystack_t functionality.
binarystack_tStores binary data in LIFO order.
freeblocksizeThe number of free bytes of memory block blockstart points to.
blocksizeSize in bytes of allocated memory block blockstart points to.
blockstartStart address of latest allocated memory block.
lifetime
binarystack_FREEStatic initializer.
init_binarystackInitializes stack object and reserves at least preallocate_size bytes.
free_binarystackFrees memory resources held by stack.
query
isempty_binarystackReturns true if stack contains no more data.
size_binarystackReturns the size of all pushed objects.
top_binarystackReturns the start address in memory of the last pushed object.
change
pop_binarystackRemoves the last pushed object from the stack.
push_binarystackAllocates memory for new object and returns pointer to its start address.
pop2_binarystackSame functionality as pop_binarystack.
push2_binarystackDoes same as push_binarystack but allocates a new block if necessary.
inline implementation
Macros
isempty_binarystackImplements binarystack_t.isempty_binarystack.
pop_binarystackImplements binarystack_t.pop_binarystack.
push_binarystackImplements binarystack_t.push_binarystack.
top_binarystackImplements binarystack_t.top_binarystack.

Copyright

This program is free software.  You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

Author

© 2012 Jörg Seebohn

Files

C-kern/api/ds/inmem/binarystack.h

Header file BinaryStack.

C-kern/ds/inmem/binarystack.c

Implementation file BinaryStack impl.

Types

struct binarystack_t

typedef struct binarystack_t binarystack_t

Export binarystack_t into global namespace.

Functions

test

unittest_ds_inmem_binarystack

int unittest_ds_inmem_binarystack(void)

Test binarystack_t functionality.

binarystack_t

struct binarystack_t

Stores binary data in LIFO order.

This implementation tries to avoid any additional memory copy operations.  Therefore the caller gets a pointer to the last pushed object as result.  This pointer is considered valid as long the object is not popped off the stack.

Therefore calling additonal push_binarystack and corresponding pop_binarystack keeps this pointer valid.  Calling free_binarystack does invalidate the pointer.

Operations

PushYou can push size bytes to the top of stack.  This operation only allocates memory and returns a pointer to it.  You need to initialize the content of the pushed object after it has been pushed.
PopRemoves size bytes from top of stack.  To access the new top of stack (start address of a previously pushed object) call top_binarystack.

Memory Alignment

If you push an object of size X the address of the next pushed object is aligned to size X.  So if you need to align memory to number X make sure that every push operation pushes only objects with sizes which are multiples of X.  The first pushed object is page aligned (see pagesize_vm).

Summary
freeblocksizeThe number of free bytes of memory block blockstart points to.
blocksizeSize in bytes of allocated memory block blockstart points to.
blockstartStart address of latest allocated memory block.
lifetime
binarystack_FREEStatic initializer.
init_binarystackInitializes stack object and reserves at least preallocate_size bytes.
free_binarystackFrees memory resources held by stack.
query
isempty_binarystackReturns true if stack contains no more data.
size_binarystackReturns the size of all pushed objects.
top_binarystackReturns the start address in memory of the last pushed object.
change
pop_binarystackRemoves the last pushed object from the stack.
push_binarystackAllocates memory for new object and returns pointer to its start address.
pop2_binarystackSame functionality as pop_binarystack.
push2_binarystackDoes same as push_binarystack but allocates a new block if necessary.

freeblocksize

uint32_t freeblocksize

The number of free bytes of memory block blockstart points to.

blocksize

uint32_t blocksize

Size in bytes of allocated memory block blockstart points to.

blockstart

uint8_t * blockstart

Start address of latest allocated memory block.  The size of this block is stored in blocksize.

lifetime

binarystack_FREE

#define binarystack_FREE { 0, 0, 0 }

Static initializer.

init_binarystack

int init_binarystack(/*out*/binarystack_t *stack,
uint32_t preallocate_size)

Initializes stack object and reserves at least preallocate_size bytes.

free_binarystack

int free_binarystack(binarystack_t *stack)

Frees memory resources held by stack.  All pointers into the stack become invalid.

query

isempty_binarystack

int isempty_binarystack(const binarystack_t *stack)

Returns true if stack contains no more data.

size_binarystack

size_t size_binarystack(binarystack_t *stack)

Returns the size of all pushed objects.  The runtime of the function depends on the number of allocated block.  So do not use this function in a inner loop.  Instead use your own counter.

top_binarystack

void * top_binarystack(binarystack_t *stack)

Returns the start address in memory of the last pushed object.  The returned address is the lowest address of the allocated memory space.

The returned pointer is never NULL.  Even if the stack is empty.  So always check with isempty_binarystack if there is an element on the stack.

Use <at_binarystack> the get the address of an object who is not top on stack.

change

pop_binarystack

int pop_binarystack(binarystack_t *stack,
size_t size)

Removes the last pushed object from the stack.  The parameter size must be set to the size of the last pushed object to remove it from the stack.  If it is set to the sum of x last pushed objects then these x objects are removed from the stack at once.  Call top_binarystack to get the new address of the object on top of the stack.

Popping only part of the last pushed object shrinks the memory of it.  Use top_binarystack to get the new address of a partially shrinked object.  If size is bigger than size_binarystack the the error EINVAL is returned and nothing is done.  This function calls pop2_binarystack if one or more memory blocks have to be freed.

push_binarystack

int push_binarystack(binarystack_t *stack,
/*out*/void **lastpushed)

Allocates memory for new object and returns pointer to its start address.  The returned address is the lowest address of the allocated memory space.  This function is implemented as generic macro and the size of the newly pushed object is calculated as

size = sizeof(**lastpushed) ;

If not enough preallocated memory is available a call to push2_binarystack is made which allocates a new block of memory.  In case of an error ENOMEM is returned.

The memory is managed as a list of allocated blocks so the address of already pushed objects never change.

Parameter

stackbinary stack object.
lastpushedA pointer to pointer of a concrete type whose newly allocated address is returned.  The allocated memory space contains random data.  The size of the object is determined from its type (see above).

pop2_binarystack

int pop2_binarystack(binarystack_t *stack,
size_t size)

Same functionality as pop_binarystack.  This function is called from pop_binarystack in case one or more memory blocks must be freed.

Attention

If the memory subsystem returns an error this function returns this error.  But it continues the work until size bytes are popped off the stack.  The reason is that the error can occur any time after some blocks have already been freed.  So doing nothing in case of an error does not work here.

push2_binarystack

int push2_binarystack(binarystack_t *stack,
uint32_t size,
/*out*/uint8_t **lastpushed)

Does same as push_binarystack but allocates a new block if necessary.  This function is called from push_binarystack in case a new memory must be allocated.  Do not call this function - always use push_binarystack.

Macros

isempty_binarystack

#define isempty_binarystack(
   stack
) ((stack)->freeblocksize == (stack)->blocksize)

Implements binarystack_t.isempty_binarystack.

pop_binarystack

#define pop_binarystack(
   stack,
   size
) ( __extension__ ({ int _err ; binarystack_t * _stack = (stack) ; uint32_t _size = (size) ; if (_stack->blocksize - _stack->freeblocksize > _size) { _stack->freeblocksize += _size ; _err = 0 ; } else { _err = pop2_binarystack(_stack, _size) ; } _err ; }))

Implements binarystack_t.pop_binarystack.

push_binarystack

top_binarystack

#define top_binarystack(
   stack
) ((void*)(&(stack)->blockstart[(stack)->freeblocksize]))

Implements binarystack_t.top_binarystack.

Interface to a stack which supports objects of differing size.
Implements BinaryStack.
typedef struct binarystack_t binarystack_t
Export binarystack_t into global namespace.
struct binarystack_t
Stores binary data in LIFO order.
int unittest_ds_inmem_binarystack(void)
Test binarystack_t functionality.
uint32_t freeblocksize
The number of free bytes of memory block blockstart points to.
uint8_t * blockstart
Start address of latest allocated memory block.
uint32_t blocksize
Size in bytes of allocated memory block blockstart points to.
#define binarystack_FREE { 0, 0, 0 }
Static initializer.
int init_binarystack(/*out*/binarystack_t *stack,
uint32_t preallocate_size)
Initializes stack object and reserves at least preallocate_size bytes.
int free_binarystack(binarystack_t *stack)
Frees memory resources held by stack.
int isempty_binarystack(const binarystack_t *stack)
Returns true if stack contains no more data.
size_t size_binarystack(binarystack_t *stack)
Returns the size of all pushed objects.
void * top_binarystack(binarystack_t *stack)
Returns the start address in memory of the last pushed object.
int pop_binarystack(binarystack_t *stack,
size_t size)
Removes the last pushed object from the stack.
int push_binarystack(binarystack_t *stack,
/*out*/void **lastpushed)
Allocates memory for new object and returns pointer to its start address.
int pop2_binarystack(binarystack_t *stack,
size_t size)
Same functionality as pop_binarystack.
int push2_binarystack(binarystack_t *stack,
uint32_t size,
/*out*/uint8_t **lastpushed)
Does same as push_binarystack but allocates a new block if necessary.
#define isempty_binarystack(
   stack
) ((stack)->freeblocksize == (stack)->blocksize)
Implements binarystack_t.isempty_binarystack.
#define pop_binarystack(
   stack,
   size
) ( __extension__ ({ int _err ; binarystack_t * _stack = (stack) ; uint32_t _size = (size) ; if (_stack->blocksize - _stack->freeblocksize > _size) { _stack->freeblocksize += _size ; _err = 0 ; } else { _err = pop2_binarystack(_stack, _size) ; } _err ; }))
Implements binarystack_t.pop_binarystack.
#define top_binarystack(
   stack
) ((void*)(&(stack)->blockstart[(stack)->freeblocksize]))
Implements binarystack_t.top_binarystack.
uint32_t pagesize_vm(void)
Returns the virtual memory page size supported by the underlying system.
Close