replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / connectivity / common / src / uarraylist.c
1 /******************************************************************
2  *
3  * Copyright 2014 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include "uarraylist.h"
24 #include "logger.h"
25 #include "oic_malloc.h"
26
27 #define TAG "UARRAYLIST"
28
29 /**
30  * Use this default capacity when initialized
31  */
32 #define U_ARRAYLIST_DEFAULT_CAPACITY 1
33
34 u_arraylist_t *u_arraylist_create()
35 {
36     u_arraylist_t *list = (u_arraylist_t *) OICCalloc(1, sizeof(u_arraylist_t));
37     if (!list)
38     {
39         OIC_LOG(DEBUG, TAG, "Out of memory");
40         return NULL;
41     }
42
43     list->capacity = U_ARRAYLIST_DEFAULT_CAPACITY;
44     list->length = 0;
45
46     list->data = (void **) OICMalloc(list->capacity * sizeof(list->data[0]));
47     if (!list->data)
48     {
49         OIC_LOG(DEBUG, TAG, "Out of memory");
50         OICFree(list);
51         return NULL;
52     }
53     return list;
54 }
55
56 void u_arraylist_free(u_arraylist_t **list)
57 {
58     if (!list || !(*list))
59     {
60         return;
61     }
62
63     OICFree((*list)->data);
64     OICFree(*list);
65
66     *list = NULL;
67 }
68
69 bool u_arraylist_reserve(u_arraylist_t *list, size_t count)
70 {
71     if (list && (count > list->capacity))
72     {
73         void *tmp = OICRealloc(list->data, count * sizeof(list->data[0]));
74         if (!tmp)
75         {
76             OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
77             return false;
78         }
79         else
80         {
81             list->data = (void **) tmp;
82             list->capacity = count;
83         }
84     }
85     return true;
86 }
87
88 void u_arraylist_shrink_to_fit(u_arraylist_t *list)
89 {
90     if (!list)
91     {
92         return;
93     }
94
95     if ((list->capacity > list->length)
96         && (list->length >= U_ARRAYLIST_DEFAULT_CAPACITY))
97     {
98         void *tmp = OICRealloc(list->data,
99                                list->length * sizeof(list->data[0]));
100         if (!tmp)
101         {
102             OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
103             // Considered non-fatal as this call is non-binding.
104         }
105         else
106         {
107             list->data = (void **) tmp;
108             list->capacity = list->length;
109         }
110     }
111 }
112
113 void *u_arraylist_get(const u_arraylist_t *list, uint32_t index)
114 {
115     if (!list )
116     {
117         return NULL;
118     }
119
120     if ((index < list->length) && (list->data))
121     {
122         return list->data[index];
123     }
124
125     return NULL;
126 }
127
128 bool u_arraylist_get_index(const u_arraylist_t *list, const void *data, uint32_t *index)
129 {
130     if (!list || !data)
131     {
132         return false;
133     }
134
135     for (uint32_t i = 0; i < list->length; i++)
136     {
137         if (data == list->data[i])
138         {
139             *index = i;
140             return true;
141         }
142     }
143
144     return false;
145 }
146
147 bool u_arraylist_add(u_arraylist_t *list, void *data)
148 {
149     if (!list)
150     {
151         return false;
152     }
153
154     if (list->capacity <= list->length)
155     {
156         // Does a non-FP calcuation of the 1.5 growth factor. Helpful for
157         // certain limited platforms.
158         size_t new_capacity = ((list->capacity * 3) + 1) / 2;
159
160         // In case the re-alloc returns null, use a local variable to avoid
161         // losing the current block of memory.
162         void *tmp = OICRealloc(list->data,
163                                new_capacity * sizeof(list->data[0]));
164         if (!tmp)
165         {
166             OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
167             return false;
168         }
169         list->data = (void **) tmp;
170         memset(list->data + list->capacity, 0,
171                (new_capacity - list->capacity) * sizeof(list->data[0]));
172         list->capacity = (uint32_t)new_capacity;
173     }
174
175     list->data[list->length] = data;
176     list->length++;
177
178     return true;
179 }
180
181 void *u_arraylist_remove(u_arraylist_t *list, uint32_t index)
182 {
183     void *removed = NULL;
184
185     if (!list || (index >= list->length))
186     {
187         return NULL;
188     }
189
190     removed = list->data[index];
191
192     if (index < list->length - 1)
193     {
194         memmove(&list->data[index],
195                 &list->data[index + 1],
196                 (list->length - index - 1) * sizeof(list->data[0]));
197     }
198
199     list->length--;
200
201     return removed;
202 }
203
204 uint32_t u_arraylist_length(const u_arraylist_t *list)
205 {
206     if (!list)
207     {
208         OIC_LOG(DEBUG, TAG, "Invalid Parameter");
209         return 0;
210     }
211     return list->length;
212 }
213
214 bool u_arraylist_contains(const u_arraylist_t *list, const void *data)
215 {
216     if (!list)
217     {
218         return false;
219     }
220
221     for (uint32_t i = 0; i < list->length; i++)
222     {
223         if (data == list->data[i])
224         {
225             return true;
226         }
227     }
228
229     return false;
230 }
231
232 // Assumes elements are shallow (have no pointers to allocated memory)
233 void u_arraylist_destroy(u_arraylist_t *list)
234 {
235     if (!list)
236     {
237         return;
238     }
239     for (uint32_t i = 0; i < list->length; i++)
240     {
241         OICFree(list->data[i]);
242     }
243     (void)u_arraylist_free(&list);
244 }