Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/tools/jam/src/newstr.c @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 3.8 KB
Line 
1/*
2 * Copyright 1993, 1995 Christopher Seiwald.
3 *
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6
7# include "jam.h"
8# include "newstr.h"
9# include "hash.h"
10# include "compile.h"
11# include <stddef.h>
12# include <stdlib.h>
13
14/*
15 * newstr.c - string manipulation routines
16 *
17 * To minimize string copying, string creation, copying, and freeing
18 * is done through newstr.
19 *
20 * External functions:
21 *
22 *    newstr() - return a dynamically allocated copy of a string
23 *    copystr() - return a copy of a string previously returned by newstr()
24 *    freestr() - free a string returned by newstr() or copystr()
25 *    donestr() - free string tables
26 *
27 * Once a string is passed to newstr(), the returned string is readonly.
28 *
29 * This implementation builds a hash table of all strings, so that multiple
30 * calls of newstr() on the same string allocate memory for the string once.
31 * Strings are never actually freed.
32 */
33
34typedef char *STRING;
35
36static struct hash *strhash = 0;
37static int strtotal = 0;
38static int strcount_in = 0;
39static int strcount_out = 0;
40
41/*
42 * Immortal string allocator implementation speeds string allocation
43 * and cuts down on internal fragmentation
44 */
45
46# define STRING_BLOCK 4096
47typedef struct strblock
48{
49    struct strblock* next;
50    char data[STRING_BLOCK];
51} strblock;
52
53static strblock* strblock_chain = 0;
54
55/* Storage remaining in the current strblock */
56static char* storage_start = 0;
57static char* storage_finish = 0;
58
59/* */
60#define SIMPLE_ALLOC 0
61/*/
62#define SIMPLE_ALLOC 1
63/* */
64
65/*
66 * allocate() - Allocate n bytes of immortal string storage
67 */
68static char* allocate(size_t n)
69{
70    #if SIMPLE_ALLOC
71    return (char*)malloc(n);
72    #else
73    /* See if we can grab storage from an existing block */
74    size_t remaining = storage_finish - storage_start;
75    if ( remaining >= n )
76    {
77        char* result = storage_start;
78        storage_start += n;
79        return result;
80    }
81    else /* Must allocate a new block */
82    {
83        strblock* new_block;
84        size_t nalloc = n;
85        if ( nalloc < STRING_BLOCK )
86            nalloc = STRING_BLOCK;
87
88        /* allocate a new block and link into the chain */
89        new_block = (strblock*)malloc( offsetof( strblock, data[0] ) + nalloc * sizeof(new_block->data[0]) );
90        if ( new_block == 0 )
91            return 0;
92        new_block->next = strblock_chain;
93        strblock_chain = new_block;
94
95        /* Take future allocations out of the larger remaining space */
96        if ( remaining < nalloc - n )
97        {
98            storage_start = new_block->data + n;
99            storage_finish = new_block->data + nalloc;
100        }
101        return new_block->data;
102    }
103    #endif
104}
105
106/*
107 * newstr() - return a dynamically allocated copy of a string
108 */
109
110char *
111newstr( char *string )
112{
113        STRING str, *s = &str;
114
115        if( !strhash )
116            strhash = hashinit( sizeof( STRING ), "strings" );
117
118        *s = string;
119
120        if( hashenter( strhash, (HASHDATA **)&s ) )
121        {
122            int l = strlen( string );
123            char *m = (char *)allocate( l + 1 );
124
125            strtotal += l + 1;
126            memcpy( m, string, l + 1 );
127            *s = m;
128
129        if ( DEBUG_PROFILE )
130            profile_memory( l+1 );
131        }
132
133    strcount_in += 1;
134        return *s;
135}
136
137/*
138 * copystr() - return a copy of a string previously returned by newstr()
139 */
140
141char *
142copystr( char *s )
143{
144    strcount_in += 1;
145        return s;
146}
147
148/*
149 * freestr() - free a string returned by newstr() or copystr()
150 */
151
152void
153freestr( char *s )
154{
155    strcount_out += 1;
156}
157
158/*
159 * donestr() - free string tables
160 */
161
162void
163donestr()
164{
165    /* Reclaim string blocks */
166    while ( strblock_chain != 0 )
167    {
168        strblock* n = strblock_chain->next;
169        free(strblock_chain);
170        strblock_chain = n;
171    }
172   
173    hashdone( strhash );
174   
175    if( DEBUG_MEM )
176        printf( "%dK in strings\n", strtotal / 1024 );
177   
178    /* printf( "--- %d strings of %d dangling\n", strcount_in-strcount_out, strcount_in ); */
179}
Note: See TracBrowser for help on using the repository browser.