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
)
85 int WMGetArrayItemCount(WMArray
* array
)
87 return array
->itemCount
;
90 void WMAppendArray(WMArray
* array
, WMArray
* other
)
92 if (other
->itemCount
== 0)
95 if (array
->itemCount
+ other
->itemCount
> array
->allocSize
) {
96 array
->allocSize
+= other
->allocSize
;
97 array
->items
= wrealloc(array
->items
, sizeof(void *) * array
->allocSize
);
100 memcpy(array
->items
+ array
->itemCount
, other
->items
, sizeof(void *) * other
->itemCount
);
101 array
->itemCount
+= other
->itemCount
;
104 void WMAddToArray(WMArray
* array
, void *item
)
106 if (array
->itemCount
>= array
->allocSize
) {
107 array
->allocSize
+= RESIZE_INCREMENT
;
108 array
->items
= wrealloc(array
->items
, sizeof(void *) * array
->allocSize
);
110 array
->items
[array
->itemCount
] = item
;
115 void WMInsertInArray(WMArray
* array
, int index
, void *item
)
117 wassertr(index
>= 0 && index
<= array
->itemCount
);
119 if (array
->itemCount
>= array
->allocSize
) {
120 array
->allocSize
+= RESIZE_INCREMENT
;
121 array
->items
= wrealloc(array
->items
, sizeof(void *) * array
->allocSize
);
123 if (index
< array
->itemCount
) {
124 memmove(array
->items
+ index
+ 1, array
->items
+ index
,
125 sizeof(void *) * (array
->itemCount
- index
));
127 array
->items
[index
] = item
;
132 void *WMReplaceInArray(WMArray
* array
, int index
, void *item
)
136 wassertrv(index
>= 0 && index
<= array
->itemCount
, NULL
);
138 /* is it really useful to perform append if index == array->itemCount ? -Dan */
139 if (index
== array
->itemCount
) {
140 WMAddToArray(array
, item
);
144 old
= array
->items
[index
];
145 array
->items
[index
] = item
;
150 int WMDeleteFromArray(WMArray
* array
, int index
)
152 wassertrv(index
>= 0 && index
< array
->itemCount
, 0);
154 if (array
->destructor
) {
155 array
->destructor(array
->items
[index
]);
158 if (index
< array
->itemCount
- 1) {
159 memmove(array
->items
+ index
, array
->items
+ index
+ 1,
160 sizeof(void *) * (array
->itemCount
- index
- 1));
168 int WMRemoveFromArrayMatching(WMArray
* array
, WMMatchDataProc
* match
, void *cdata
)
173 for (i
= 0; i
< array
->itemCount
; i
++) {
174 if ((*match
) (array
->items
[i
], cdata
)) {
175 WMDeleteFromArray(array
, i
);
180 for (i
= 0; i
< array
->itemCount
; i
++) {
181 if (array
->items
[i
] == cdata
) {
182 WMDeleteFromArray(array
, i
);
191 void *WMGetFromArray(WMArray
* array
, int index
)
193 if (index
< 0 || index
>= array
->itemCount
)
196 return array
->items
[index
];
199 void *WMPopFromArray(WMArray
* array
)
203 return array
->items
[array
->itemCount
];
206 int WMFindInArray(WMArray
* array
, WMMatchDataProc
* match
, void *cdata
)
211 for (i
= 0; i
< array
->itemCount
; i
++) {
212 if ((*match
) (array
->items
[i
], cdata
))
216 for (i
= 0; i
< array
->itemCount
; i
++) {
217 if (array
->items
[i
] == cdata
)
225 int WMCountInArray(WMArray
* array
, void *item
)
229 for (i
= 0, count
= 0; i
< array
->itemCount
; i
++) {
230 if (array
->items
[i
] == item
)
237 void WMSortArray(WMArray
* array
, WMCompareDataProc
* comparer
)
239 if (array
->itemCount
> 1) { /* Don't sort empty or single element arrays */
240 qsort(array
->items
, array
->itemCount
, sizeof(void *), comparer
);
244 void WMMapArray(WMArray
* array
, void (*function
) (void *, void *), void *data
)
248 for (i
= 0; i
< array
->itemCount
; i
++) {
249 (*function
) (array
->items
[i
], data
);
253 WMArray
*WMGetSubarrayWithRange(WMArray
* array
, WMRange aRange
)
257 if (aRange
.count
<= 0)
258 return WMCreateArray(0);
260 if (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
;
267 newArray
= WMCreateArray(aRange
.count
);
268 memcpy(newArray
->items
, array
->items
+ aRange
.position
, sizeof(void *) * aRange
.count
);
269 newArray
->itemCount
= aRange
.count
;
274 void *WMArrayFirst(WMArray
* array
, WMArrayIterator
* iter
)
276 if (array
->itemCount
== 0) {
281 return array
->items
[0];
285 void *WMArrayLast(WMArray
* array
, WMArrayIterator
* iter
)
287 if (array
->itemCount
== 0) {
291 *iter
= array
->itemCount
- 1;
292 return array
->items
[*iter
];
296 void *WMArrayNext(WMArray
* array
, WMArrayIterator
* iter
)
298 if (*iter
>= 0 && *iter
< array
->itemCount
- 1) {
299 return array
->items
[++(*iter
)];
306 void *WMArrayPrevious(WMArray
* array
, WMArrayIterator
* iter
)
308 if (*iter
> 0 && *iter
< array
->itemCount
) {
309 return array
->items
[--(*iter
)];