LMMS
Loading...
Searching...
No Matches
stack.h
Go to the documentation of this file.
1/*
2 Copyright 2011-2020 David Robillard <d@drobilla.net>
3
4 Permission to use, copy, modify, and/or distribute this software for any
5 purpose with or without fee is hereby granted, provided that the above
6 copyright notice and this permission notice appear in all copies.
7
8 THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*/
16
17#ifndef SERD_STACK_H
18#define SERD_STACK_H
19
20#include <assert.h>
21#include <stdbool.h>
22#include <stddef.h>
23#include <stdint.h>
24#include <stdlib.h>
25
27#define SERD_STACK_BOTTOM sizeof(void*)
28
30typedef struct {
32 size_t buf_size;
33 size_t size;
34} SerdStack;
35
37#define SERD_STACK_BOTTOM sizeof(void*)
38
39static inline SerdStack
41{
42 SerdStack stack;
43 stack.buf = (uint8_t*)calloc(size, 1);
44 stack.buf_size = size;
45 stack.size = SERD_STACK_BOTTOM;
46 return stack;
47}
48
49static inline bool
51{
52 return stack->size <= SERD_STACK_BOTTOM;
53}
54
55static inline void
57{
58 free(stack->buf);
59 stack->buf = NULL;
60 stack->buf_size = 0;
61 stack->size = 0;
62}
63
64static inline void*
65serd_stack_push(SerdStack* stack, size_t n_bytes)
66{
67 const size_t new_size = stack->size + n_bytes;
68 if (stack->buf_size < new_size) {
69 stack->buf_size += (stack->buf_size >> 1); // *= 1.5
70 stack->buf = (uint8_t*)realloc(stack->buf, stack->buf_size);
71 }
72
73 uint8_t* const ret = (stack->buf + stack->size);
74
75 stack->size = new_size;
76 return ret;
77}
78
79static inline void
80serd_stack_pop(SerdStack* stack, size_t n_bytes)
81{
82 assert(stack->size >= n_bytes);
83 stack->size -= n_bytes;
84}
85
86static inline void*
87serd_stack_push_aligned(SerdStack* stack, size_t n_bytes, size_t align)
88{
89 // Push one byte to ensure space for a pad count
90 serd_stack_push(stack, 1);
91
92 // Push padding if necessary
93 const size_t pad = align - stack->size % align;
94 if (pad > 0) {
95 serd_stack_push(stack, pad);
96 }
97
98 // Set top of stack to pad count so we can properly pop later
99 assert(pad < UINT8_MAX);
100 stack->buf[stack->size - 1] = (uint8_t)pad;
101
102 // Push requested space at aligned location
103 return serd_stack_push(stack, n_bytes);
104}
105
106static inline void
107serd_stack_pop_aligned(SerdStack* stack, size_t n_bytes)
108{
109 // Pop requested space down to aligned location
110 serd_stack_pop(stack, n_bytes);
111
112 // Get amount of padding from top of stack
113 const uint8_t pad = stack->buf[stack->size - 1];
114
115 // Pop padding and pad count
116 serd_stack_pop(stack, pad + 1u);
117}
118
119#endif // SERD_STACK_H
#define NULL
Definition CarlaBridgeFormat.cpp:30
assert(0)
unsigned char uint8_t
Definition mid.cpp:98
static void serd_stack_pop(SerdStack *stack, size_t n_bytes)
Definition stack.h:80
static void serd_stack_free(SerdStack *stack)
Definition stack.h:56
static void * serd_stack_push_aligned(SerdStack *stack, size_t n_bytes, size_t align)
Definition stack.h:87
static bool serd_stack_is_empty(SerdStack *stack)
Definition stack.h:50
static void serd_stack_pop_aligned(SerdStack *stack, size_t n_bytes)
Definition stack.h:107
#define SERD_STACK_BOTTOM
Definition stack.h:27
static void * serd_stack_push(SerdStack *stack, size_t n_bytes)
Definition stack.h:65
static SerdStack serd_stack_new(size_t size)
Definition stack.h:40
Definition stack.h:30
size_t size
Conceptual size of stack in buf.
Definition stack.h:33
uint8_t * buf
Stack memory.
Definition stack.h:31
size_t buf_size
Allocated size of buf (>= size).
Definition stack.h:32
ulg size
Definition extract.c:2350