Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_stack.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
27#include "nilorea/n_stack.h"
28
34STACK* new_stack(size_t size) {
35 STACK* stack = NULL;
36
37 if (size == 0) {
38 n_log(LOG_ERR, "stack size cannot be 0");
39 return NULL;
40 }
41
42 Malloc(stack, STACK, 1);
43 __n_assert(stack, return NULL);
44 Malloc(stack->stack_array, STACK_ITEM, size);
45 __n_assert(stack->stack_array, Free(stack); return NULL;);
46
47 stack->size = size;
48 stack->head = stack->tail = 0;
49 stack->nb_items = 0;
50 return stack;
51}
52
58bool delete_stack(STACK** stack) {
59 __n_assert(stack, return FALSE);
60 __n_assert((*stack), return FALSE);
61 Free((*stack)->stack_array);
62 Free((*stack));
63 return TRUE;
64}
65
71bool stack_is_full(const STACK* stack) {
72 if (!stack) return false;
73 return ((stack->head + 1) % stack->size == stack->tail);
74}
75
81bool stack_is_empty(const STACK* stack) {
82 if (!stack) return false;
83 return (stack->nb_items == 0);
84}
85
92STACK_ITEM* stack_peek(STACK* stack, size_t position) {
93 STACK_ITEM* item = NULL;
94 __n_assert(stack, return NULL);
95
96 if (stack_is_empty(stack)) {
97 return NULL;
98 }
99
100 if (stack->tail < stack->head) {
101 if (position >= stack->tail && position < stack->head && position < stack->size && stack->stack_array[position].is_set) {
102 item = &stack->stack_array[position];
103 }
104 } else if (stack->tail > stack->head) {
105 if ((position >= stack->tail || position < stack->head) && position < stack->size && stack->stack_array[position].is_set) {
106 item = &stack->stack_array[position];
107 }
108 }
109 return item;
110}
111
118size_t __stack_push(STACK* stack, uint8_t* status) {
119 (*status) = STACK_IS_UNDEFINED;
120 __n_assert(stack, return 0);
121
122 (*status) = STACK_IS_FULL;
123 if (stack_is_full(stack))
124 return 0;
125
126 size_t next_pos = (stack->head + 1) % stack->size;
127
128 // if next_pos == tail, the stack is full
129 if (next_pos == stack->tail) {
130 // status already set to (*status) = STACK_IS_FULL ;
131 return 0;
132 }
133
134 // set data, move, set item status, inc counter
135 (*status) = STACK_ITEM_OK;
136 stack->stack_array[stack->head].is_set = 1;
137 stack->stack_array[stack->head].is_empty = 0;
138 // inc
139 stack->nb_items++;
140 return next_pos;
141}
142
149size_t __stack_pop(STACK* stack, uint8_t* status) {
150 (*status) = STACK_IS_UNDEFINED;
151 __n_assert(stack, return FALSE);
152
153 size_t next_pos = 0;
154 size_t prev_pos = 0;
155
156 // if the head == tail, the stack is empty
157 if (stack->head == stack->tail) {
158 (*status) = STACK_IS_EMPTY;
159 return 0;
160 }
161
162 // item is here and read
163 (*status) = STACK_ITEM_OK;
164
165 // next is where tail will point to after this read
166 next_pos = (stack->tail + 1) % stack->size;
167
168 // set item status, dec counter, move, return value
169 stack->stack_array[stack->tail].is_set = 0;
170 stack->stack_array[stack->tail].is_empty = 1;
171 prev_pos = stack->tail;
172 // tail to next offset.
173 stack->tail = next_pos;
174 // dec
175 stack->nb_items--;
176 return prev_pos;
177}
178
185bool stack_push_b(STACK* stack, bool b) {
186 uint8_t status = STACK_ITEM_OK;
187 size_t next_pos = __stack_push(stack, &status);
188 if (status != STACK_ITEM_OK)
189 return FALSE;
190 stack->stack_array[stack->head].data.b = b;
191 stack->stack_array[stack->head].v_type = STACK_ITEM_BOOL;
192 stack->head = next_pos;
193
194 return TRUE;
195}
196
203bool stack_pop_b(STACK* stack, uint8_t* status) {
204 (*status) = STACK_IS_UNDEFINED;
205 __n_assert(stack, return FALSE);
206
207 if (stack->head == stack->tail) {
208 (*status) = STACK_IS_EMPTY;
209 return 0;
210 }
211
212 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_BOOL) {
213 (*status) = STACK_ITEM_WRONG_TYPE;
214 return 0;
215 }
216
217 uint8_t pop_status = STACK_IS_UNDEFINED;
218 size_t prev_pos = __stack_pop(stack, &pop_status);
219 if (pop_status != STACK_ITEM_OK) {
220 (*status) = pop_status;
221 return 0;
222 }
223 return stack->stack_array[prev_pos].data.b;
224}
225
232bool stack_push_c(STACK* stack, char c) {
233 uint8_t status = STACK_ITEM_OK;
234
235 size_t next_pos = __stack_push(stack, &status);
236 if (status != STACK_ITEM_OK)
237 return FALSE;
238
239 stack->stack_array[stack->head].data.c = c;
240 stack->stack_array[stack->head].v_type = STACK_ITEM_CHAR;
241 stack->head = next_pos;
242
243 return TRUE;
244}
245
252char stack_pop_c(STACK* stack, uint8_t* status) {
253 (*status) = STACK_IS_UNDEFINED;
254 __n_assert(stack, return FALSE);
255
256 if (stack->head == stack->tail) {
257 (*status) = STACK_IS_EMPTY;
258 return 0;
259 }
260
261 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_CHAR) {
262 (*status) = STACK_ITEM_WRONG_TYPE;
263 return 0;
264 }
265
266 uint8_t pop_status = STACK_IS_UNDEFINED;
267 size_t prev_pos = __stack_pop(stack, &pop_status);
268 if (pop_status != STACK_ITEM_OK) {
269 (*status) = pop_status;
270 return 0;
271 }
272 return stack->stack_array[prev_pos].data.c;
273}
274
281bool stack_push_ui8(STACK* stack, uint8_t ui8) {
282 uint8_t status = STACK_ITEM_OK;
283
284 size_t next_pos = __stack_push(stack, &status);
285 if (status != STACK_ITEM_OK)
286 return FALSE;
287
288 stack->stack_array[stack->head].data.ui8 = ui8;
289 stack->stack_array[stack->head].v_type = STACK_ITEM_UINT8;
290 stack->head = next_pos;
291
292 return TRUE;
293}
294
301uint8_t stack_pop_ui8(STACK* stack, uint8_t* status) {
302 (*status) = STACK_IS_UNDEFINED;
303 __n_assert(stack, return FALSE);
304
305 if (stack->head == stack->tail) {
306 (*status) = STACK_IS_EMPTY;
307 return 0;
308 }
309
310 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_UINT8) {
311 (*status) = STACK_ITEM_WRONG_TYPE;
312 return 0;
313 }
314
315 uint8_t pop_status = STACK_IS_UNDEFINED;
316 size_t prev_pos = __stack_pop(stack, &pop_status);
317 if (pop_status != STACK_ITEM_OK) {
318 (*status) = pop_status;
319 return 0;
320 }
321 return stack->stack_array[prev_pos].data.ui8;
322}
323
330bool stack_push_i8(STACK* stack, int8_t i8) {
331 uint8_t status = STACK_ITEM_OK;
332
333 size_t next_pos = __stack_push(stack, &status);
334 if (status != STACK_ITEM_OK)
335 return FALSE;
336
337 stack->stack_array[stack->head].data.i8 = i8;
338 stack->stack_array[stack->head].v_type = STACK_ITEM_INT8;
339 stack->head = next_pos;
340
341 return TRUE;
342}
343
350int8_t stack_pop_i8(STACK* stack, uint8_t* status) {
351 (*status) = STACK_IS_UNDEFINED;
352 __n_assert(stack, return FALSE);
353
354 if (stack->head == stack->tail) {
355 (*status) = STACK_IS_EMPTY;
356 return 0;
357 }
358
359 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_INT8) {
360 (*status) = STACK_ITEM_WRONG_TYPE;
361 return 0;
362 }
363
364 uint8_t pop_status = STACK_IS_UNDEFINED;
365 size_t prev_pos = __stack_pop(stack, &pop_status);
366 if (pop_status != STACK_ITEM_OK) {
367 (*status) = pop_status;
368 return 0;
369 }
370 return stack->stack_array[prev_pos].data.i8;
371}
372
379bool stack_push_ui32(STACK* stack, uint32_t ui32) {
380 uint8_t status = STACK_ITEM_OK;
381
382 size_t next_pos = __stack_push(stack, &status);
383 if (status != STACK_ITEM_OK)
384 return FALSE;
385
386 stack->stack_array[stack->head].data.ui32 = ui32;
387 stack->stack_array[stack->head].v_type = STACK_ITEM_UINT32;
388 stack->head = next_pos;
389
390 return TRUE;
391}
392
399uint32_t stack_pop_ui32(STACK* stack, uint8_t* status) {
400 (*status) = STACK_IS_UNDEFINED;
401 __n_assert(stack, return FALSE);
402
403 if (stack->head == stack->tail) {
404 (*status) = STACK_IS_EMPTY;
405 return 0;
406 }
407
408 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_UINT32) {
409 (*status) = STACK_ITEM_WRONG_TYPE;
410 return 0;
411 }
412
413 uint8_t pop_status = STACK_IS_UNDEFINED;
414 size_t prev_pos = __stack_pop(stack, &pop_status);
415 if (pop_status != STACK_ITEM_OK) {
416 (*status) = pop_status;
417 return 0;
418 }
419 return stack->stack_array[prev_pos].data.ui32;
420}
421
428bool stack_push_i32(STACK* stack, int32_t i32) {
429 uint8_t status = STACK_ITEM_OK;
430
431 size_t next_pos = __stack_push(stack, &status);
432 if (status != STACK_ITEM_OK)
433 return FALSE;
434
435 stack->stack_array[stack->head].data.i32 = i32;
436 stack->stack_array[stack->head].v_type = STACK_ITEM_INT32;
437 stack->head = next_pos;
438
439 return TRUE;
440}
441
448int32_t stack_pop_i32(STACK* stack, uint8_t* status) {
449 (*status) = STACK_IS_UNDEFINED;
450 __n_assert(stack, return FALSE);
451
452 if (stack->head == stack->tail) {
453 (*status) = STACK_IS_EMPTY;
454 return 0;
455 }
456
457 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_INT32) {
458 (*status) = STACK_ITEM_WRONG_TYPE;
459 return 0;
460 }
461
462 uint8_t pop_status = STACK_IS_UNDEFINED;
463 size_t prev_pos = __stack_pop(stack, &pop_status);
464 if (pop_status != STACK_ITEM_OK) {
465 (*status) = pop_status;
466 return 0;
467 }
468 return stack->stack_array[prev_pos].data.i32;
469}
470
477bool stack_push_f(STACK* stack, float f) {
478 uint8_t status = STACK_ITEM_OK;
479
480 size_t next_pos = __stack_push(stack, &status);
481 if (status != STACK_ITEM_OK)
482 return FALSE;
483
484 stack->stack_array[stack->head].data.f = f;
485 stack->stack_array[stack->head].v_type = STACK_ITEM_FLOAT;
486 stack->head = next_pos;
487
488 return TRUE;
489}
490
497float stack_pop_f(STACK* stack, uint8_t* status) {
498 (*status) = STACK_IS_UNDEFINED;
499 __n_assert(stack, return FALSE);
500
501 if (stack->head == stack->tail) {
502 (*status) = STACK_IS_EMPTY;
503 return 0;
504 }
505
506 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_FLOAT) {
507 (*status) = STACK_ITEM_WRONG_TYPE;
508 return 0;
509 }
510
511 uint8_t pop_status = STACK_IS_UNDEFINED;
512 size_t prev_pos = __stack_pop(stack, &pop_status);
513 if (pop_status != STACK_ITEM_OK) {
514 (*status) = pop_status;
515 return 0;
516 }
517 return stack->stack_array[prev_pos].data.f;
518}
519
526bool stack_push_d(STACK* stack, double d) {
527 uint8_t status = STACK_ITEM_OK;
528
529 size_t next_pos = __stack_push(stack, &status);
530 if (status != STACK_ITEM_OK)
531 return FALSE;
532
533 stack->stack_array[stack->head].data.d = d;
534 stack->stack_array[stack->head].v_type = STACK_ITEM_DOUBLE;
535 stack->head = next_pos;
536
537 return TRUE;
538}
539
546double stack_pop_d(STACK* stack, uint8_t* status) {
547 (*status) = STACK_IS_UNDEFINED;
548 __n_assert(stack, return FALSE);
549
550 if (stack->head == stack->tail) {
551 (*status) = STACK_IS_EMPTY;
552 return 0;
553 }
554
555 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_DOUBLE) {
556 (*status) = STACK_ITEM_WRONG_TYPE;
557 return 0;
558 }
559
560 uint8_t pop_status = STACK_IS_UNDEFINED;
561 size_t prev_pos = __stack_pop(stack, &pop_status);
562 if (pop_status != STACK_ITEM_OK) {
563 (*status) = pop_status;
564 return 0;
565 }
566 return stack->stack_array[prev_pos].data.d;
567}
568
576bool stack_push_p(STACK* stack, void* p, uint16_t p_type) {
577 uint8_t status = STACK_ITEM_OK;
578
579 size_t next_pos = __stack_push(stack, &status);
580 if (status != STACK_ITEM_OK)
581 return FALSE;
582
583 stack->stack_array[stack->head].data.p = p;
584 stack->stack_array[stack->head].v_type = STACK_ITEM_PTR;
585 stack->stack_array[stack->head].p_type = p_type;
586 stack->head = next_pos;
587
588 return TRUE;
589}
590
597void* stack_pop_p(STACK* stack, uint8_t* status) {
598 (*status) = STACK_IS_UNDEFINED;
599 __n_assert(stack, return NULL);
600
601 if (stack->head == stack->tail) {
602 (*status) = STACK_IS_EMPTY;
603 return 0;
604 }
605
606 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_PTR) {
607 (*status) = STACK_ITEM_WRONG_TYPE;
608 return 0;
609 }
610
611 uint8_t pop_status = STACK_IS_UNDEFINED;
612 size_t prev_pos = __stack_pop(stack, &pop_status);
613 if (pop_status != STACK_ITEM_OK) {
614 (*status) = pop_status;
615 return 0;
616 }
617 return stack->stack_array[prev_pos].data.p;
618}
619
626bool stack_push_p_default(STACK* stack, void* p) {
627 return stack_push_p(stack, p, 0);
628}
629
630#ifdef ENV_64BITS
637bool stack_push_ui64(STACK* stack, uint64_t ui64) {
638 uint8_t status = STACK_ITEM_OK;
639
640 size_t next_pos = __stack_push(stack, &status);
641 if (status != STACK_ITEM_OK)
642 return FALSE;
643
644 stack->stack_array[stack->head].data.ui64 = ui64;
645 stack->stack_array[stack->head].v_type = STACK_ITEM_UINT64;
646 stack->head = next_pos;
647
648 return TRUE;
649}
650
657uint64_t stack_pop_ui64(STACK* stack, uint8_t* status) {
658 (*status) = STACK_IS_UNDEFINED;
659 __n_assert(stack, return FALSE);
660
661 if (stack->head == stack->tail) {
662 (*status) = STACK_IS_EMPTY;
663 return 0;
664 }
665
666 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_UINT64) {
667 (*status) = STACK_ITEM_WRONG_TYPE;
668 return 0;
669 }
670
671 uint8_t pop_status = STACK_IS_UNDEFINED;
672 size_t prev_pos = __stack_pop(stack, &pop_status);
673 if (pop_status != STACK_ITEM_OK) {
674 (*status) = pop_status;
675 return 0;
676 }
677 return stack->stack_array[prev_pos].data.ui64;
678}
679
686bool stack_push_i64(STACK* stack, int64_t i64) {
687 uint8_t status = STACK_ITEM_OK;
688
689 size_t next_pos = __stack_push(stack, &status);
690 if (status != STACK_ITEM_OK)
691 return FALSE;
692
693 stack->stack_array[stack->head].data.i64 = i64;
694 stack->stack_array[stack->head].v_type = STACK_ITEM_INT64;
695 stack->head = next_pos;
696
697 return TRUE;
698}
699
706int64_t stack_pop_i64(STACK* stack, uint8_t* status) {
707 (*status) = STACK_IS_UNDEFINED;
708 __n_assert(stack, return FALSE);
709
710 if (stack->head == stack->tail) {
711 (*status) = STACK_IS_EMPTY;
712 return 0;
713 }
714
715 if (stack->stack_array[stack->tail].v_type != STACK_ITEM_INT64) {
716 (*status) = STACK_ITEM_WRONG_TYPE;
717 return 0;
718 }
719
720 uint8_t pop_status = STACK_IS_UNDEFINED;
721 size_t prev_pos = __stack_pop(stack, &pop_status);
722 if (pop_status != STACK_ITEM_OK) {
723 (*status) = pop_status;
724 return 0;
725 }
726 return stack->stack_array[prev_pos].data.i64;
727}
728#endif
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:203
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:278
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:262
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:88
#define LOG_ERR
error conditions
Definition n_log.h:75
size_t tail
position of tail
Definition n_stack.h:125
bool is_empty
is item empty ?
Definition n_stack.h:107
size_t head
position of head
Definition n_stack.h:123
size_t nb_items
number of item inside stack
Definition n_stack.h:127
STACK_ITEM * stack_array
STACK_ITEM array.
Definition n_stack.h:119
int8_t i8
int 8
Definition n_stack.h:83
uint16_t p_type
if v_type is STACK_ITEM_PTR, user defined pointer type
Definition n_stack.h:113
union STACK_DATA data
union of different types
Definition n_stack.h:109
void * p
pointer
Definition n_stack.h:99
double d
double
Definition n_stack.h:97
size_t size
Size of array.
Definition n_stack.h:121
float f
float
Definition n_stack.h:95
char c
single character
Definition n_stack.h:79
int32_t i32
int 32
Definition n_stack.h:87
uint8_t v_type
type of the item
Definition n_stack.h:111
bool b
boolean
Definition n_stack.h:77
bool is_set
is item set ?
Definition n_stack.h:105
uint32_t ui32
unsigned int 32
Definition n_stack.h:85
uint8_t ui8
unsigned int 8
Definition n_stack.h:81
bool stack_push_f(STACK *stack, float f)
helper to push a float
Definition n_stack.c:477
#define STACK_ITEM_UINT64
v_type value for a uint64_t
Definition n_stack.h:53
double stack_pop_d(STACK *stack, uint8_t *status)
helper to pop a double
Definition n_stack.c:546
bool stack_pop_b(STACK *stack, uint8_t *status)
helper to pop a bool
Definition n_stack.c:203
bool stack_push_d(STACK *stack, double d)
helper to push a double
Definition n_stack.c:526
bool stack_push_ui8(STACK *stack, uint8_t ui8)
helper to push an uint8_t
Definition n_stack.c:281
#define STACK_ITEM_UINT32
v_type value for a uint32_t
Definition n_stack.h:49
STACK_ITEM * stack_peek(STACK *stack, size_t position)
peek in the stack without removing the stack item
Definition n_stack.c:92
bool stack_push_ui32(STACK *stack, uint32_t ui32)
helper to push an uint32_t
Definition n_stack.c:379
int8_t stack_pop_i8(STACK *stack, uint8_t *status)
helper to pop a int8_t
Definition n_stack.c:350
#define STACK_ITEM_INT8
v_type value for a int8_t
Definition n_stack.h:47
char stack_pop_c(STACK *stack, uint8_t *status)
helper to pop a char
Definition n_stack.c:252
bool stack_is_empty(const STACK *stack)
test if the stack is empty
Definition n_stack.c:81
float stack_pop_f(STACK *stack, uint8_t *status)
helper to pop a float
Definition n_stack.c:497
#define STACK_ITEM_PTR
v_type value for a void *pointer
Definition n_stack.h:61
uint8_t stack_pop_ui8(STACK *stack, uint8_t *status)
helper to pop a uint8_t
Definition n_stack.c:301
bool stack_push_c(STACK *stack, char c)
helper to push a char
Definition n_stack.c:232
bool stack_is_full(const STACK *stack)
test if the stack is full
Definition n_stack.c:71
#define STACK_IS_EMPTY
code for an empty stack state
Definition n_stack.h:66
#define STACK_ITEM_INT64
v_type value for a int64_t
Definition n_stack.h:55
#define STACK_ITEM_INT32
v_type value for a int32_t
Definition n_stack.h:51
#define STACK_IS_FULL
code for a full stack state
Definition n_stack.h:64
#define STACK_ITEM_CHAR
v_type value for a char
Definition n_stack.h:43
#define STACK_ITEM_OK
code for a successfully retrieved item
Definition n_stack.h:72
uint32_t stack_pop_ui32(STACK *stack, uint8_t *status)
helper to pop a uint32_t
Definition n_stack.c:399
bool stack_push_b(STACK *stack, bool b)
helper to push a bool
Definition n_stack.c:185
#define STACK_ITEM_BOOL
v_type value for a bool
Definition n_stack.h:41
#define STACK_IS_UNDEFINED
code for a NULL stack state
Definition n_stack.h:68
#define STACK_ITEM_UINT8
v_type value for a uint8_t
Definition n_stack.h:45
bool stack_push_i32(STACK *stack, int32_t i32)
helper to push an int32_t
Definition n_stack.c:428
int32_t stack_pop_i32(STACK *stack, uint8_t *status)
helper to pop a int32_t
Definition n_stack.c:448
#define STACK_ITEM_WRONG_TYPE
code for a bad item type
Definition n_stack.h:70
#define STACK_ITEM_DOUBLE
v_type value for a double
Definition n_stack.h:59
bool delete_stack(STACK **stack)
delete a STACK *stack
Definition n_stack.c:58
bool stack_push_i8(STACK *stack, int8_t i8)
helper to push an int8_t
Definition n_stack.c:330
#define STACK_ITEM_FLOAT
v_type value for a float
Definition n_stack.h:57
STACK * new_stack(size_t size)
allocate a new STACK
Definition n_stack.c:34
bool stack_push_p(STACK *stack, void *p, uint16_t p_type)
helper to push a pointer
Definition n_stack.c:576
void * stack_pop_p(STACK *stack, uint8_t *status)
helper to pop a pointer
Definition n_stack.c:597
bool stack_push_p_default(STACK *stack, void *p)
helper to push a pointer with a default p_type of 0
Definition n_stack.c:626
STACK structure.
Definition n_stack.h:117
structure of a STACK item
Definition n_stack.h:103
size_t __stack_push(STACK *stack, uint8_t *status)
helper for stack_push.
Definition n_stack.c:118
size_t __stack_pop(STACK *stack, uint8_t *status)
helper for stack_pop.
Definition n_stack.c:149
Stack header definitions.