Nuklear
This is a minimal-state, immediate-mode graphical user interface toolkit written in ANSI C and licensed under public domain. It was designed as a simple embeddable user interface for application and does not have any dependencies, a default render backend or OS window/input handling but instead provides a highly modular, library-based approach, with simple input state for input and draw commands describing primitive shapes as output. So instead of providing a layered library that tries to abstract over a number of platform and render backends, it focuses only on the actual UI.
 
Loading...
Searching...
No Matches
nuklear_buffer.c
1#include "nuklear.h"
2#include "nuklear_internal.h"
3
4/* ==============================================================
5 *
6 * BUFFER
7 *
8 * ===============================================================*/
9#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
10NK_LIB void*
11nk_malloc(nk_handle unused, void *old,nk_size size)
12{
13 NK_UNUSED(unused);
14 NK_UNUSED(old);
15 return malloc(size);
16}
17NK_LIB void
18nk_mfree(nk_handle unused, void *ptr)
19{
20 NK_UNUSED(unused);
21 free(ptr);
22}
23NK_API void
24nk_buffer_init_default(struct nk_buffer *buffer)
25{
26 struct nk_allocator alloc;
27 alloc.userdata.ptr = 0;
28 alloc.alloc = nk_malloc;
29 alloc.free = nk_mfree;
30 nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
31}
32#endif
33
34NK_API void
35nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
36 nk_size initial_size)
37{
38 NK_ASSERT(b);
39 NK_ASSERT(a);
40 NK_ASSERT(initial_size);
41 if (!b || !a || !initial_size) return;
42
43 nk_zero(b, sizeof(*b));
44 b->type = NK_BUFFER_DYNAMIC;
45 b->memory.ptr = a->alloc(a->userdata,0, initial_size);
46 b->memory.size = initial_size;
47 b->size = initial_size;
48 b->grow_factor = 2.0f;
49 b->pool = *a;
50}
51NK_API void
52nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
53{
54 NK_ASSERT(b);
55 NK_ASSERT(m);
56 NK_ASSERT(size);
57 if (!b || !m || !size) return;
58
59 nk_zero(b, sizeof(*b));
60 b->type = NK_BUFFER_FIXED;
61 b->memory.ptr = m;
62 b->memory.size = size;
63 b->size = size;
64}
65NK_LIB void*
66nk_buffer_align(void *unaligned,
67 nk_size align, nk_size *alignment,
68 enum nk_buffer_allocation_type type)
69{
70 void *memory = 0;
71 switch (type) {
72 default:
73 case NK_BUFFER_MAX:
74 case NK_BUFFER_FRONT:
75 if (align) {
76 memory = NK_ALIGN_PTR(unaligned, align);
77 *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
78 } else {
79 memory = unaligned;
80 *alignment = 0;
81 }
82 break;
83 case NK_BUFFER_BACK:
84 if (align) {
85 memory = NK_ALIGN_PTR_BACK(unaligned, align);
86 *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
87 } else {
88 memory = unaligned;
89 *alignment = 0;
90 }
91 break;
92 }
93 return memory;
94}
95NK_LIB void*
96nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
97{
98 void *temp;
99 nk_size buffer_size;
100
101 NK_ASSERT(b);
102 NK_ASSERT(size);
103 if (!b || !size || !b->pool.alloc || !b->pool.free)
104 return 0;
105
106 buffer_size = b->memory.size;
107 temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
108 NK_ASSERT(temp);
109 if (!temp) return 0;
110
111 *size = capacity;
112 if (temp != b->memory.ptr) {
113 NK_MEMCPY(temp, b->memory.ptr, buffer_size);
114 b->pool.free(b->pool.userdata, b->memory.ptr);
115 }
116
117 if (b->size == buffer_size) {
118 /* no back buffer so just set correct size */
119 b->size = capacity;
120 return temp;
121 } else {
122 /* copy back buffer to the end of the new buffer */
123 void *dst, *src;
124 nk_size back_size;
125 back_size = buffer_size - b->size;
126 dst = nk_ptr_add(void, temp, capacity - back_size);
127 src = nk_ptr_add(void, temp, b->size);
128 NK_MEMCPY(dst, src, back_size);
129 b->size = capacity - back_size;
130 }
131 return temp;
132}
133NK_LIB void*
134nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
135 nk_size size, nk_size align)
136{
137 int full;
138 nk_size alignment;
139 void *unaligned;
140 void *memory;
141
142 NK_ASSERT(b);
143 NK_ASSERT(size);
144 if (!b || !size) return 0;
145 b->needed += size;
146
147 /* calculate total size with needed alignment + size */
148 if (type == NK_BUFFER_FRONT)
149 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
150 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
151 memory = nk_buffer_align(unaligned, align, &alignment, type);
152
153 /* check if buffer has enough memory*/
154 if (type == NK_BUFFER_FRONT)
155 full = ((b->allocated + size + alignment) > b->size);
156 else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
157
158 if (full) {
159 nk_size capacity;
160 if (b->type != NK_BUFFER_DYNAMIC)
161 return 0;
162 NK_ASSERT(b->pool.alloc && b->pool.free);
163 if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
164 return 0;
165
166 /* buffer is full so allocate bigger buffer if dynamic */
167 capacity = (nk_size)((float)b->memory.size * b->grow_factor);
168 capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
169 b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
170 if (!b->memory.ptr) return 0;
171
172 /* align newly allocated pointer */
173 if (type == NK_BUFFER_FRONT)
174 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
175 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
176 memory = nk_buffer_align(unaligned, align, &alignment, type);
177 }
178 if (type == NK_BUFFER_FRONT)
179 b->allocated += size + alignment;
180 else b->size -= (size + alignment);
181 b->needed += alignment;
182 b->calls++;
183 return memory;
184}
185NK_API void
186nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type,
187 const void *memory, nk_size size, nk_size align)
188{
189 void *mem = nk_buffer_alloc(b, type, size, align);
190 if (!mem) return;
191 NK_MEMCPY(mem, memory, size);
192}
193NK_API void
194nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
195{
196 NK_ASSERT(buffer);
197 if (!buffer) return;
198 buffer->marker[type].active = nk_true;
199 if (type == NK_BUFFER_BACK)
200 buffer->marker[type].offset = buffer->size;
201 else buffer->marker[type].offset = buffer->allocated;
202}
203NK_API void
204nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
205{
206 NK_ASSERT(buffer);
207 if (!buffer) return;
208 if (type == NK_BUFFER_BACK) {
209 /* reset back buffer either back to marker or empty */
210 buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
211 if (buffer->marker[type].active)
212 buffer->size = buffer->marker[type].offset;
213 else buffer->size = buffer->memory.size;
214 buffer->marker[type].active = nk_false;
215 } else {
216 /* reset front buffer either back to back marker or empty */
217 buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
218 if (buffer->marker[type].active)
219 buffer->allocated = buffer->marker[type].offset;
220 else buffer->allocated = 0;
221 buffer->marker[type].active = nk_false;
222 }
223}
224NK_API void
225nk_buffer_clear(struct nk_buffer *b)
226{
227 NK_ASSERT(b);
228 if (!b) return;
229 b->allocated = 0;
230 b->size = b->memory.size;
231 b->calls = 0;
232 b->needed = 0;
233}
234NK_API void
235nk_buffer_free(struct nk_buffer *b)
236{
237 NK_ASSERT(b);
238 if (!b || !b->memory.ptr) return;
239 if (b->type == NK_BUFFER_FIXED) return;
240 if (!b->pool.free) return;
241 NK_ASSERT(b->pool.free);
242 b->pool.free(b->pool.userdata, b->memory.ptr);
243}
244NK_API void
245nk_buffer_info(struct nk_memory_status *s, const struct nk_buffer *b)
246{
247 NK_ASSERT(b);
248 NK_ASSERT(s);
249 if (!s || !b) return;
250 s->allocated = b->allocated;
251 s->size = b->memory.size;
252 s->needed = b->needed;
253 s->memory = b->memory.ptr;
254 s->calls = b->calls;
255}
256NK_API void*
257nk_buffer_memory(struct nk_buffer *buffer)
258{
259 NK_ASSERT(buffer);
260 if (!buffer) return 0;
261 return buffer->memory.ptr;
262}
263NK_API const void*
264nk_buffer_memory_const(const struct nk_buffer *buffer)
265{
266 NK_ASSERT(buffer);
267 if (!buffer) return 0;
268 return buffer->memory.ptr;
269}
270NK_API nk_size
271nk_buffer_total(const struct nk_buffer *buffer)
272{
273 NK_ASSERT(buffer);
274 if (!buffer) return 0;
275 return buffer->memory.size;
276}
main API and documentation file
struct nk_allocator pool
!< buffer marker to free a buffer to a certain offset
Definition nuklear.h:4191
struct nk_memory memory
!< memory management type
Definition nuklear.h:4193
enum nk_allocation_type type
!< allocator callback for dynamic buffers
Definition nuklear.h:4192
nk_size needed
!< total amount of memory allocated
Definition nuklear.h:4196
nk_size size
!< number of allocation calls
Definition nuklear.h:4198
nk_size allocated
!< growing factor for dynamic memory management
Definition nuklear.h:4195
float grow_factor
!< memory and size of the current memory block
Definition nuklear.h:4194
nk_size calls
!< totally consumed memory given that enough memory is present
Definition nuklear.h:4197