Hybrid ICN (hICN) plugin  v21.06-rc0-4-g18fa668
array.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2019 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
21 #ifndef UTIL_ARRAY_H
22 #define UTIL_ARRAY_H
23 
24 #include <assert.h>
25 #include <hicn/util/log.h>
26 #include <math.h> // log2
27 #include <string.h> // memmove
28 
29 #define BUFSIZE 1024
30 
31 typedef int(*cmp_t)(const void * x, const void * y);
32 
33 #define TYPEDEF_ARRAY_H(NAME, T) \
34  \
35 typedef struct { \
36  size_t size; \
37  size_t max_size_log; \
38  T * elements; \
39 } NAME ## _t; \
40  \
41 int NAME ## _initialize(NAME ## _t * array); \
42  \
43 int NAME ## _finalize(NAME ## _t * array); \
44  \
45 NAME ## _t * NAME ## _create(); \
46  \
47 void NAME ## _free(NAME ## _t * array); \
48  \
49 int NAME ## _add(NAME ## _t * array, T element); \
50  \
51 int NAME ## _remove_index(NAME ## _t * array, int index, T * element); \
52  \
53 int NAME ## _remove(NAME ## _t * array, const T search, T * element); \
54  \
55 int NAME ## _get(const NAME ## _t * array, const T search, T * element); \
56  \
57 int NAME ## _get_index(const NAME ## _t * array, int index, T * element); \
58  \
59 int NAME ## _get_elements(const NAME ## _t * array, T ** elements); \
60  \
61 size_t NAME ## _len(const NAME ## _t * array);
62 
63 
64 #define ARRAY_MAX_SIZE_LOG_INIT 0
65 
66 #define TYPEDEF_ARRAY(NAME, T, CMP, SNPRINTF) \
67 int \
68 NAME ## _initialize(NAME ## _t * array) \
69 { \
70  array->max_size_log = ARRAY_MAX_SIZE_LOG_INIT; \
71  array->size = 0; \
72  if (array->max_size_log == 0) { \
73  array->elements = NULL; \
74  return 0; \
75  } \
76  array->elements = malloc((1 << array->max_size_log) * sizeof(T)); \
77  if (!array->elements) \
78  return -1; \
79  return 0; \
80 } \
81  \
82 int \
83 NAME ## _finalize(NAME ## _t * array) \
84 { \
85  for (unsigned i = 0; i < array->size; i++) { \
86  NAME ## _remove_index(array, i, NULL); \
87  } \
88  return 0; \
89 } \
90  \
91 NAME ## _t * \
92 NAME ## _create() \
93 { \
94  NAME ## _t * array = malloc(sizeof(NAME ## _t)); \
95  if (!array) \
96  goto ERR_MALLOC; \
97  \
98  if (NAME ## _initialize(array) < 0) \
99  goto ERR_INITIALIZE; \
100  \
101  return array; \
102  \
103 ERR_INITIALIZE: \
104  free(array); \
105 ERR_MALLOC: \
106  return NULL; \
107 } \
108  \
109 void \
110 NAME ## _free(NAME ## _t * array) \
111 { \
112  NAME ## _finalize(array); \
113  free(array->elements); \
114  free(array); \
115 } \
116  \
117 int \
118 NAME ## _add(NAME ## _t * array, T element) \
119 { \
120  /* Ensure sufficient space for next addition */ \
121  size_t new_size_log = (array->size > 0) ? log2(array->size)+1 : 1; \
122  if (new_size_log > array->max_size_log) { \
123  array->max_size_log = new_size_log; \
124  array->elements = realloc(array->elements, \
125  (1 << new_size_log) * sizeof(T)); \
126  } \
127  \
128  if (!array->elements) \
129  goto ERR_REALLOC; \
130  \
131  array->elements[array->size++] = element; \
132  return 0; \
133  \
134 ERR_REALLOC: \
135  return -1; \
136 } \
137  \
138 int \
139 NAME ## _remove_index(NAME ## _t * array, int index, T * element) \
140 { \
141  if (index > NAME ## _len(array)) \
142  return -1; \
143  if (element) \
144  *element = array->elements[index]; \
145  if (index < array->size) \
146  memmove(array->elements + index, array->elements + index + 1, \
147  array->size - index); \
148  array->size--; \
149  return 0; \
150 } \
151  \
152 int \
153 NAME ## _remove(NAME ## _t * array, const T search, T * element) \
154 { \
155  for (unsigned i = 0; i < array->size; i++) { \
156  if (CMP(search, array->elements[i]) == 0) \
157  return facelet_array_remove_index(array, i, element); \
158  } \
159  /* Not found */ \
160  if (element) \
161  *element = NULL; \
162  return 0; \
163 } \
164  \
165 int \
166 NAME ## _get(const NAME ## _t * array, const T search, T * element) \
167 { \
168  assert(element); \
169  for (unsigned i = 0; i < array->size; i++) \
170  if (CMP(search, array->elements[i]) == 0) { \
171  *element = array->elements[i]; \
172  return 0; \
173  } \
174  /* Not found */ \
175  *element = NULL; \
176  return 0; \
177 } \
178  \
179 int \
180 NAME ## _get_index(const NAME ## _t * array, int index, T * element) \
181 { \
182  assert(element); \
183  *element = array->elements[index]; \
184  return 0; \
185 } \
186  \
187 int \
188 NAME ## _get_elements(const NAME ## _t * array, T ** elements) \
189 { \
190  *elements = array->elements; \
191  return 0; \
192 } \
193  \
194 size_t \
195 NAME ## _len(const NAME ## _t * array) \
196 { \
197  return array->size; \
198 }
199 
200 #endif /* UTIL_ARRAY_H */