home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
me34src.zip
/
me3
/
util
/
dtable.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-14
|
7KB
|
246 lines
/* dtable.c : dynamic tables
* xpand_dTable: Make sure a dTable can hold n more items.
* Input:
* dtable: A pointer to a dTable.
* n: Number of items that will be added to the table after
* this call.
* initial_size: Number of cells to initialize table to.
* step: Grow table by multiples of step cells.
* Returns:
* TRUE: Table has room for n items.
* FALSE: Not enough memory for n new items. The table may have been
* cleared, check the size.
* How to use:
* #include "dtable.h"
* typedef struct { ... } Blob;
* * IF dTable is global (or static):
* declare_and_init_dTable(foobar,Blob);
* * IF dTable is a typdef'ed global:
* typedef declare_dTable_of(Blob) FooBar;
* FooBar foobar = initial_dTable_data(foobar);
* * IF dTable is automatic (local):
* declare_dTable_of(Blob) foobar;
* INIT_dTable(&foobar); or initialize_dTable(&foobar,sizeof(Blob));
* xpand_dTable(&foobar, n, initial_size, step);
* foobar.table[j] = a_Blob; -- do this n times
* Notes:
* Make sure the dTable is initialized! See "How to use" above.
* If you want to reuse the table: reset_dTable(dtable);
* sizeof_dTable(dtable) is the number of items in the table (not the
* max).
* To release the dtable: free_dTable(dtable). If you are going to
* reuse the table header, do an INIT_dTable(dtable) after the
* free.
* extern declare_dTable_of(Blob) foobar; is legal.
* typedef declare_dTable_of(Blob) foobar; is legal.
* If initial_size is not big enough to hold the first n items, the
* table is created n+step big.
* WARNINGS:
* Table may be moved during xpand_dTable(). So don't expect
* ptr = foo->table; xpand_dTable(foo,...) to work. Always set ptr
* after the xpand.
* For 2 byte int machines (eg MS-DOS), there are some overflow checks.
* The following MUST be true for them to work:
* - sizeof(int) < sizeof(long int)
* - In xpand_dtable(dtable, n, initial_size, step), the args n,
* initial_size and step are int and therefore must be <= INT_MAX
* (32k - 1). DON'T change them to unsigned int or pass in
* anything bigger - it can break the checking.
* - malloc and realloc must take size_t (unsigned int) ie be able
* to allocate up to 64k bytes.
*
* Craig Durland 6/89, 1/93
*/
/* Copyright 1989, 1990 Craig Durland
* Distributed under the terms of the GNU General Public License.
* Distributed "as is", without warranties of any kind, but comments,
* suggestions and bug reports are welcome.
*/
#include <limits.h> /* for INT_MAX */
#include "const.h"
#include "dtable.h"
extern char *malloc(), *realloc();
void initialize_dTable(dtable,blob_size) dTable *dtable;
{
dtable->max_items = dtable->num_items = 0;
dtable->blob_size = blob_size;
dtable->table = NULL; /* for debugging purposes */
}
void free_dTable(dtable) dTable *dtable;
{ if (dtable->max_items) free((char *)dtable->table); }
/* Pad dtable so there is enough room for n more items without having to
* malloc(). This is useful when you know you are going to add a
* bunchg of stuff but not all at once.
*/
pad_dTable(dtable, n) dTable *dtable;
{
unsigned int z;
z = dtable->num_items;
if (!xpand_dTable(dtable, n, 0, 1)) return FALSE;
dtable->num_items = z;
return TRUE;
}
#define SMALL_INT (INT_MAX == 0x7FFF) /* (sizeof(int) == 2) */
#if SMALL_INT /* Check to see if trying to overflow a size_t */
static int overflowed(), too_big();
#define CHECK_REQUEST_SIZE if (too_big(dtable, n)) return FALSE;
#define CHECK_FOR_OVERFLOW if (overflowed(dtable, &blobs, n)) return FALSE;
#else /* Don't need no steenking overflow checking */
#define CHECK_FOR_OVERFLOW
#define CHECK_REQUEST_SIZE
#endif /* SMALL_INT */
xpand_dTable(dtable, n, initial_size, step) dTable *dtable;
{
char *ptr;
int blob_size;
unsigned int max_items, num_items;
long int blobs;
CHECK_REQUEST_SIZE
max_items = dtable->max_items;
num_items = (dtable->num_items += n);
/* check to see if already have enough room for n more items */
if (num_items <= max_items) return TRUE;
blob_size = dtable->blob_size;
if (max_items == 0) /* table not allocated yet */
{
if ((blobs = initial_size) < num_items) /* initial size ain't big enough */
blobs = num_items + step;
CHECK_FOR_OVERFLOW
ptr = malloc((unsigned int)blobs * blob_size);
}
else /* table full, make bigger */
{
blobs = (num_items - max_items + step - 1)/step;
blobs = blobs*step + max_items;
CHECK_FOR_OVERFLOW
ptr = realloc(dtable->table, (unsigned int)blobs * blob_size);
#ifdef __STDC__
if (!ptr) /* in ANSI C, realloc may fail but table is still OK */
{
dtable->num_items -= n;
return FALSE;
}
#endif /* __STDC__ */
}
dtable->max_items = blobs;
if ((dtable->table = ptr) == NULL) /* out of memory => table is mush */
{ initialize_dTable(dtable,blob_size); return FALSE; }
return TRUE;
}
#if SMALL_INT /* Check to see if trying to overflow a size_t */
static int too_big(dtable, n) dTable *dtable; int n;
{
unsigned int num_items = dtable->num_items;
return (n < 0 || num_items + n < num_items);
/*
if ((long int)UINT_MAX <= ((long int)n + num_items))
return TRUE;
*/
}
static int overflowed(dtable, blobs, n)
dTable *dtable; long int *blobs; int n;
{
long int z = *blobs;
int blob_size = dtable->blob_size;
if ((long int)UINT_MAX <= (z * blob_size)) /* Can't have what they want */
{ /* but maybe they can have what they need */
z = (long int)UINT_MAX / blob_size;
if (z < dtable->num_items) /* Won't fit no way, no how */
{
dtable->num_items -= n;
return TRUE;
}
*blobs = z;
}
return FALSE;
}
#endif /* SMALL_INT */
#ifdef TEST
/* ******************************************************************** */
/* ******************************* TEST ******************************* */
/* ******************************************************************** */
typedef struct { char *name; int token; } Blob;
declare_and_init_dTable(foo,Blob);
declare_and_init_dTable(bar,char);
main(argc, argv) char **argv;
{
char zik[100], *name, *savestr();
int n, s, j, step;
if (argc != 1)
{
if (argc == 2)
{
printf("dtable <step> n [n ...]\n");
exit(1);
}
step = atoi(argv[1]);
for (j = 2; j < argc; j++)
{
s = xpand_dTable(&bar, atoi(argv[j]), 0, step);
printf("%d | num_items = %u, max_items = %u\n",
s, sizeof_dTable(&bar), bar.max_items);
}
exit(0);
}
for (j = 0; 1; j++)
{
printf("name: "); gets(zik);
if (*zik=='q') break;
name = savestr(zik);
printf("token: "); gets(zik); n = atoi(zik);
s = xpand_dTable(&foo, 1, 3, 2);
foo.table[j].name = name;
foo.table[j].token = n;
printf("%d | num_items = %d, max_items = %d: %d %s\n",
s,
sizeof_dTable(&foo),
foo.max_items,
foo.table[j].token,foo.table[j].name);
}
for (n=0; n<sizeof_dTable(&foo); n++)
printf("%d: %d %s\n",n, foo.table[n].token,foo.table[n].name);
}
#endif