The Machine Perception Toolbox

[Introduction]- [News]- [Download]- [Screenshots]- [Manual (pdf)]- [Forums]- [API Reference]- [Repository ]

 

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

newstr.c

Go to the documentation of this file.
00001 /*
00002  * Copyright 1993, 1995 Christopher Seiwald.
00003  *
00004  * This file is part of Jam - see jam.c for Copyright information.
00005  */
00006 
00007 # include "jam.h"
00008 # include "newstr.h"
00009 # include "hash.h"
00010 # include <stddef.h>
00011 # include <stdlib.h>
00012 
00013 /*
00014  * newstr.c - string manipulation routines
00015  *
00016  * To minimize string copying, string creation, copying, and freeing
00017  * is done through newstr.
00018  *
00019  * External functions:
00020  *
00021  *    newstr() - return a dynamically allocated copy of a string
00022  *    copystr() - return a copy of a string previously returned by newstr()
00023  *    freestr() - free a string returned by newstr() or copystr()
00024  *    donestr() - free string tables
00025  *
00026  * Once a string is passed to newstr(), the returned string is readonly.
00027  *
00028  * This implementation builds a hash table of all strings, so that multiple 
00029  * calls of newstr() on the same string allocate memory for the string once.
00030  * Strings are never actually freed.
00031  */
00032 
00033 typedef char *STRING;
00034 
00035 static struct hash *strhash = 0;
00036 static int strtotal = 0;
00037 
00038 /*
00039  * Immortal string allocator implementation speeds string allocation
00040  * and cuts down on internal fragmentation
00041  */
00042 
00043 # define STRING_BLOCK 4096
00044 typedef struct strblock
00045 {
00046     struct strblock* next;
00047     char data[STRING_BLOCK];
00048 } strblock;
00049 
00050 static strblock* strblock_chain = 0;
00051 
00052 /* Storage remaining in the current strblock */
00053 static char* storage_start = 0;
00054 static char* storage_finish = 0;
00055 
00056 /*
00057  * allocate() - Allocate n bytes of immortal string storage
00058  */
00059 static char* allocate(size_t n)
00060 {
00061     /* See if we can grab storage from an existing block */
00062     size_t remaining = storage_finish - storage_start;
00063     if ( remaining >= n )
00064     {
00065         char* result = storage_start;
00066         storage_start += n;
00067         return result;
00068     }
00069     else /* Must allocate a new block */
00070     {
00071         strblock* new_block;
00072         size_t nalloc = n;
00073         if ( nalloc < STRING_BLOCK )
00074             nalloc = STRING_BLOCK;
00075 
00076         /* allocate a new block and link into the chain */
00077         new_block = (strblock*)malloc( offsetof( strblock, data[0] ) + nalloc * sizeof(new_block->data[0]) );
00078         if ( new_block == 0 )
00079             return 0;
00080         new_block->next = strblock_chain;
00081         strblock_chain = new_block;
00082 
00083         /* Take future allocations out of the larger remaining space */
00084         if ( remaining < nalloc - n )
00085         {
00086             storage_start = new_block->data + n;
00087             storage_finish = new_block->data + nalloc;
00088         }
00089         return new_block->data;
00090     }
00091 }
00092 
00093 /*
00094  * newstr() - return a dynamically allocated copy of a string
00095  */
00096 
00097 char *
00098 newstr( char *string )
00099 {
00100         STRING str, *s = &str;
00101 
00102         if( !strhash )
00103             strhash = hashinit( sizeof( STRING ), "strings" );
00104 
00105         *s = string;
00106 
00107         if( hashenter( strhash, (HASHDATA **)&s ) )
00108         {
00109             int l = strlen( string );
00110             char *m = (char *)allocate( l + 1 );
00111 
00112             strtotal += l + 1;
00113             memcpy( m, string, l + 1 );
00114             *s = m;
00115         }
00116 
00117         return *s;
00118 }
00119 
00120 /*
00121  * copystr() - return a copy of a string previously returned by newstr()
00122  */
00123 
00124 char *
00125 copystr( char *s )
00126 {
00127         return s;
00128 }
00129 
00130 /*
00131  * freestr() - free a string returned by newstr() or copystr()
00132  */
00133 
00134 void
00135 freestr( char *s )
00136 {
00137 }
00138 
00139 /*
00140  * donestr() - free string tables
00141  */
00142 
00143 void
00144 donestr()
00145 {
00146     /* Reclaim string blocks */
00147     while ( strblock_chain != 0 )
00148     {
00149         strblock* n = strblock_chain->next;
00150         free(strblock_chain);
00151         strblock_chain = n;
00152     }
00153     
00154     hashdone( strhash );
00155     
00156     if( DEBUG_MEM )
00157         printf( "%dK in strings\n", strtotal / 1024 );
00158 }

Generated on Mon Nov 8 17:07:46 2004 for MPT by  doxygen 1.3.9.1