Fixed u_arraylist to correct performance and missing calls.
[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 size when initialized
31  */
32 #define U_ARRAYLIST_DEFAULT_SIZE 1
33
34 u_arraylist_t *u_arraylist_create()
35 {
36     u_arraylist_t *list = (u_arraylist_t *) OICMalloc(sizeof(u_arraylist_t));
37     if (!list)
38     {
39         OIC_LOG(DEBUG, TAG, "Out of memory");
40         return NULL;
41     }
42
43     list->size = U_ARRAYLIST_DEFAULT_SIZE;
44     list->length = 0;
45
46     list->data = (void **) OICMalloc(list->size * 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 void u_arraylist_reserve(u_arraylist_t *list, size_t count)
70 {
71     if (list && (count > list->size))
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             // Note that this is considered non-fatal.
78         }
79         else
80         {
81             list->data = (void **) tmp;
82             list->size = count;
83         }
84     }
85 }
86
87 void u_arraylist_shrink_to_fit(u_arraylist_t *list)
88 {
89     if (!list)
90     {
91         return;
92     }
93
94     if ((list->size > list->length)
95         && (list->length >= U_ARRAYLIST_DEFAULT_SIZE))
96     {
97         void *tmp = OICRealloc(list->data,
98                                list->length * sizeof(list->data[0]));
99         if (!tmp)
100         {
101             OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
102             // Considered non-fatal as this call is non-binding.
103         }
104         else
105         {
106             list->data = (void **) tmp;
107             list->size = list->length;
108         }
109     }
110 }
111
112 void *u_arraylist_get(const u_arraylist_t *list, uint32_t index)
113 {
114     if (!list )
115     {
116         return NULL;
117     }
118
119     if ((index < list->length) && (list->data))
120     {
121         return list->data[index];
122     }
123
124     return NULL;
125 }
126
127 bool u_arraylist_add(u_arraylist_t *list, void *data)
128 {
129     static const double GROWTH_FACTOR = 1.5;
130     if (!list)
131     {
132         return false;
133     }
134
135     if (list->size <= list->length)
136     {
137         uint32_t new_size = (list->size * GROWTH_FACTOR) + 0.5;
138         // In case the re-alloc returns null, use a local variable to avoid
139         // losing the current block of memory.
140         void *tmp = OICRealloc(list->data, new_size * sizeof(list->data[0]));
141         if (!tmp)
142         {
143             OIC_LOG(DEBUG, TAG, "Memory reallocation failed.");
144             return false;
145         }
146         list->data = (void **) tmp;
147         memset(list->data + list->size, 0,
148                (new_size - list->size) * sizeof(list->data[0]));
149         list->size = new_size;
150     }
151
152     list->data[list->length] = data;
153     list->length++;
154
155     return true;
156 }
157
158 void *u_arraylist_remove(u_arraylist_t *list, uint32_t index)
159 {
160     void *removed = NULL;
161
162     if (!list || (index >= list->length))
163     {
164         return NULL;
165     }
166
167     removed = list->data[index];
168
169     if (index < list->length - 1)
170     {
171         memmove(&list->data[index],
172                 &list->data[index + 1],
173                 (list->length - index - 1) * sizeof(list->data[0]));
174     }
175
176     list->length--;
177
178     return removed;
179 }
180
181 uint32_t u_arraylist_length(const u_arraylist_t *list)
182 {
183     if (!list)
184     {
185         OIC_LOG(DEBUG, TAG, "Invalid Parameter");
186         return 0;
187     }
188     return list->length;
189 }
190
191 bool u_arraylist_contains(const u_arraylist_t *list, const void *data)
192 {
193     if (!list)
194     {
195         return false;
196     }
197
198     for (uint32_t i = 0; i < list->size; i++)
199     {
200         if (data == list->data[i])
201         {
202             return true;
203         }
204     }
205
206     return false;
207 }
208
209 // Assumes elements are shallow (have no pointers to allocated memory)
210 void u_arraylist_destroy(u_arraylist_t *list)
211 {
212     if (!list)
213     {
214         return;
215     }
216     for (uint32_t i = 0; i < list->length; i++)
217     {
218         OICFree(list->data[i]);
219     }
220     (void)u_arraylist_free(&list);
221 }