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