Category : UNIX Files
Archive   : UUPC11YS.ZIP
Filename : STRPOOL.C

 
Output of file : STRPOOL.C contained in archive : UUPC11YS.ZIP
/*--------------------------------------------------------------------*/
/* s t r p o o l . c */
/* */
/* String dynamic literal pool management for UUPC/extended */
/* */
/* Copyright (c) 1992 by Kendra Electronic Wonderworks; all */
/* rights reserved except those explicitly granted by the */
/* UUPC/extended license. */
/*--------------------------------------------------------------------*/

/*
* $Id: STRPOOL.C 1.3 1992/12/04 01:00:27 ahd Exp $
*
* $Log: STRPOOL.C $
* Revision 1.3 1992/12/04 01:00:27 ahd
* Delete allocating pool message; now handled by pools allocated summary
*
* Revision 1.2 1992/12/01 04:37:03 ahd
* Add SpeedOverMemory
*
* Revision 1.1 1992/11/22 20:58:55 ahd
* Initial revision
*
*/

/*--------------------------------------------------------------------*/
/* System include files */
/*--------------------------------------------------------------------*/

#include
#include
#include
#include

/*--------------------------------------------------------------------*/
/* UUPC/extended include files */
/*--------------------------------------------------------------------*/

#include "lib.h"

/*--------------------------------------------------------------------*/
/* Local structures */
/*--------------------------------------------------------------------*/

typedef struct str_queue {
struct str_queue *next_link;
size_t used;
char pool[BUFSIZ];
} STR_QUEUE;

/*--------------------------------------------------------------------*/
/* Local variables */
/*--------------------------------------------------------------------*/

static STR_QUEUE *anchor = NULL;
static const size_t pool_size = BUFSIZ;
static int pools = 0;

#define _UDEBUG
#ifdef _UDEBUG

static int strings = 0;
static int used = 0;
static int duplicates = 0;
static int saved = 0;

/*--------------------------------------------------------------------*/
/* Local prototypes */
/*--------------------------------------------------------------------*/

void dump_pool( void );

#endif

/*--------------------------------------------------------------------*/
/* The problem: UUPC/extended allocates large number of small */
/* (<< 50 characters) string variables off the heap which are */
/* never modified and never deallocated. This means that the */
/* possibly duplicate and relatively large overhead required by */
/* malloc and causes these variables to waste space. */
/* */
/* The solution: We use this routine to maintain our own local */
/* pool of storage for allocating NULL terminated strings out */
/* of a chain of large buffers. This allows us to both reduce */
/* storage overhead by placing the strings end to end, and to */
/* optionally scan the list for duplicates entries. */
/* */
/* The duplicate string search can be questionable on a small */
/* system, because we have to walk the entire list to locate */
/* the duplicate. However, a smaller system is less likely to */
/* have a large dynamic string pool, so we take the hit anyway. */
/*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*/
/* s t r p o o l */
/* */
/* Allocate a string from the string poll */
/*--------------------------------------------------------------------*/

char *strpool( const char *input , const char *file, size_t line)
{
int len = strlen( input );
int best_fit = SHRT_MAX;
char *result;

STR_QUEUE *current = anchor;
STR_QUEUE *last = anchor;
STR_QUEUE *save = NULL;

/*--------------------------------------------------------------------*/
/* Perform best fit search */
/*--------------------------------------------------------------------*/

while(current != NULL )
{
int available;

/*--------------------------------------------------------------------*/
/* Scan current buffer for the string */
/*--------------------------------------------------------------------*/

if ( ! bflag[ F_SPEEDOVERMEMORY ] )
{
char *target = current->pool;
char *bufend = target + current->used;

while( target < bufend )
{
int target_len = strlen( target );
int diff = target_len - len;

if ((diff >= 0 ) && equal( target + diff, input))
{

#ifdef _UDEBUG
duplicates ++;
saved += len + 1;
#endif
return target+diff;
}

target += target_len + 1; /* Step to start of next string */

} /* while( offset < current->used ) */
} /* if */

/*--------------------------------------------------------------------*/
/* No string in this buffer, look for best fit in case we need */
/* to allocate the string from scratch */
/*--------------------------------------------------------------------*/

available = pool_size - current->used;

if (( available < best_fit) && (available > len ))
{
best_fit = available;
save = current;
}
else
last = current; /* Save last buffer in case we
have to chain new buffer in */
current = current->next_link;
} /* while */

/*--------------------------------------------------------------------*/
/* We have no matching string, we have to insert the new string */
/* into our pool */
/*--------------------------------------------------------------------*/

if ( save == NULL ) /* We find a buffer? */
{ /* No --> Allocate a new one */
pools ++;

save = malloc( sizeof *save );
checkptr(save, file, line);

if ( anchor == NULL )
{

#ifdef _UDEBUG
atexit( dump_pool );
#endif

anchor = save;
}
else
last->next_link = save;

save->used = 0;
save->next_link = NULL;
}

/*--------------------------------------------------------------------*/
/* Save the string, update memory available in current pool, */
/* and return to the caller with the new string */
/*--------------------------------------------------------------------*/

result = strcpy( save->pool + save->used, input );
save->used += len + 1;

#ifdef _UDEBUG
strings ++;
used += len + 1;
#endif

return result;

} /* strpool */

/*--------------------------------------------------------------------*/
/* s a f e f r e e */
/* */
/* Insure we are not freeing memory saved for a pool */
/*--------------------------------------------------------------------*/

void safefree( void *input , const char *file, size_t line)
{
STR_QUEUE *current = anchor;
int buffers = 0;
while( current != NULL )
{
buffers ++;
if (( input > (void *) current ) &&
(input < (void *) (current->pool + pool_size ) ))
{
printmsg(0,"Attempt to free string \"%s\" allocated via newstr() in pool %d",
input , buffers );

bugout( line, file);
}

current = current->next_link;
}

#undef free

free(input);

} /* safefree */

#ifdef _UDEBUG

/*--------------------------------------------------------------------*/
/* d u m p _ p o o l */
/* */
/* Print the free storage pool */
/*--------------------------------------------------------------------*/

void dump_pool( void )
{

STR_QUEUE *current = anchor;
int buffers = 0;

printmsg(3,"Allocated %d bytes in %d strings "
"requiring %d pools of %d bytes each",
used, strings, pools, pool_size );

if ( duplicates )
printmsg(3,"Saved %d bytes in %d redundant strings",
saved, duplicates);

if ( debuglevel > 5 )
while(current != NULL )
{
size_t offset = 0;
size_t strings = 0;
buffers ++;

printmsg(5,"Buffer %d length is %d bytes",buffers, current->used);

while( offset < current->used )
{
size_t target_len = strlen( current->pool + offset );
strings ++;
printmsg(5,"[%d,%02d,%02d]=\"%s\"",
buffers,
strings,
target_len,
current->pool + offset);
offset += target_len +1; /* Go to end of string */

} /* while( offset < current->used ) */

current = current->next_link;

} /* while */

} /* dump_pool */

#endif


  3 Responses to “Category : UNIX Files
Archive   : UUPC11YS.ZIP
Filename : STRPOOL.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/