2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-15 13:02:11 +00:00
Files
build/jam_src/newstr.c
Rene Rivera 135cc00ef8 Variety of performance improvements.
* bjam; bump to version 3.1.12
* bjam; make it possible to build in MinGW/MSYS shell
* bjam; move profile code to debug.h/c to make it available for use everywhere
* bjam; cache all filesystem query operations, Unix and Windows only, include PWD and scanning
* bjam; add memory profile info, and sprinkle throught code
* bbv2; rewrite some while() loops into for() loops to reduce time and memory
* bbv2; keep a single instance counter instead of one per type to reduce memory use
* bjam+bbv2; change NORMALIZE_PATH builtin to join path parts to reduce memory use


[SVN r31177]
2005-10-03 00:47:36 +00:00

180 lines
3.8 KiB
C

/*
* Copyright 1993, 1995 Christopher Seiwald.
*
* This file is part of Jam - see jam.c for Copyright information.
*/
# include "jam.h"
# include "newstr.h"
# include "hash.h"
# include "compile.h"
# include <stddef.h>
# include <stdlib.h>
/*
* newstr.c - string manipulation routines
*
* To minimize string copying, string creation, copying, and freeing
* is done through newstr.
*
* External functions:
*
* newstr() - return a dynamically allocated copy of a string
* copystr() - return a copy of a string previously returned by newstr()
* freestr() - free a string returned by newstr() or copystr()
* donestr() - free string tables
*
* Once a string is passed to newstr(), the returned string is readonly.
*
* This implementation builds a hash table of all strings, so that multiple
* calls of newstr() on the same string allocate memory for the string once.
* Strings are never actually freed.
*/
typedef char *STRING;
static struct hash *strhash = 0;
static int strtotal = 0;
static int strcount_in = 0;
static int strcount_out = 0;
/*
* Immortal string allocator implementation speeds string allocation
* and cuts down on internal fragmentation
*/
# define STRING_BLOCK 4096
typedef struct strblock
{
struct strblock* next;
char data[STRING_BLOCK];
} strblock;
static strblock* strblock_chain = 0;
/* Storage remaining in the current strblock */
static char* storage_start = 0;
static char* storage_finish = 0;
/* */
#define SIMPLE_ALLOC 0
/*/
#define SIMPLE_ALLOC 1
/* */
/*
* allocate() - Allocate n bytes of immortal string storage
*/
static char* allocate(size_t n)
{
#if SIMPLE_ALLOC
return (char*)malloc(n);
#else
/* See if we can grab storage from an existing block */
size_t remaining = storage_finish - storage_start;
if ( remaining >= n )
{
char* result = storage_start;
storage_start += n;
return result;
}
else /* Must allocate a new block */
{
strblock* new_block;
size_t nalloc = n;
if ( nalloc < STRING_BLOCK )
nalloc = STRING_BLOCK;
/* allocate a new block and link into the chain */
new_block = (strblock*)malloc( offsetof( strblock, data[0] ) + nalloc * sizeof(new_block->data[0]) );
if ( new_block == 0 )
return 0;
new_block->next = strblock_chain;
strblock_chain = new_block;
/* Take future allocations out of the larger remaining space */
if ( remaining < nalloc - n )
{
storage_start = new_block->data + n;
storage_finish = new_block->data + nalloc;
}
return new_block->data;
}
#endif
}
/*
* newstr() - return a dynamically allocated copy of a string
*/
char *
newstr( char *string )
{
STRING str, *s = &str;
if( !strhash )
strhash = hashinit( sizeof( STRING ), "strings" );
*s = string;
if( hashenter( strhash, (HASHDATA **)&s ) )
{
int l = strlen( string );
char *m = (char *)allocate( l + 1 );
strtotal += l + 1;
memcpy( m, string, l + 1 );
*s = m;
if ( DEBUG_PROFILE )
profile_memory( l+1 );
}
strcount_in += 1;
return *s;
}
/*
* copystr() - return a copy of a string previously returned by newstr()
*/
char *
copystr( char *s )
{
strcount_in += 1;
return s;
}
/*
* freestr() - free a string returned by newstr() or copystr()
*/
void
freestr( char *s )
{
strcount_out += 1;
}
/*
* donestr() - free string tables
*/
void
donestr()
{
/* Reclaim string blocks */
while ( strblock_chain != 0 )
{
strblock* n = strblock_chain->next;
free(strblock_chain);
strblock_chain = n;
}
hashdone( strhash );
if( DEBUG_MEM )
printf( "%dK in strings\n", strtotal / 1024 );
/* printf( "--- %d strings of %d dangling\n", strcount_in-strcount_out, strcount_in ); */
}