mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-19 04:20:27 +01:00
364 lines
7.2 KiB
C
364 lines
7.2 KiB
C
/*
|
|
* Dynamically Resized Array
|
|
*
|
|
* Authors: Alfredo K. Kojima <kojima@windowmaker.info>
|
|
* Dan Pascu <dan@windowmaker.info>
|
|
*
|
|
* This code is released to the Public Domain, but
|
|
* proper credit is always appreciated :)
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "WUtil.h"
|
|
|
|
#define INITIAL_SIZE 8
|
|
#define RESIZE_INCREMENT 8
|
|
|
|
typedef struct W_Array {
|
|
void **items; /* the array data */
|
|
int itemCount; /* # of items in array */
|
|
int allocSize; /* allocated size of array */
|
|
WMFreeDataProc *destructor; /* the destructor to free elements */
|
|
} W_Array;
|
|
|
|
WMArray *WMCreateArray(int initialSize)
|
|
{
|
|
return WMCreateArrayWithDestructor(initialSize, NULL);
|
|
}
|
|
|
|
WMArray *WMCreateArrayWithDestructor(int initialSize, WMFreeDataProc * destructor)
|
|
{
|
|
WMArray *array;
|
|
|
|
array = wmalloc(sizeof(WMArray));
|
|
|
|
if (initialSize <= 0) {
|
|
initialSize = INITIAL_SIZE;
|
|
}
|
|
|
|
array->items = wmalloc(sizeof(void *) * initialSize);
|
|
|
|
array->itemCount = 0;
|
|
array->allocSize = initialSize;
|
|
array->destructor = destructor;
|
|
|
|
return array;
|
|
}
|
|
|
|
WMArray *WMCreateArrayWithArray(WMArray * array)
|
|
{
|
|
WMArray *newArray;
|
|
|
|
newArray = wmalloc(sizeof(WMArray));
|
|
|
|
newArray->items = wmalloc(sizeof(void *) * array->allocSize);
|
|
memcpy(newArray->items, array->items, sizeof(void *) * array->itemCount);
|
|
|
|
newArray->itemCount = array->itemCount;
|
|
newArray->allocSize = array->allocSize;
|
|
newArray->destructor = NULL;
|
|
|
|
return newArray;
|
|
}
|
|
|
|
void WMEmptyArray(WMArray * array)
|
|
{
|
|
if (array->destructor) {
|
|
while (array->itemCount > 0) {
|
|
array->itemCount--;
|
|
array->destructor(array->items[array->itemCount]);
|
|
}
|
|
}
|
|
/*memset(array->items, 0, array->itemCount * sizeof(void*)); */
|
|
array->itemCount = 0;
|
|
}
|
|
|
|
void WMFreeArray(WMArray * array)
|
|
{
|
|
if (array == NULL)
|
|
return;
|
|
|
|
WMEmptyArray(array);
|
|
wfree(array->items);
|
|
wfree(array);
|
|
}
|
|
|
|
int WMGetArrayItemCount(WMArray * array)
|
|
{
|
|
if (array == NULL)
|
|
return 0;
|
|
|
|
return array->itemCount;
|
|
}
|
|
|
|
void WMAppendArray(WMArray * array, WMArray * other)
|
|
{
|
|
if (array == NULL || other == NULL)
|
|
return;
|
|
|
|
if (other->itemCount == 0)
|
|
return;
|
|
|
|
if (array->itemCount + other->itemCount > array->allocSize) {
|
|
array->allocSize += other->allocSize;
|
|
array->items = wrealloc(array->items, sizeof(void *) * array->allocSize);
|
|
}
|
|
|
|
memcpy(array->items + array->itemCount, other->items, sizeof(void *) * other->itemCount);
|
|
array->itemCount += other->itemCount;
|
|
}
|
|
|
|
void WMAddToArray(WMArray * array, void *item)
|
|
{
|
|
if (array == NULL)
|
|
return;
|
|
|
|
if (array->itemCount >= array->allocSize) {
|
|
array->allocSize += RESIZE_INCREMENT;
|
|
array->items = wrealloc(array->items, sizeof(void *) * array->allocSize);
|
|
}
|
|
array->items[array->itemCount] = item;
|
|
|
|
array->itemCount++;
|
|
}
|
|
|
|
void WMInsertInArray(WMArray * array, int index, void *item)
|
|
{
|
|
wassertr(index >= 0 && index <= array->itemCount);
|
|
|
|
if (array == NULL)
|
|
return;
|
|
|
|
if (array->itemCount >= array->allocSize) {
|
|
array->allocSize += RESIZE_INCREMENT;
|
|
array->items = wrealloc(array->items, sizeof(void *) * array->allocSize);
|
|
}
|
|
if (index < array->itemCount) {
|
|
memmove(array->items + index + 1, array->items + index,
|
|
sizeof(void *) * (array->itemCount - index));
|
|
}
|
|
array->items[index] = item;
|
|
|
|
array->itemCount++;
|
|
}
|
|
|
|
void *WMReplaceInArray(WMArray * array, int index, void *item)
|
|
{
|
|
void *old;
|
|
|
|
wassertrv(index >= 0 && index <= array->itemCount, NULL);
|
|
|
|
if (array == NULL)
|
|
return NULL;
|
|
|
|
/* is it really useful to perform append if index == array->itemCount ? -Dan */
|
|
if (index == array->itemCount) {
|
|
WMAddToArray(array, item);
|
|
return NULL;
|
|
}
|
|
|
|
old = array->items[index];
|
|
array->items[index] = item;
|
|
|
|
return old;
|
|
}
|
|
|
|
int WMDeleteFromArray(WMArray * array, int index)
|
|
{
|
|
wassertrv(index >= 0 && index < array->itemCount, 0);
|
|
|
|
if (array == NULL)
|
|
return 0;
|
|
|
|
if (array->destructor) {
|
|
array->destructor(array->items[index]);
|
|
}
|
|
|
|
if (index < array->itemCount - 1) {
|
|
memmove(array->items + index, array->items + index + 1,
|
|
sizeof(void *) * (array->itemCount - index - 1));
|
|
}
|
|
|
|
array->itemCount--;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int WMRemoveFromArrayMatching(WMArray * array, WMMatchDataProc * match, void *cdata)
|
|
{
|
|
int i;
|
|
|
|
if (array == NULL)
|
|
return 1;
|
|
|
|
if (match != NULL) {
|
|
for (i = 0; i < array->itemCount; i++) {
|
|
if ((*match) (array->items[i], cdata)) {
|
|
WMDeleteFromArray(array, i);
|
|
return 1;
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0; i < array->itemCount; i++) {
|
|
if (array->items[i] == cdata) {
|
|
WMDeleteFromArray(array, i);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *WMGetFromArray(WMArray * array, int index)
|
|
{
|
|
if (index < 0 || array == NULL || index >= array->itemCount)
|
|
return NULL;
|
|
|
|
return array->items[index];
|
|
}
|
|
|
|
void *WMPopFromArray(WMArray * array)
|
|
{
|
|
if (array->itemCount <= 0 || array == NULL)
|
|
return NULL;
|
|
|
|
array->itemCount--;
|
|
|
|
return array->items[array->itemCount];
|
|
}
|
|
|
|
int WMFindInArray(WMArray * array, WMMatchDataProc * match, void *cdata)
|
|
{
|
|
int i;
|
|
|
|
if (array == NULL)
|
|
return WANotFound;
|
|
|
|
if (match != NULL) {
|
|
for (i = 0; i < array->itemCount; i++) {
|
|
if ((*match) (array->items[i], cdata))
|
|
return i;
|
|
}
|
|
} else {
|
|
for (i = 0; i < array->itemCount; i++) {
|
|
if (array->items[i] == cdata)
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return WANotFound;
|
|
}
|
|
|
|
int WMCountInArray(WMArray * array, void *item)
|
|
{
|
|
int i, count;
|
|
|
|
if (array == NULL)
|
|
return 0;
|
|
|
|
for (i = 0, count = 0; i < array->itemCount; i++) {
|
|
if (array->items[i] == item)
|
|
count++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
void WMSortArray(WMArray * array, WMCompareDataProc * comparer)
|
|
{
|
|
if (array == NULL)
|
|
return;
|
|
|
|
if (array->itemCount > 1) { /* Don't sort empty or single element arrays */
|
|
qsort(array->items, array->itemCount, sizeof(void *), comparer);
|
|
}
|
|
}
|
|
|
|
void WMMapArray(WMArray * array, void (*function) (void *, void *), void *data)
|
|
{
|
|
int i;
|
|
|
|
if (array == NULL)
|
|
return;
|
|
|
|
for (i = 0; i < array->itemCount; i++) {
|
|
(*function) (array->items[i], data);
|
|
}
|
|
}
|
|
|
|
WMArray *WMGetSubarrayWithRange(WMArray * array, WMRange aRange)
|
|
{
|
|
WMArray *newArray;
|
|
|
|
if (aRange.count <= 0 || array == NULL)
|
|
return WMCreateArray(0);
|
|
|
|
if (aRange.position < 0)
|
|
aRange.position = 0;
|
|
if (aRange.position >= array->itemCount)
|
|
aRange.position = array->itemCount - 1;
|
|
if (aRange.position + aRange.count > array->itemCount)
|
|
aRange.count = array->itemCount - aRange.position;
|
|
|
|
newArray = WMCreateArray(aRange.count);
|
|
memcpy(newArray->items, array->items + aRange.position, sizeof(void *) * aRange.count);
|
|
newArray->itemCount = aRange.count;
|
|
|
|
return newArray;
|
|
}
|
|
|
|
void *WMArrayFirst(WMArray * array, WMArrayIterator * iter)
|
|
{
|
|
if (array == NULL || array->itemCount == 0) {
|
|
*iter = WANotFound;
|
|
return NULL;
|
|
} else {
|
|
*iter = 0;
|
|
return array->items[0];
|
|
}
|
|
}
|
|
|
|
void *WMArrayLast(WMArray * array, WMArrayIterator * iter)
|
|
{
|
|
if (array == NULL || array->itemCount == 0) {
|
|
*iter = WANotFound;
|
|
return NULL;
|
|
} else {
|
|
*iter = array->itemCount - 1;
|
|
return array->items[*iter];
|
|
}
|
|
}
|
|
|
|
void *WMArrayNext(WMArray * array, WMArrayIterator * iter)
|
|
{
|
|
if (array == NULL) {
|
|
*iter = WANotFound;
|
|
return NULL;
|
|
}
|
|
|
|
if (*iter >= 0 && *iter < array->itemCount - 1) {
|
|
return array->items[++(*iter)];
|
|
} else {
|
|
*iter = WANotFound;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
void *WMArrayPrevious(WMArray * array, WMArrayIterator * iter)
|
|
{
|
|
if (array == NULL) {
|
|
*iter = WANotFound;
|
|
return NULL;
|
|
}
|
|
|
|
if (*iter > 0 && *iter < array->itemCount) {
|
|
return array->items[--(*iter)];
|
|
} else {
|
|
*iter = WANotFound;
|
|
return NULL;
|
|
}
|
|
}
|