FreeRDP
Stack.c
1 
20 #include <winpr/config.h>
21 
22 #include <winpr/collections.h>
23 #include <winpr/assert.h>
24 
25 struct s_wStack
26 {
27  size_t size;
28  size_t capacity;
29  void** array;
30  CRITICAL_SECTION lock;
31  BOOL synchronized;
32  wObject object;
33 };
34 
48 size_t Stack_Count(wStack* stack)
49 {
50  size_t ret = 0;
51  WINPR_ASSERT(stack);
52  if (stack->synchronized)
53  EnterCriticalSection(&stack->lock);
54 
55  ret = stack->size;
56 
57  if (stack->synchronized)
58  LeaveCriticalSection(&stack->lock);
59 
60  return ret;
61 }
62 
67 BOOL Stack_IsSynchronized(wStack* stack)
68 {
69  WINPR_ASSERT(stack);
70  return stack->synchronized;
71 }
72 
73 wObject* Stack_Object(wStack* stack)
74 {
75  WINPR_ASSERT(stack);
76  return &stack->object;
77 }
78 
87 void Stack_Clear(wStack* stack)
88 {
89  WINPR_ASSERT(stack);
90  if (stack->synchronized)
91  EnterCriticalSection(&stack->lock);
92 
93  for (size_t index = 0; index < stack->size; index++)
94  {
95  if (stack->object.fnObjectFree)
96  stack->object.fnObjectFree(stack->array[index]);
97 
98  stack->array[index] = NULL;
99  }
100 
101  stack->size = 0;
102 
103  if (stack->synchronized)
104  LeaveCriticalSection(&stack->lock);
105 }
106 
111 BOOL Stack_Contains(wStack* stack, const void* obj)
112 {
113  BOOL found = FALSE;
114 
115  WINPR_ASSERT(stack);
116  if (stack->synchronized)
117  EnterCriticalSection(&stack->lock);
118 
119  for (size_t i = 0; i < stack->size; i++)
120  {
121  if (stack->object.fnObjectEquals(stack->array[i], obj))
122  {
123  found = TRUE;
124  break;
125  }
126  }
127 
128  if (stack->synchronized)
129  LeaveCriticalSection(&stack->lock);
130 
131  return found;
132 }
133 
138 void Stack_Push(wStack* stack, void* obj)
139 {
140  WINPR_ASSERT(stack);
141  if (stack->synchronized)
142  EnterCriticalSection(&stack->lock);
143 
144  if ((stack->size + 1) >= stack->capacity)
145  {
146  const size_t new_cap = stack->capacity * 2;
147  void** new_arr = (void**)realloc(stack->array, sizeof(void*) * new_cap);
148 
149  if (!new_arr)
150  goto end;
151 
152  stack->array = new_arr;
153  stack->capacity = new_cap;
154  }
155 
156  stack->array[(stack->size)++] = obj;
157 
158 end:
159  if (stack->synchronized)
160  LeaveCriticalSection(&stack->lock);
161 }
162 
167 void* Stack_Pop(wStack* stack)
168 {
169  void* obj = NULL;
170 
171  WINPR_ASSERT(stack);
172  if (stack->synchronized)
173  EnterCriticalSection(&stack->lock);
174 
175  if (stack->size > 0)
176  obj = stack->array[--(stack->size)];
177 
178  if (stack->synchronized)
179  LeaveCriticalSection(&stack->lock);
180 
181  return obj;
182 }
183 
188 void* Stack_Peek(wStack* stack)
189 {
190  void* obj = NULL;
191 
192  WINPR_ASSERT(stack);
193  if (stack->synchronized)
194  EnterCriticalSection(&stack->lock);
195 
196  if (stack->size > 0)
197  obj = stack->array[stack->size - 1];
198 
199  if (stack->synchronized)
200  LeaveCriticalSection(&stack->lock);
201 
202  return obj;
203 }
204 
205 static BOOL default_stack_equals(const void* obj1, const void* obj2)
206 {
207  return (obj1 == obj2);
208 }
209 
214 wStack* Stack_New(BOOL synchronized)
215 {
216  wStack* stack = NULL;
217  stack = (wStack*)calloc(1, sizeof(wStack));
218 
219  if (!stack)
220  return NULL;
221 
222  stack->object.fnObjectEquals = default_stack_equals;
223  stack->synchronized = synchronized;
224  stack->capacity = 32;
225  stack->array = (void**)calloc(stack->capacity, sizeof(void*));
226 
227  if (!stack->array)
228  goto out_free;
229 
230  if (stack->synchronized && !InitializeCriticalSectionAndSpinCount(&stack->lock, 4000))
231  goto out_free;
232 
233  return stack;
234 out_free:
235  WINPR_PRAGMA_DIAG_PUSH
236  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
237  Stack_Free(stack);
238  WINPR_PRAGMA_DIAG_POP
239  return NULL;
240 }
241 
242 void Stack_Free(wStack* stack)
243 {
244  if (stack)
245  {
246  if (stack->synchronized)
247  DeleteCriticalSection(&stack->lock);
248 
249  free(stack->array);
250  free(stack);
251  }
252 }
This struct contains function pointer to initialize/free objects.
Definition: collections.h:57