• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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