2 * Dynamically Resized Array
4 * Authors: Alfredo K. Kojima <kojima@windowmaker.info>
5 * Dan Pascu <dan@windowmaker.info>
7 * This code is released to the Public Domain, but
8 * proper credit is always appreciated :)
16 #define INITIAL_SIZE 8
17 #define RESIZE_INCREMENT 8
19 typedef struct W_Array
{
20 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 */
26 WMArray
*WMCreateArray(int initialSize
)
28 return WMCreateArrayWithDestructor(initialSize
, NULL
);
31 WMArray
*WMCreateArrayWithDestructor(int initialSize
, WMFreeDataProc
* destructor
)
35 array
= wmalloc(sizeof(WMArray
));
37 if (initialSize
<= 0) {
38 initialSize
= INITIAL_SIZE
;
41 array
->items
= wmalloc(sizeof(void *) * initialSize
);
44 array
->allocSize
= initialSize
;
45 array
->destructor
= destructor
;
50 WMArray
*WMCreateArrayWithArray(WMArray
* array
)
54 newArray
= wmalloc(sizeof(WMArray
));
56 newArray
->items
= wmalloc(sizeof(void *) * array
->allocSize
);
57 memcpy(newArray
->items
, array
->items
, sizeof(void *) * array
->itemCount
);
59 newArray
->itemCount
= array
->itemCount
;
60 newArray
->allocSize
= array
->allocSize
;
61 newArray
->destructor
= NULL
;
66 void WMEmptyArray(WMArray
* array
)
68 if (array
->destructor
) {
69 while (array
->itemCount
> 0) {
71 array
->destructor(array
->items
[array
->itemCount
]);
74 /*memset(array->items, 0, array->itemCount * sizeof(void*)); */
78 void WMFreeArray(WMArray
* array
)
88 int WMGetArrayItemCount(WMArray
* array
)
93 return array
->itemCount
;
96 void WMAppendArray(WMArray
* array
, WMArray
* other
)
98 if (array
== NULL
|| other
== NULL
)
101 if (other
->itemCount
== 0)
104 if (array
->itemCount
+ other
->itemCount
> array
->allocSize
) {
105 array
->allocSize
+= other
->allocSize
;
106 array
->items
= wrealloc(array
->items
, sizeof(void *) * array
->allocSize
);
109 memcpy(array
->items
+ array
->itemCount
, other
->items
, sizeof(void *) * other
->itemCount
);
110 array
->itemCount
+= other
->itemCount
;
113 void WMAddToArray(WMArray
* array
, void *item
)
118 if (array
->itemCount
>= array
->allocSize
) {
119 array
->allocSize
+= RESIZE_INCREMENT
;
120 array
->items
= wrealloc(array
->items
, sizeof(void *) * array
->allocSize
);
122 array
->items
[array
->itemCount
] = item
;
127 void WMInsertInArray(WMArray
* array
, int index
, void *item
)
132 wassertr(index
>= 0 && index
<= array
->itemCount
);
134 if (array
->itemCount
>= array
->allocSize
) {
135 array
->allocSize
+= RESIZE_INCREMENT
;
136 array
->items
= wrealloc(array
->items
, sizeof(void *) * array
->allocSize
);
138 if (index
< array
->itemCount
) {
139 memmove(array
->items
+ index
+ 1, array
->items
+ index
,
140 sizeof(void *) * (array
->itemCount
- index
));
142 array
->items
[index
] = item
;
147 void *WMReplaceInArray(WMArray
* array
, int index
, void *item
)
154 wassertrv(index
>= 0 && index
<= array
->itemCount
, NULL
);
156 /* is it really useful to perform append if index == array->itemCount ? -Dan */
157 if (index
== array
->itemCount
) {
158 WMAddToArray(array
, item
);
162 old
= array
->items
[index
];
163 array
->items
[index
] = item
;
168 int WMDeleteFromArray(WMArray
* array
, int index
)
173 wassertrv(index
>= 0 && index
< array
->itemCount
, 0);
175 if (array
->destructor
) {
176 array
->destructor(array
->items
[index
]);
179 if (index
< array
->itemCount
- 1) {
180 memmove(array
->items
+ index
, array
->items
+ index
+ 1,
181 sizeof(void *) * (array
->itemCount
- index
- 1));
189 int WMRemoveFromArrayMatching(WMArray
* array
, WMMatchDataProc
* match
, void *cdata
)
197 for (i
= 0; i
< array
->itemCount
; i
++) {
198 if ((*match
) (array
->items
[i
], cdata
)) {
199 WMDeleteFromArray(array
, i
);
204 for (i
= 0; i
< array
->itemCount
; i
++) {
205 if (array
->items
[i
] == cdata
) {
206 WMDeleteFromArray(array
, i
);
215 void *WMGetFromArray(WMArray
* array
, int index
)
217 if (index
< 0 || array
== NULL
|| index
>= array
->itemCount
)
220 return array
->items
[index
];
223 void *WMPopFromArray(WMArray
* array
)
225 if (array
== NULL
|| array
->itemCount
<= 0)
230 return array
->items
[array
->itemCount
];
233 int WMFindInArray(WMArray
* array
, WMMatchDataProc
* match
, void *cdata
)
241 for (i
= 0; i
< array
->itemCount
; i
++) {
242 if ((*match
) (array
->items
[i
], cdata
))
246 for (i
= 0; i
< array
->itemCount
; i
++) {
247 if (array
->items
[i
] == cdata
)
255 int WMCountInArray(WMArray
* array
, void *item
)
262 for (i
= 0, count
= 0; i
< array
->itemCount
; i
++) {
263 if (array
->items
[i
] == item
)
270 void WMSortArray(WMArray
* array
, WMCompareDataProc
* comparer
)
275 if (array
->itemCount
> 1) { /* Don't sort empty or single element arrays */
276 qsort(array
->items
, array
->itemCount
, sizeof(void *), comparer
);
280 void WMMapArray(WMArray
* array
, void (*function
) (void *, void *), void *data
)
287 for (i
= 0; i
< array
->itemCount
; i
++) {
288 (*function
) (array
->items
[i
], data
);
292 WMArray
*WMGetSubarrayWithRange(WMArray
* array
, WMRange aRange
)
296 if (aRange
.count
<= 0 || array
== NULL
)
297 return WMCreateArray(0);
299 if (aRange
.position
< 0)
301 if (aRange
.position
>= array
->itemCount
)
302 aRange
.position
= array
->itemCount
- 1;
303 if (aRange
.position
+ aRange
.count
> array
->itemCount
)
304 aRange
.count
= array
->itemCount
- aRange
.position
;
306 newArray
= WMCreateArray(aRange
.count
);
307 memcpy(newArray
->items
, array
->items
+ aRange
.position
, sizeof(void *) * aRange
.count
);
308 newArray
->itemCount
= aRange
.count
;
313 void *WMArrayFirst(WMArray
* array
, WMArrayIterator
* iter
)
315 if (array
== NULL
|| array
->itemCount
== 0) {
320 return array
->items
[0];
324 void *WMArrayLast(WMArray
* array
, WMArrayIterator
* iter
)
326 if (array
== NULL
|| array
->itemCount
== 0) {
330 *iter
= array
->itemCount
- 1;
331 return array
->items
[*iter
];
335 void *WMArrayNext(WMArray
* array
, WMArrayIterator
* iter
)
342 if (*iter
>= 0 && *iter
< array
->itemCount
- 1) {
343 return array
->items
[++(*iter
)];
350 void *WMArrayPrevious(WMArray
* array
, WMArrayIterator
* iter
)
357 if (*iter
> 0 && *iter
< array
->itemCount
) {
358 return array
->items
[--(*iter
)];