stack.h (3900B)
1 /* 2 * This file is part of the Lumidify ToolKit (LTK) 3 * Copyright (c) 2020 lumidify <nobody@lumidify.org> 4 * Based on the stack from libraqm. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in all 14 * copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #ifndef _LTK_STACK_H_ 26 #define _LTK_STACK_H_ 27 28 /* This is a "macro'd" and modified version of raqm's stack */ 29 30 #define LTK_STACK_INIT_DECL(name, type1, type2, data1, data2) \ 31 struct ltk_stack_##name { \ 32 size_t capacity; \ 33 size_t size; \ 34 type1 *data1; \ 35 type2 *data2; \ 36 }; \ 37 \ 38 int ltk_stack_pop_##name(struct ltk_stack_##name *stack); \ 39 type1 ltk_stack_top1_##name(struct ltk_stack_##name *stack, type1 def); \ 40 void ltk_stack_destroy_##name(struct ltk_stack_##name *stack); \ 41 int ltk_stack_push_##name( \ 42 struct ltk_stack_##name *stack, type1 data1, type2 data2); \ 43 type2 ltk_stack_top2_##name(struct ltk_stack_##name *stack, type2 def); \ 44 struct ltk_stack_##name *ltk_stack_create_##name(size_t max); 45 46 #define LTK_STACK_INIT_IMPL(name, type1, type2, data1, data2) \ 47 struct ltk_stack_##name * \ 48 ltk_stack_create_##name(size_t max) { \ 49 struct ltk_stack_##name *stack; \ 50 stack = malloc(sizeof(struct ltk_stack_##name)); \ 51 if (!stack) goto error; \ 52 \ 53 stack->data1 = malloc(sizeof(type1) * max); \ 54 if (!stack->data1) goto error; \ 55 stack->data2 = malloc(sizeof(type2) * max); \ 56 if (!stack->data2) goto error; \ 57 \ 58 stack->size = 0; \ 59 stack->capacity = max; \ 60 \ 61 return stack; \ 62 error: \ 63 (void)fprintf(stderr, "Cannot allocate memory for stack\n"); \ 64 exit(1); \ 65 } \ 66 \ 67 int \ 68 ltk_stack_pop_##name(struct ltk_stack_##name *stack) { \ 69 if (!stack->size) \ 70 return 0; \ 71 \ 72 stack->size--; \ 73 \ 74 return 1; \ 75 } \ 76 \ 77 type1 \ 78 ltk_stack_top1_##name(struct ltk_stack_##name *stack, type1 def) { \ 79 if (!stack->size) \ 80 return def; \ 81 \ 82 return stack->data1[stack->size]; \ 83 } \ 84 \ 85 type2 \ 86 ltk_stack_top2_##name(struct ltk_stack_##name *stack, type2 def) { \ 87 if (!stack->size) \ 88 return def; \ 89 \ 90 return stack->data2[stack->size]; \ 91 } \ 92 \ 93 int \ 94 ltk_stack_push_##name(struct ltk_stack_##name *stack, \ 95 type1 data1, type2 data2) { \ 96 if (stack->size == stack->capacity) \ 97 return 0; \ 98 \ 99 stack->size++; \ 100 stack->data1[stack->size] = data1; \ 101 stack->data2[stack->size] = data2; \ 102 \ 103 return 1; \ 104 } \ 105 \ 106 void \ 107 ltk_stack_destroy_##name(struct ltk_stack_##name *stack) { \ 108 free(stack->data1); \ 109 free(stack->data2); \ 110 free(stack); \ 111 } 112 113 #endif /* _LTK_STACK_H_ */