Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / array.c
Commit [+]AuthorDateLineData
595d2b06 dan2000-09-15 04:57:31 +00001/*
2 * Dynamically Resized Array
3 *
90c0e656 dan2006-04-25 19:35:14 +00004 * Authors: Alfredo K. Kojima <kojima@windowmaker.info>
5 * Dan Pascu <dan@windowmaker.info>
595d2b06 dan2000-09-15 04:57:31 +00006 *
7 * This code is released to the Public Domain, but
8 * proper credit is always appreciated :)
9 */
10
595d2b06 dan2000-09-15 04:57:31 +000011#include <stdlib.h>
12#include <string.h>
13
14#include "WUtil.h"
15
595d2b06 dan2000-09-15 04:57:31 +000016#define INITIAL_SIZE 8
17#define RESIZE_INCREMENT 8
18
c1a77f23 dan2000-09-20 00:30:45 +000019typedef struct W_Array {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020020 void **items; /* the array data */
21 int itemCount; /* # of items in array */
22 int allocSize; /* allocated size of array */
23 WMFreeDataProc *destructor; /* the destructor to free elements */
595d2b06 dan2000-09-15 04:57:31 +000024} W_Array;
25
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020026WMArray *WMCreateArray(int initialSize)
595d2b06 dan2000-09-15 04:57:31 +000027{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020028 return WMCreateArrayWithDestructor(initialSize, NULL);
9f98db67 dan2000-09-15 09:42:22 +000029}
30
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020031WMArray *WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc * destructor)
9f98db67 dan2000-09-15 09:42:22 +000032{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020033 WMArray *array;
595d2b06 dan2000-09-15 04:57:31 +000034
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020035 array = wmalloc(sizeof(WMArray));
595d2b06 dan2000-09-15 04:57:31 +000036
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020037 if (initialSize <= 0) {
38 initialSize = INITIAL_SIZE;
39 }
595d2b06 dan2000-09-15 04:57:31 +000040
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020041 array->items = wmalloc(sizeof(void *) * initialSize);
595d2b06 dan2000-09-15 04:57:31 +000042
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020043 array->itemCount = 0;
44 array->allocSize = initialSize;
45 array->destructor = destructor;
9f98db67 dan2000-09-15 09:42:22 +000046
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020047 return array;
595d2b06 dan2000-09-15 04:57:31 +000048}
49
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020050WMArray *WMCreateArrayWithArray(WMArray * array)
b2478b63 dan2000-10-01 23:26:03 +000051{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020052 WMArray *newArray;
b2478b63 dan2000-10-01 23:26:03 +000053
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020054 newArray = wmalloc(sizeof(WMArray));
b2478b63 dan2000-10-01 23:26:03 +000055
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020056 newArray->items = wmalloc(sizeof(void *) * array->allocSize);
57 memcpy(newArray->items, array->items, sizeof(void *) * array->itemCount);
b2478b63 dan2000-10-01 23:26:03 +000058
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020059 newArray->itemCount = array->itemCount;
60 newArray->allocSize = array->allocSize;
61 newArray->destructor = NULL;
b2478b63 dan2000-10-01 23:26:03 +000062
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020063 return newArray;
b2478b63 dan2000-10-01 23:26:03 +000064}
65
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020066void WMEmptyArray(WMArray * array)
595d2b06 dan2000-09-15 04:57:31 +000067{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020068 if (array->destructor) {
69 while (array->itemCount > 0) {
70 array->itemCount--;
71 array->destructor(array->items[array->itemCount]);
72 }
73 }
74 /*memset(array->items, 0, array->itemCount * sizeof(void*)); */
75 array->itemCount = 0;
595d2b06 dan2000-09-15 04:57:31 +000076}
77
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020078void WMFreeArray(WMArray * array)
595d2b06 dan2000-09-15 04:57:31 +000079{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020080 WMEmptyArray(array);
81 wfree(array->items);
82 wfree(array);
595d2b06 dan2000-09-15 04:57:31 +000083}
84
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020085int WMGetArrayItemCount(WMArray * array)
595d2b06 dan2000-09-15 04:57:31 +000086{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020087 return array->itemCount;
595d2b06 dan2000-09-15 04:57:31 +000088}
89
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020090void WMAppendArray(WMArray * array, WMArray * other)
595d2b06 dan2000-09-15 04:57:31 +000091{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020092 if (other->itemCount == 0)
93 return;
9f98db67 dan2000-09-15 09:42:22 +000094
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020095 if (array->itemCount + other->itemCount > array->allocSize) {
96 array->allocSize += other->allocSize;
97 array->items = wrealloc(array->items, sizeof(void *) * array->allocSize);
98 }
c1a77f23 dan2000-09-20 00:30:45 +000099
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200100 memcpy(array->items + array->itemCount, other->items, sizeof(void *) * other->itemCount);
101 array->itemCount += other->itemCount;
595d2b06 dan2000-09-15 04:57:31 +0000102}
595d2b06 dan2000-09-15 04:57:31 +0000103
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200104void WMAddToArray(WMArray * array, void *item)
595d2b06 dan2000-09-15 04:57:31 +0000105{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200106 if (array->itemCount >= array->allocSize) {
107 array->allocSize += RESIZE_INCREMENT;
108 array->items = wrealloc(array->items, sizeof(void *) * array->allocSize);
109 }
110 array->items[array->itemCount] = item;
c1a77f23 dan2000-09-20 00:30:45 +0000111
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200112 array->itemCount++;
595d2b06 dan2000-09-15 04:57:31 +0000113}
114
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200115void WMInsertInArray(WMArray * array, int index, void *item)
595d2b06 dan2000-09-15 04:57:31 +0000116{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200117 wassertr(index >= 0 && index <= array->itemCount);
118
119 if (array->itemCount >= array->allocSize) {
120 array->allocSize += RESIZE_INCREMENT;
121 array->items = wrealloc(array->items, sizeof(void *) * array->allocSize);
122 }
123 if (index < array->itemCount) {
124 memmove(array->items + index + 1, array->items + index,
125 sizeof(void *) * (array->itemCount - index));
126 }
127 array->items[index] = item;
128
129 array->itemCount++;
595d2b06 dan2000-09-15 04:57:31 +0000130}
131
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200132void *WMReplaceInArray(WMArray * array, int index, void *item)
595d2b06 dan2000-09-15 04:57:31 +0000133{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200134 void *old;
c1a77f23 dan2000-09-20 00:30:45 +0000135
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200136 wassertrv(index >= 0 && index <= array->itemCount, NULL);
c1a77f23 dan2000-09-20 00:30:45 +0000137
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200138 /* is it really useful to perform append if index == array->itemCount ? -Dan */
139 if (index == array->itemCount) {
140 WMAddToArray(array, item);
141 return NULL;
142 }
c1a77f23 dan2000-09-20 00:30:45 +0000143
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200144 old = array->items[index];
145 array->items[index] = item;
c1a77f23 dan2000-09-20 00:30:45 +0000146
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200147 return old;
85702115 dan2000-09-17 21:52:24 +0000148}
149
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200150int WMDeleteFromArray(WMArray * array, int index)
85702115 dan2000-09-17 21:52:24 +0000151{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200152 wassertrv(index >= 0 && index < array->itemCount, 0);
85702115 dan2000-09-17 21:52:24 +0000153
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200154 if (array->destructor) {
155 array->destructor(array->items[index]);
156 }
85702115 dan2000-09-17 21:52:24 +0000157
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200158 if (index < array->itemCount - 1) {
159 memmove(array->items + index, array->items + index + 1,
160 sizeof(void *) * (array->itemCount - index - 1));
161 }
40e67dfc dan2000-09-21 01:25:47 +0000162
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200163 array->itemCount--;
c1a77f23 dan2000-09-20 00:30:45 +0000164
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200165 return 1;
c1a77f23 dan2000-09-20 00:30:45 +0000166}
167
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200168int WMRemoveFromArrayMatching(WMArray * array, WMMatchDataProc * match, void *cdata)
c1a77f23 dan2000-09-20 00:30:45 +0000169{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200170 int i;
171
172 if (match != NULL) {
173 for (i = 0; i < array->itemCount; i++) {
174 if ((*match) (array->items[i], cdata)) {
175 WMDeleteFromArray(array, i);
176 return 1;
177 }
178 }
179 } else {
180 for (i = 0; i < array->itemCount; i++) {
181 if (array->items[i] == cdata) {
182 WMDeleteFromArray(array, i);
183 return 1;
184 }
185 }
186 }
187
188 return 0;
c1a77f23 dan2000-09-20 00:30:45 +0000189}
190
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200191void *WMGetFromArray(WMArray * array, int index)
c1a77f23 dan2000-09-20 00:30:45 +0000192{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200193 if (index < 0 || index >= array->itemCount)
194 return NULL;
c1a77f23 dan2000-09-20 00:30:45 +0000195
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200196 return array->items[index];
85702115 dan2000-09-17 21:52:24 +0000197}
198
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200199void *WMPopFromArray(WMArray * array)
595d2b06 dan2000-09-15 04:57:31 +0000200{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200201 array->itemCount--;
595d2b06 dan2000-09-15 04:57:31 +0000202
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200203 return array->items[array->itemCount];
595d2b06 dan2000-09-15 04:57:31 +0000204}
205
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200206int WMFindInArray(WMArray * array, WMMatchDataProc * match, void *cdata)
595d2b06 dan2000-09-15 04:57:31 +0000207{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200208 int i;
209
210 if (match != NULL) {
211 for (i = 0; i < array->itemCount; i++) {
212 if ((*match) (array->items[i], cdata))
213 return i;
214 }
215 } else {
216 for (i = 0; i < array->itemCount; i++) {
217 if (array->items[i] == cdata)
218 return i;
219 }
220 }
221
222 return WANotFound;
c1a77f23 dan2000-09-20 00:30:45 +0000223}
224
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200225int WMCountInArray(WMArray * array, void *item)
c1a77f23 dan2000-09-20 00:30:45 +0000226{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200227 int i, count;
c1a77f23 dan2000-09-20 00:30:45 +0000228
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200229 for (i = 0, count = 0; i < array->itemCount; i++) {
230 if (array->items[i] == item)
231 count++;
232 }
c1a77f23 dan2000-09-20 00:30:45 +0000233
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200234 return count;
c1a77f23 dan2000-09-20 00:30:45 +0000235}
236
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200237void WMSortArray(WMArray * array, WMCompareDataProc * comparer)
c1a77f23 dan2000-09-20 00:30:45 +0000238{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200239 if (array->itemCount > 1) { /* Don't sort empty or single element arrays */
240 qsort(array->items, array->itemCount, sizeof(void *), comparer);
241 }
c1a77f23 dan2000-09-20 00:30:45 +0000242}
243
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200244void WMMapArray(WMArray * array, void (*function) (void *, void *), void *data)
c1a77f23 dan2000-09-20 00:30:45 +0000245{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200246 int i;
c1a77f23 dan2000-09-20 00:30:45 +0000247
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200248 for (i = 0; i < array->itemCount; i++) {
249 (*function) (array->items[i], data);
250 }
595d2b06 dan2000-09-15 04:57:31 +0000251}
9f98db67 dan2000-09-15 09:42:22 +0000252
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200253WMArray *WMGetSubarrayWithRange(WMArray * array, WMRange aRange)
b2478b63 dan2000-10-01 23:26:03 +0000254{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200255 WMArray *newArray;
b2478b63 dan2000-10-01 23:26:03 +0000256
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200257 if (aRange.count <= 0)
258 return WMCreateArray(0);
b2478b63 dan2000-10-01 23:26:03 +0000259
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200260 if (aRange.position < 0)
261 aRange.position = 0;
262 if (aRange.position >= array->itemCount)
263 aRange.position = array->itemCount - 1;
264 if (aRange.position + aRange.count > array->itemCount)
265 aRange.count = array->itemCount - aRange.position;
b2478b63 dan2000-10-01 23:26:03 +0000266
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200267 newArray = WMCreateArray(aRange.count);
268 memcpy(newArray->items, array->items + aRange.position, sizeof(void *) * aRange.count);
269 newArray->itemCount = aRange.count;
b2478b63 dan2000-10-01 23:26:03 +0000270
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200271 return newArray;
b2478b63 dan2000-10-01 23:26:03 +0000272}
273
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200274void *WMArrayFirst(WMArray * array, WMArrayIterator * iter)
046403db dan2001-04-15 01:22:56 +0000275{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200276 if (array->itemCount == 0) {
277 *iter = WANotFound;
278 return NULL;
279 } else {
280 *iter = 0;
281 return array->items[0];
282 }
046403db dan2001-04-15 01:22:56 +0000283}
284
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200285void *WMArrayLast(WMArray * array, WMArrayIterator * iter)
046403db dan2001-04-15 01:22:56 +0000286{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200287 if (array->itemCount == 0) {
288 *iter = WANotFound;
289 return NULL;
290 } else {
291 *iter = array->itemCount - 1;
292 return array->items[*iter];
293 }
046403db dan2001-04-15 01:22:56 +0000294}
295
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200296void *WMArrayNext(WMArray * array, WMArrayIterator * iter)
046403db dan2001-04-15 01:22:56 +0000297{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200298 if (*iter >= 0 && *iter < array->itemCount - 1) {
299 return array->items[++(*iter)];
300 } else {
301 *iter = WANotFound;
302 return NULL;
303 }
046403db dan2001-04-15 01:22:56 +0000304}
305
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200306void *WMArrayPrevious(WMArray * array, WMArrayIterator * iter)
046403db dan2001-04-15 01:22:56 +0000307{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200308 if (*iter > 0 && *iter < array->itemCount) {
309 return array->items[--(*iter)];
310 } else {
311 *iter = WANotFound;
312 return NULL;
313 }
046403db dan2001-04-15 01:22:56 +0000314}