1 /*############################################################################
2 # Copyright 2016-2017 Intel Corporation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 ############################################################################*/
16 /*!
17 * \file
18 * \brief Stack container implementation.
19 */
20 #include "epid/common/src/stack.h"
21 #include <limits.h>
22 #include "epid/common/src/memory.h"
23
24 /// Internal representation of a Stack
25 struct Stack {
26 size_t element_size; ///< Size of element in bytes
27 void* buf; ///< Buffer to store elements
28 size_t max_size; ///< Numbers of elements buffer was allocated to
29 size_t top; ///< Stack top, the number of elements in the stack
30 };
31
CreateStack(size_t element_size,Stack ** stack)32 bool CreateStack(size_t element_size, Stack** stack) {
33 if (!stack || 0 == element_size) return false;
34 *stack = SAFE_ALLOC(sizeof(Stack));
35 if (!*stack) return false;
36 (*stack)->element_size = element_size;
37 return true;
38 }
39
StackPushN(Stack * stack,size_t n,void * elements)40 void* StackPushN(Stack* stack, size_t n, void* elements) {
41 if (!stack) return 0;
42 if (n > 0) {
43 size_t max_size_required = stack->top + n;
44 if (n > (SIZE_MAX / stack->element_size) - stack->top)
45 return 0; // integer overflow
46 if (max_size_required > stack->max_size) {
47 void* reallocated =
48 SAFE_REALLOC(stack->buf, max_size_required * stack->element_size);
49 if (!reallocated) return 0;
50 stack->buf = reallocated;
51 stack->max_size = max_size_required;
52 }
53 if (elements) {
54 // Memory copy is used to copy variable number of elements to stack
55 if (0 != memcpy_S((uint8_t*)stack->buf + stack->top * stack->element_size,
56 (stack->max_size - stack->top) * stack->element_size,
57 elements, n * stack->element_size)) {
58 return 0;
59 }
60 }
61 stack->top += n;
62 }
63 return (uint8_t*)stack->buf + (stack->top - n) * stack->element_size;
64 }
65
StackPopN(Stack * stack,size_t n,void * elements)66 bool StackPopN(Stack* stack, size_t n, void* elements) {
67 if (!stack) return false;
68 if (n > 0) {
69 if (n > stack->top) return false;
70 if (elements) {
71 // Memory copy is used to copy variable number of elements from stack
72 if (0 != memcpy_S(elements, n * stack->element_size,
73 (uint8_t*)stack->buf +
74 (stack->top - n) * stack->element_size,
75 n * stack->element_size)) {
76 return false;
77 }
78 stack->top -= n;
79 }
80 }
81 return true;
82 }
83
StackGetSize(Stack const * stack)84 size_t StackGetSize(Stack const* stack) {
85 return stack ? stack->top : (size_t)0;
86 }
87
StackGetBuf(Stack const * stack)88 void* StackGetBuf(Stack const* stack) { return stack ? stack->buf : NULL; }
89
DeleteStack(Stack ** stack)90 void DeleteStack(Stack** stack) {
91 if (stack && *stack) {
92 SAFE_FREE((*stack)->buf);
93 SAFE_FREE(*stack);
94 }
95 }
96