1 /*
2 Copyright 2021 Northern.tech AS
3
4 This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 3.
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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18
19 To the extent this program is licensed as part of the Enterprise
20 versions of CFEngine, the applicable Commercial Open Source License
21 (COSL) may apply to this file if you as a licensee so wish it. See
22 included file COSL.txt.
23 */
24
25 #include <platform.h>
26 #include <alloc.h>
27 #include <logging.h>
28 #include <stack_base.c>
29
StackNew(size_t initial_capacity,void (ItemDestroy)(void * item))30 Stack *StackNew(size_t initial_capacity, void (ItemDestroy) (void *item))
31 {
32 Stack *stack = xmalloc(sizeof(Stack));
33
34 StackInit(stack, initial_capacity, ItemDestroy);
35
36 return stack;
37 }
38
StackDestroy(Stack * stack)39 void StackDestroy(Stack *stack)
40 {
41 if (stack != NULL)
42 {
43 DestroyRange(stack, 0, stack->size);
44
45 StackSoftDestroy(stack);
46 }
47 }
48
StackSoftDestroy(Stack * stack)49 void StackSoftDestroy(Stack *stack)
50 {
51 if (stack != NULL)
52 {
53 free(stack->data);
54 free(stack);
55 }
56 }
57
StackPop(Stack * stack)58 void *StackPop(Stack *stack)
59 {
60 assert(stack != NULL);
61
62 size_t size = stack->size;
63 void *item = NULL;
64
65 if (size > 0)
66 {
67 size--;
68 item = stack->data[size];
69
70 stack->data[size] = NULL;
71 stack->size = size;
72 }
73
74 return item;
75 }
76
StackTop(Stack * stack)77 void *StackTop(Stack *stack)
78 {
79 assert(stack != NULL);
80
81 size_t size = stack->size;
82
83 if (size > 0)
84 {
85 return stack->data[size-1];
86 }
87
88 return NULL;
89 }
90
91 /**
92 @brief Expands capacity of stack.
93 @note Assumes that locks are acquired.
94 @param [in] stack Pointer to struct.
95 */
ExpandIfNecessary(Stack * stack)96 static void ExpandIfNecessary(Stack *stack)
97 {
98 assert(stack != NULL);
99 assert(stack->size <= stack->capacity);
100
101 if (stack->size == stack->capacity)
102 {
103 stack->capacity *= EXPAND_FACTOR;
104 stack->data = xrealloc(stack->data, sizeof(void *) * stack->capacity);
105 }
106 }
107
StackPush(Stack * stack,void * item)108 void StackPush(Stack *stack, void *item)
109 {
110 assert(stack != NULL);
111
112 ExpandIfNecessary(stack);
113 stack->data[stack->size++] = item;
114 }
115
StackPushReportCount(Stack * stack,void * item)116 size_t StackPushReportCount(Stack *stack, void *item)
117 {
118 assert(stack != NULL);
119
120 ExpandIfNecessary(stack);
121 stack->data[stack->size++] = item;
122 size_t size = stack->size;
123
124 return size;
125 }
126
StackCount(Stack const * stack)127 size_t StackCount(Stack const *stack)
128 {
129 assert(stack != NULL);
130
131 size_t count = stack->size;
132
133 return count;
134 }
135
StackCapacity(Stack const * stack)136 size_t StackCapacity(Stack const *stack)
137 {
138 assert(stack != NULL);
139
140 size_t capacity = stack->capacity;
141
142 return capacity;
143 }
144
StackIsEmpty(Stack const * stack)145 bool StackIsEmpty(Stack const *stack)
146 {
147 assert(stack != NULL);
148
149 bool const empty = (stack->size == 0);
150
151 return empty;
152 }
153
StackCopy(Stack const * stack)154 Stack *StackCopy(Stack const *stack)
155 {
156 assert(stack != NULL);
157
158 Stack *new_stack = xmemdup(stack, sizeof(Stack));
159 new_stack->data = xmalloc(sizeof(void *) * stack->capacity);
160 memcpy(new_stack->data, stack->data, sizeof(void *) * stack->size);
161
162 return new_stack;
163 }
164