14ecf7bb9SMasatake YAMATO /* 24ecf7bb9SMasatake YAMATO * Copyright (c) 1999-2002, Darren Hiebert 34ecf7bb9SMasatake YAMATO * 44ecf7bb9SMasatake YAMATO * This source code is released for free distribution under the terms of the 54ecf7bb9SMasatake YAMATO * GNU General Public License version 2 or (at your option) any later version. 64ecf7bb9SMasatake YAMATO * 74ecf7bb9SMasatake YAMATO * This module contains functions managing resizable pointer arrays. 84ecf7bb9SMasatake YAMATO */ 94ecf7bb9SMasatake YAMATO 104ecf7bb9SMasatake YAMATO /* 114ecf7bb9SMasatake YAMATO * INCLUDE FILES 124ecf7bb9SMasatake YAMATO */ 134ecf7bb9SMasatake YAMATO #include "general.h" /* must always come first */ 144ecf7bb9SMasatake YAMATO 154ecf7bb9SMasatake YAMATO #include "debug.h" 164ecf7bb9SMasatake YAMATO #include "numarray.h" 1714781660SMasatake YAMATO #include "routines.h" 184ecf7bb9SMasatake YAMATO 1921ba4f38SMasatake YAMATO #include <stdlib.h> 2021ba4f38SMasatake YAMATO #include <string.h> 214ecf7bb9SMasatake YAMATO 224ecf7bb9SMasatake YAMATO #define impNumArray(prefix,Prefix,type) \ 234ecf7bb9SMasatake YAMATO \ 244ecf7bb9SMasatake YAMATO struct s##Prefix##Array { \ 254ecf7bb9SMasatake YAMATO unsigned int max; \ 264ecf7bb9SMasatake YAMATO unsigned int count; \ 274ecf7bb9SMasatake YAMATO type *array; \ 284ecf7bb9SMasatake YAMATO }; \ 294ecf7bb9SMasatake YAMATO \ 304ecf7bb9SMasatake YAMATO extern prefix##Array *prefix##ArrayNew (void) \ 314ecf7bb9SMasatake YAMATO { \ 324ecf7bb9SMasatake YAMATO prefix##Array* const result = xMalloc (1, prefix##Array); \ 334ecf7bb9SMasatake YAMATO result->max = 8; \ 344ecf7bb9SMasatake YAMATO result->count = 0; \ 354ecf7bb9SMasatake YAMATO result->array = xMalloc (result->max, type); \ 364ecf7bb9SMasatake YAMATO return result; \ 374ecf7bb9SMasatake YAMATO } \ 384ecf7bb9SMasatake YAMATO \ 39b47ea137SMasatake YAMATO extern unsigned int prefix##ArrayAdd (prefix##Array *const current, type num) \ 404ecf7bb9SMasatake YAMATO { \ 414ecf7bb9SMasatake YAMATO Assert (current != NULL); \ 424ecf7bb9SMasatake YAMATO if (current->count == current->max) \ 434ecf7bb9SMasatake YAMATO { \ 444ecf7bb9SMasatake YAMATO current->max *= 2; \ 454ecf7bb9SMasatake YAMATO current->array = xRealloc (current->array, current->max, type); \ 464ecf7bb9SMasatake YAMATO } \ 47b47ea137SMasatake YAMATO current->array [current->count] = num; \ 48b47ea137SMasatake YAMATO return current->count++; \ 494ecf7bb9SMasatake YAMATO } \ 504ecf7bb9SMasatake YAMATO \ 514ecf7bb9SMasatake YAMATO extern void prefix##ArrayRemoveLast (prefix##Array *const current) \ 524ecf7bb9SMasatake YAMATO { \ 534ecf7bb9SMasatake YAMATO Assert (current != NULL); \ 544ecf7bb9SMasatake YAMATO Assert (current->count > 0); \ 554ecf7bb9SMasatake YAMATO --current->count; \ 564ecf7bb9SMasatake YAMATO } \ 574ecf7bb9SMasatake YAMATO \ 584ecf7bb9SMasatake YAMATO extern void prefix##ArrayCombine (prefix##Array *const current, prefix##Array *const from) \ 594ecf7bb9SMasatake YAMATO { \ 604ecf7bb9SMasatake YAMATO unsigned int i; \ 614ecf7bb9SMasatake YAMATO Assert (current != NULL); \ 624ecf7bb9SMasatake YAMATO Assert (from != NULL); \ 634ecf7bb9SMasatake YAMATO for (i = 0 ; i < from->count ; ++i) \ 644ecf7bb9SMasatake YAMATO prefix##ArrayAdd (current, from->array [i]); \ 654ecf7bb9SMasatake YAMATO from->count = 0; \ 664ecf7bb9SMasatake YAMATO prefix##ArrayDelete (from); \ 674ecf7bb9SMasatake YAMATO } \ 684ecf7bb9SMasatake YAMATO \ 694ecf7bb9SMasatake YAMATO extern unsigned int prefix##ArrayCount (const prefix##Array *const current) \ 704ecf7bb9SMasatake YAMATO { \ 714ecf7bb9SMasatake YAMATO Assert (current != NULL); \ 724ecf7bb9SMasatake YAMATO return current->count; \ 734ecf7bb9SMasatake YAMATO } \ 744ecf7bb9SMasatake YAMATO \ 75090f0bb7SMasatake YAMATO extern bool prefix##ArrayIsEmpty (const prefix##Array *const current) \ 76090f0bb7SMasatake YAMATO { \ 77090f0bb7SMasatake YAMATO return (prefix##ArrayCount(current) == 0); \ 78090f0bb7SMasatake YAMATO } \ 79090f0bb7SMasatake YAMATO \ 804ecf7bb9SMasatake YAMATO extern type prefix##ArrayItem (const prefix##Array *const current, const unsigned int indx) \ 814ecf7bb9SMasatake YAMATO { \ 824ecf7bb9SMasatake YAMATO Assert (current != NULL); \ 834ecf7bb9SMasatake YAMATO return current->array [indx]; \ 844ecf7bb9SMasatake YAMATO } \ 854ecf7bb9SMasatake YAMATO \ 864ecf7bb9SMasatake YAMATO extern type prefix##ArrayLast (const prefix##Array *const current) \ 874ecf7bb9SMasatake YAMATO { \ 884ecf7bb9SMasatake YAMATO Assert (current != NULL); \ 894ecf7bb9SMasatake YAMATO Assert (current->count > 0); \ 904ecf7bb9SMasatake YAMATO return current->array [current->count - 1]; \ 914ecf7bb9SMasatake YAMATO } \ 924ecf7bb9SMasatake YAMATO \ 934ecf7bb9SMasatake YAMATO extern void prefix##ArrayClear (prefix##Array *const current) \ 944ecf7bb9SMasatake YAMATO { \ 954ecf7bb9SMasatake YAMATO Assert (current != NULL); \ 964ecf7bb9SMasatake YAMATO current->count = 0; \ 974ecf7bb9SMasatake YAMATO } \ 984ecf7bb9SMasatake YAMATO \ 994ecf7bb9SMasatake YAMATO extern void prefix##ArrayDelete (prefix##Array *const current) \ 1004ecf7bb9SMasatake YAMATO { \ 1014ecf7bb9SMasatake YAMATO if (current != NULL) \ 1024ecf7bb9SMasatake YAMATO { \ 1034ecf7bb9SMasatake YAMATO prefix##ArrayClear (current); \ 1044ecf7bb9SMasatake YAMATO eFree (current->array); \ 1054ecf7bb9SMasatake YAMATO eFree (current); \ 1064ecf7bb9SMasatake YAMATO } \ 1074ecf7bb9SMasatake YAMATO } \ 1084ecf7bb9SMasatake YAMATO \ 1094ecf7bb9SMasatake YAMATO extern bool prefix##ArrayHasTest (const prefix##Array *const current, \ 1104ecf7bb9SMasatake YAMATO bool (*test)(const type num, void *userData), \ 1114ecf7bb9SMasatake YAMATO void *userData) \ 1124ecf7bb9SMasatake YAMATO { \ 1134ecf7bb9SMasatake YAMATO bool result = false; \ 1144ecf7bb9SMasatake YAMATO unsigned int i; \ 1154ecf7bb9SMasatake YAMATO Assert (current != NULL); \ 1164ecf7bb9SMasatake YAMATO for (i = 0 ; ! result && i < current->count ; ++i) \ 1174ecf7bb9SMasatake YAMATO result = (*test)(current->array [i], userData); \ 1184ecf7bb9SMasatake YAMATO return result; \ 1194ecf7bb9SMasatake YAMATO } \ 1204ecf7bb9SMasatake YAMATO \ 1214ecf7bb9SMasatake YAMATO static bool prefix##Eq (const type num, void *userData) \ 1224ecf7bb9SMasatake YAMATO { \ 1234ecf7bb9SMasatake YAMATO type *num0 = userData; \ 1244ecf7bb9SMasatake YAMATO return (num == *num0); \ 1254ecf7bb9SMasatake YAMATO } \ 1264ecf7bb9SMasatake YAMATO \ 1274ecf7bb9SMasatake YAMATO extern bool prefix##ArrayHas (const prefix##Array *const current, type num) \ 1284ecf7bb9SMasatake YAMATO { \ 1294ecf7bb9SMasatake YAMATO return prefix##ArrayHasTest (current, prefix##Eq, &num); \ 1304ecf7bb9SMasatake YAMATO } \ 1314ecf7bb9SMasatake YAMATO \ 1324ecf7bb9SMasatake YAMATO extern void prefix##ArrayReverse (const prefix##Array *const current) \ 1334ecf7bb9SMasatake YAMATO { \ 1344ecf7bb9SMasatake YAMATO unsigned int i, j; \ 1354ecf7bb9SMasatake YAMATO type tmp; \ 1364ecf7bb9SMasatake YAMATO \ 1374ecf7bb9SMasatake YAMATO Assert (current != NULL); \ 1384ecf7bb9SMasatake YAMATO for (i = 0, j = current->count - 1 ; i < (current->count / 2); ++i, --j) \ 1394ecf7bb9SMasatake YAMATO { \ 1404ecf7bb9SMasatake YAMATO tmp = current->array[i]; \ 1414ecf7bb9SMasatake YAMATO current->array[i] = current->array[j]; \ 1424ecf7bb9SMasatake YAMATO current->array[j] = tmp; \ 1434ecf7bb9SMasatake YAMATO } \ 1444ecf7bb9SMasatake YAMATO } \ 1454ecf7bb9SMasatake YAMATO \ 1464ecf7bb9SMasatake YAMATO extern void prefix##ArrayDeleteItem (prefix##Array* const current, unsigned int indx) \ 1474ecf7bb9SMasatake YAMATO { \ 1484ecf7bb9SMasatake YAMATO memmove (current->array + indx, current->array + indx + 1, \ 149*4a710c06SHideki IWAMOTO (current->count - indx - 1) * sizeof (*current->array)); \ 1504ecf7bb9SMasatake YAMATO --current->count; \ 1514ecf7bb9SMasatake YAMATO } \ 1524ecf7bb9SMasatake YAMATO static int prefix##GreaterThan(const void *a, const void *b) \ 1534ecf7bb9SMasatake YAMATO { \ 1544ecf7bb9SMasatake YAMATO type an = *(type *)a; \ 1554ecf7bb9SMasatake YAMATO type bn = *(type *)b; \ 1564ecf7bb9SMasatake YAMATO if (an > bn) \ 1574ecf7bb9SMasatake YAMATO return 1; \ 1584ecf7bb9SMasatake YAMATO else if (an == bn) \ 1594ecf7bb9SMasatake YAMATO return 0; \ 1604ecf7bb9SMasatake YAMATO else \ 1614ecf7bb9SMasatake YAMATO return -1; \ 1624ecf7bb9SMasatake YAMATO } \ 1634ecf7bb9SMasatake YAMATO static int prefix##LessThan(const void *a, const void *b) \ 1644ecf7bb9SMasatake YAMATO { \ 1654ecf7bb9SMasatake YAMATO return prefix##GreaterThan (b, a); \ 1664ecf7bb9SMasatake YAMATO } \ 1674ecf7bb9SMasatake YAMATO extern void prefix##ArraySort (prefix##Array *const current, bool descendingOrder) \ 1684ecf7bb9SMasatake YAMATO { \ 1694ecf7bb9SMasatake YAMATO if (descendingOrder) \ 1704ecf7bb9SMasatake YAMATO qsort (current->array, current->count, sizeof (type), prefix##GreaterThan); \ 1714ecf7bb9SMasatake YAMATO else \ 1724ecf7bb9SMasatake YAMATO qsort (current->array, current->count, sizeof (type), prefix##LessThan); \ 1734ecf7bb9SMasatake YAMATO } 1744ecf7bb9SMasatake YAMATO 1754ecf7bb9SMasatake YAMATO /* We expect the linker we use is enough clever to delete dead code. */ 176e4f99c14SColomban Wendling impNumArray(char, Char, char) 177e4f99c14SColomban Wendling impNumArray(uchar, Uchar, unsigned char) 178e4f99c14SColomban Wendling impNumArray(int, Int, int) 179e4f99c14SColomban Wendling impNumArray(uint, Uint, unsigned int) 180e4f99c14SColomban Wendling impNumArray(long, Long, long) 181e4f99c14SColomban Wendling impNumArray(ulong, Ulong, unsigned long) 182