TR_datastructures 0.1.0
A generic C data structures library
Loading...
Searching...
No Matches
tr_stack.h
Go to the documentation of this file.
1
2/**
3 * @file tr_stack.h
4 * @brief Public API for the stack data structure
5 *
6 * Provides a generic stack implementation supporting multiple
7 * underlying storage strategies selectable at runtime via
8 * @ref tr_stack_type_t.
9 *
10 * Typical usage:
11 * @code
12 * struct stack *p_stack = NULL;
13 * tr_result_t res = TR_OK;
14 * int val = 42;
15 * int out = 0;
16 *
17 * res = tr_stack_create(sizeof(int), 10, TR_STACK_ARRAY_DYNAMIC, &p_stack);
18 * if (TR_OK != res) { return res; }
19 *
20 * res = tr_stack_push(p_stack, &val);
21 * if (TR_OK != res) { return res; }
22 *
23 * res = tr_stack_top(p_stack, &out);
24 * if (TR_OK != res) { return res; }
25 *
26 * res = tr_stack_pop(p_stack);
27 * if (TR_OK != res) { return res; }
28 *
29 * tr_stack_destroy(&p_stack);
30 * @endcode
31 */
32/*******************************************************************************
33 * NAME: tr_stack.h
34 *
35 * PURPOSE: Declaration of the stack functions
36 *
37 * GLOBAL VARIABLES:
38 *
39 * Variable Type Description
40 * -------- ---- -----------
41 *
42 * DEVELOPMENT HISTORY:
43 *
44 * Date Author Change Id Release Description Of Change
45 * 31-05-2026 Tiago Rodrigues 1 File preparation
46 *
47 *******************************************************************************/
48#ifndef TR_STACK_H
49#define TR_STACK_H
50
51/* 0 copyright/licensing */
52/*******************************************************************************************************
53 *
54 * This is free and unencumbered software released into the public domain (Unlicense).
55 *
56 ********************************************************************************************************/
57
58/* Ensure C++ compatibility */
59#ifdef __cplusplus
60extern "C"
61{
62#endif
63
64/* 1 includes */
65/*****************************************************/
69/*****************************************************/
70
71/* 2 defines */
72/*****************************************************/
73/*****************************************************/
74
75/* 3 external declarations */
76/*****************************************************/
77/*****************************************************/
78
79/* 4 typedefs */
80/*****************************************************/
81
82/*******************************************************************************************************
83 *
84 * TYPE NAME: struct stack
85 *
86 * PURPOSE: Opaque handle to a stack instance
87 *
88 *******************************************************************************************************/
89/**
90 * @brief Opaque handle to a stack instance
91 *
92 * Users interact with the stack exclusively through the API functions.
93 * The internal implementation is hidden.
94 */
95struct stack;
96
97/*******************************************************************************************************
98 *
99 * TYPE NAME: tr_stack_type_t
100 *
101 * PURPOSE: Selects the underlying implementation used by the stack
102 *
103 * VALUES:
104 *
105 * VALUE DESCRIPTION
106 * ----- -----------
107 * TR_STACK_ARRAY Array based implementation - fixed capacity, fast access
108 * TR_STACK_ARRAY_FIXED Array based implementation - fixed capacity, returns FULL when capacity
109 * is reached TR_STACK_LL Linked list based implementation - dynamic growth, unbounded
110 *
111 *******************************************************************************************************/
112/**
113 * @brief Selects the underlying implementation used by the stack
114 *
115 * Passed to @ref tr_stack_create to select which implementation
116 * to use. The choice affects memory layout, growth behaviour
117 * and performance characteristics.
118 *
119 * | Type | Memory | Growth | Best for |
120 * |-------------------------|-----------|----------|-----------------------|
121 * | TR_STACK_ARRAY_DYNAMIC | Contiguous| Automatic| General purpose |
122 * | TR_STACK_ARRAY_FIXED | Contiguous| None | Bounded/embedded use |
123 * | TR_STACK_LL | Per node | Automatic| Unpredictable size |
124 */
125typedef enum tr_stack_type
126{
127 TR_STACK_ARRAY_DYNAMIC = 0, /**< Array based - grows automatically by factor of 2 */
128 TR_STACK_ARRAY_FIXED = 1, /**< Array based - fixed capacity, returns TR_ERR_FULL */
129 TR_STACK_LL = 2 /**< Linked list based - dynamic node allocation */
131/*****************************************************/
132
133/* 5 global variable declarations */
134/*****************************************************/
135
136/* 6 function prototypes */
137/*****************************************************/
138
139/******************************************************************
140 *
141 * FUNCTION NAME: tr_stack_create
142 *
143 * PURPOSE: Allocates the needed memory for the stack wanted
144 *
145 * ARGUMENTS:
146 *
147 * ARGUMENT TYPE I/O DESCRIPTION
148 * -------- ---- --- ------------
149 * size_of_datatype size_t I Byte size of the datatype to store in the
150 * elements_to_allocate size_t I Initial number of elements to
151 * stack_type tr_stack_type_t I Type of stack to create (array or linked
152 * list)
153 * allocate id_of_stack stack_t ** O Pointer to pointer to receive the
154 * created stack
155 *
156 * RETURNS: tr_result_t
157 * TR_OK - Stack created successfully
158 * TR_ERR_NULL - id_of_stack is NULL
159 * TR_ERR_INVALID - size_of_datatype or elements_to_allocate is 0, or unknown stack_type
160 * TR_ERR_ALLOC - Memory allocation failed
161 *
162 *****************************************************************/
163/**
164 * @brief Allocates and initialises a new stack instance
165 *
166 * @param[in] size_of_datatype Byte size of the datatype to store
167 * @param[in] elements_to_allocate Initial number of elements to allocate
168 * @param[in] stack_type Implementation type to use
169 * @param[out] id_of_stack Pointer to receive the created stack
170 *
171 * @return TR_OK Stack created successfully
172 * @return TR_ERR_NULL id_of_stack is NULL
173 * @return TR_ERR_INVALID size_of_datatype or elements_to_allocate is 0
174 * @return TR_ERR_ALLOC Memory allocation failed
175 */
177 size_t elements_to_allocate,
178 tr_stack_type_t stack_type,
179 struct stack **id_of_stack);
180
181/******************************************************************
182 *
183 * FUNCTION NAME: tr_stack_destroy
184 *
185 * PURPOSE: Frees all memory associated with the stack instance
186 *
187 * ARGUMENTS:
188 *
189 * ARGUMENT TYPE I/O DESCRIPTION
190 * -------- ---- --- ------------
191 * id_of_stack struct stack ** I/O Pointer to pointer to the stack to
192 * destroy. Set to NULL after destruction
193 *
194 * RETURNS: tr_result_t
195 * TR_OK - Stack destroyed successfully
196 * TR_ERR_NULL - id_of_stack or *id_of_stack is NULL
197 *
198 *****************************************************************/
199/**
200 * @brief Frees all memory associated with the stack instance
201 *
202 * Destroys the stack and sets the pointer to @c NULL to prevent
203 * use after free. Both the implementation data and the stack
204 * handle are freed.
205 *
206 * @param[in,out] id_of_stack Pointer to pointer to the stack to destroy.
207 * Set to @c NULL after destruction
208 *
209 * @return TR_OK Stack destroyed successfully
210 * @return TR_ERR_NULL id_of_stack or *id_of_stack is NULL
211 *
212 * Example:
213 * @code
214 * struct stack *p_stack = NULL;
215 *
216 * tr_stack_create(sizeof(int), 10, TR_STACK_ARRAY_DYNAMIC, &p_stack);
217 *
218 * tr_stack_destroy(&p_stack);
219 * // p_stack is now NULL
220 * @endcode
221 */
223
224/******************************************************************
225 *
226 * FUNCTION NAME: tr_stack_push
227 *
228 * PURPOSE: Pushes a element onto the top of the stack
229 *
230 * ARGUMENTS:
231 *
232 * ARGUMENT TYPE I/O DESCRIPTION
233 * -------- ---- --- ------------
234 * id_of_stack struct stack * I/O Pointer to the stack to push onto
235 * data_to_push const void * I Pointer to the data to copy onto the stack
236 *
237 * RETURNS: tr_result_t
238 * TR_OK - Data pushed successfully
239 * TR_ERR_NULL - id_of_stack or data_to_push is NULL
240 * TR_ERR_ALLOC - Memory allocation failed (linked list only)
241 * TR_ERR_FULL - Stack is full (array based only)
242 *
243 *****************************************************************/
244/**
245 * @brief Pushes a deep copy of the data onto the top of the stack
246 *
247 * Copies @c size_of_datatype bytes from @p data_to_push into the
248 * stack. The caller retains ownership of the original data.
249 *
250 * For @ref TR_STACK_ARRAY_DYNAMIC stacks the array grows automatically
251 * by a factor of 2 when full. For @ref TR_STACK_ARRAY_FIXED stacks
252 * @ref TR_ERR_FULL is returned when capacity is reached.
253 *
254 * @param[in,out] id_of_stack Pointer to the stack to push onto
255 * @param[in] data_to_push Pointer to the data to copy onto the stack
256 *
257 * @return TR_OK Data pushed successfully
258 * @return TR_ERR_NULL id_of_stack or data_to_push is NULL
259 * @return TR_ERR_ALLOC Memory reallocation failed (dynamic only)
260 * @return TR_ERR_FULL Stack is at capacity (fixed only)
261 *
262 * Example:
263 * @code
264 * int val = 42;
265 * tr_result_t res = TR_OK;
266 *
267 * res = tr_stack_push(p_stack, &val);
268 * if (TR_OK != res)
269 * {
270 * // handle error
271 * }
272 * @endcode
273 */
274TR_NODISCARD TR_API tr_result_t tr_stack_push(struct stack *id_of_stack, const void *data_to_push);
275
276/******************************************************************
277 *
278 * FUNCTION NAME: tr_stack_pop
279 *
280 * PURPOSE: Removes the element at the top of the stack
281 *
282 * ARGUMENTS:
283 *
284 * ARGUMENT TYPE I/O DESCRIPTION
285 * -------- ---- --- ------------
286 * id_of_stack struct stack * I/O Pointer to the stack to pop from
287 *
288 * RETURNS: tr_result_t
289 * TR_OK - Element popped successfully
290 * TR_ERR_NULL - id_of_stack is NULL
291 * TR_ERR_EMPTY - Stack is empty
292 *
293 *****************************************************************/
294/**
295 * @brief Removes the element at the top of the stack
296 *
297 * Decrements the stack size by one. The data is not returned —
298 * call @ref tr_stack_top first if you need the value before removing it.
299 *
300 * @param[in,out] id_of_stack Pointer to the stack to pop from
301 *
302 * @return TR_OK Element removed successfully
303 * @return TR_ERR_NULL id_of_stack is NULL
304 * @return TR_ERR_EMPTY Stack is empty
305 *
306 * Example:
307 * @code
308 * int out = 0;
309 * tr_result_t res = TR_OK;
310 *
311 * res = tr_stack_top(p_stack, &out);
312 * if (TR_OK == res)
313 * {
314 * tr_stack_pop(p_stack);
315 * }
316 * @endcode
317 */
318TR_NODISCARD TR_API tr_result_t tr_stack_pop(struct stack *id_of_stack);
319
320/******************************************************************
321 *
322 * FUNCTION NAME: tr_stack_top
323 *
324 * PURPOSE: Copies the element at the top of the stack into the provided buffer
325 * Does not remove the element
326 *
327 * ARGUMENTS:
328 *
329 * ARGUMENT TYPE I/O DESCRIPTION
330 * -------- ---- --- ------------
331 * id_of_stack const struct stack * I Pointer to the stack to peek at
332 * data_at_top void * O Pointer to buffer to copy the top
333 * element into. Must be at least
334 * size_of_datatype bytes
335 *
336 * RETURNS: tr_result_t
337 * TR_OK - Data copied successfully
338 * TR_ERR_NULL - id_of_stack or data_at_top is NULL
339 * TR_ERR_EMPTY - Stack is empty
340 *
341 *****************************************************************/
342/**
343 * @brief Copies the element at the top of the stack into the provided buffer
344 *
345 * Copies @c size_of_datatype bytes from the top of the stack into
346 * @p data_at_top. The element is not removed — call @ref tr_stack_pop
347 * afterwards if removal is needed.
348 *
349 * The buffer pointed to by @p data_at_top must be at least
350 * @c size_of_datatype bytes large.
351 *
352 * @param[in] id_of_stack Pointer to the stack to peek at
353 * @param[out] data_at_top Buffer to copy the top element into
354 *
355 * @return TR_OK Data copied successfully
356 * @return TR_ERR_NULL id_of_stack or data_at_top is NULL
357 * @return TR_ERR_EMPTY Stack is empty
358 *
359 * Example:
360 * @code
361 * int out = 0;
362 * tr_result_t res = TR_OK;
363 *
364 * res = tr_stack_top(p_stack, &out);
365 * if (TR_OK == res)
366 * {
367 * printf("Top value: %d\n", out);
368 * }
369 * @endcode
370 */
371TR_NODISCARD TR_API tr_result_t tr_stack_top(const struct stack *id_of_stack, void *data_at_top);
372
373/******************************************************************
374 *
375 * FUNCTION NAME: tr_stack_size
376 *
377 * PURPOSE: Returns the current number of elements in the stack
378 *
379 * ARGUMENTS:
380 *
381 * ARGUMENT TYPE I/O DESCRIPTION
382 * -------- ---- --- ------------
383 * id_of_stack const struct stack * I Pointer to the stack to query
384 * size size_t * O Pointer to receive the current element
385 * count
386 *
387 * RETURNS: tr_result_t
388 * TR_OK - Size retrieved successfully
389 * TR_ERR_NULL - id_of_stack or size is NULL
390 *
391 *****************************************************************/
392/**
393 * @brief Returns the current number of elements in the stack
394 *
395 * @param[in] id_of_stack Pointer to the stack to query
396 * @param[out] size Pointer to receive the current element count
397 *
398 * @return TR_OK Size retrieved successfully
399 * @return TR_ERR_NULL id_of_stack or size is NULL
400 *
401 * Example:
402 * @code
403 * size_t size = 0u;
404 * tr_result_t res = TR_OK;
405 *
406 * res = tr_stack_size(p_stack, &size);
407 * if (TR_OK == res)
408 * {
409 * printf("Stack has %zu elements\n", size);
410 * }
411 * @endcode
412 */
413TR_NODISCARD TR_API tr_result_t tr_stack_size(const struct stack *id_of_stack, size_t *size);
414
415/******************************************************************
416 *
417 * FUNCTION NAME: tr_stack_is_empty
418 *
419 * PURPOSE: Checks whether the stack contains no elements
420 *
421 * ARGUMENTS:
422 *
423 * ARGUMENT TYPE I/O DESCRIPTION
424 * -------- ---- --- ------------
425 * id_of_stack const struct stack * I Pointer to the stack to check
426 * is_empty bool * O Pointer to receive the result
427 * Set to true if empty, false otherwise
428 *
429 * RETURNS: tr_result_t
430 * TR_OK - Check completed successfully
431 * TR_ERR_NULL - id_of_stack or is_empty is NULL
432 *
433 *****************************************************************/
434/**
435 * @brief Checks whether the stack contains no elements
436 *
437 * @param[in] id_of_stack Pointer to the stack to check
438 * @param[out] is_empty Set to @c true if the stack is empty,
439 * @c false otherwise
440 *
441 * @return TR_OK Check completed successfully
442 * @return TR_ERR_NULL id_of_stack or is_empty is NULL
443 *
444 * Example:
445 * @code
446 * bool is_empty = false;
447 * tr_result_t res = TR_OK;
448 *
449 * res = tr_stack_is_empty(p_stack, &is_empty);
450 * if (TR_OK == res && is_empty)
451 * {
452 * printf("Stack is empty\n");
453 * }
454 * @endcode
455 */
456TR_NODISCARD TR_API tr_result_t tr_stack_is_empty(const struct stack *id_of_stack, bool *is_empty);
457
458/******************************************************************
459 *
460 * FUNCTION NAME: tr_stack_capacity
461 *
462 * PURPOSE: Returns the total allocated capacity of the stack
463 * For linked list based stacks this is the same as stack_size
464 *
465 * ARGUMENTS:
466 *
467 * ARGUMENT TYPE I/O DESCRIPTION
468 * -------- ---- --- ------------
469 * id_of_stack const struct stack * I Pointer to the stack to query
470 * capacity size_t * O Pointer to receive the capacity
471 *
472 * RETURNS: tr_result_t
473 * TR_OK - Capacity retrieved successfully
474 * TR_ERR_NULL - id_of_stack or capacity is NULL
475 *
476 *****************************************************************/
477/**
478 * @brief Returns the total allocated capacity of the stack
479 *
480 * For @ref TR_STACK_ARRAY_DYNAMIC stacks capacity grows automatically
481 * and may be larger than the current size. For @ref TR_STACK_ARRAY_FIXED
482 * stacks capacity is fixed at creation time and never changes.
483 * For @ref TR_STACK_LL stacks capacity equals the current size since
484 * nodes are allocated individually.
485 *
486 * @param[in] id_of_stack Pointer to the stack to query
487 * @param[out] capacity Pointer to receive the capacity
488 *
489 * @return TR_OK Capacity retrieved successfully
490 * @return TR_ERR_NULL id_of_stack or capacity is NULL
491 *
492 * Example:
493 * @code
494 * size_t capacity = 0u;
495 * size_t size = 0u;
496 * tr_result_t res = TR_OK;
497 *
498 * tr_stack_size(p_stack, &size);
499 * res = tr_stack_capacity(p_stack, &capacity);
500 * if (TR_OK == res)
501 * {
502 * printf("Using %zu of %zu slots\n", size, capacity);
503 * }
504 * @endcode
505 */
506TR_NODISCARD TR_API tr_result_t tr_stack_capacity(const struct stack *id_of_stack,
507 size_t *capacity);
508
509/*****************************************************/
510
511#ifdef __cplusplus
512}
513#endif
514
515#endif /* TR_STACK_H */
Symbol visibility and compiler annotation macros.
#define TR_NODISCARD
Warns if the return value of a function is ignored.
Definition tr_export.h:217
#define TR_API
Marks a public API symbol for export or import.
Definition tr_export.h:129
Library wide error code definitions for the tr_datastructures library.
enum tr_result tr_result_t
Library wide error code returned by all API functions.
tr_result_t tr_stack_create(size_t size_of_datatype, size_t elements_to_allocate, tr_stack_type_t stack_type, struct stack **id_of_stack)
Allocates and initialises a new stack instance.
tr_stack_type
Selects the underlying implementation used by the stack.
Definition tr_stack.h:126
@ TR_STACK_LL
Definition tr_stack.h:129
@ TR_STACK_ARRAY_DYNAMIC
Definition tr_stack.h:127
@ TR_STACK_ARRAY_FIXED
Definition tr_stack.h:128
tr_result_t tr_stack_capacity(const struct stack *id_of_stack, size_t *capacity)
Returns the total allocated capacity of the stack.
tr_result_t tr_stack_size(const struct stack *id_of_stack, size_t *size)
Returns the current number of elements in the stack.
enum tr_stack_type tr_stack_type_t
Selects the underlying implementation used by the stack.
tr_result_t tr_stack_pop(struct stack *id_of_stack)
Removes the element at the top of the stack.
tr_result_t tr_stack_push(struct stack *id_of_stack, const void *data_to_push)
Pushes a deep copy of the data onto the top of the stack.
tr_result_t tr_stack_destroy(struct stack **id_of_stack)
Frees all memory associated with the stack instance.
tr_result_t tr_stack_top(const struct stack *id_of_stack, void *data_at_top)
Copies the element at the top of the stack into the provided buffer.
tr_result_t tr_stack_is_empty(const struct stack *id_of_stack, bool *is_empty)
Checks whether the stack contains no elements.
Portable type definitions for C89/C99/C11 compatibility.