FAUST compiler  0.9.9.6b8
symbol.cpp
Go to the documentation of this file.
00001 /************************************************************************
00002  ************************************************************************
00003     FAUST compiler
00004     Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
00005     ---------------------------------------------------------------------
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  ************************************************************************
00020  ************************************************************************/
00021 
00022 #include    <stdlib.h>
00023 #include    <stdio.h>
00024 #include    <string.h>
00025 #include    "symbol.hh"
00026 #include    "compatibility.hh"
00027 #include    <iostream>
00028 #include    <cstring>
00029 #include    <assert.h>
00030 
00031 using namespace std;
00032 
00037 Symbol* Symbol::gSymbolTable[kHashTableSize];
00038 
00039 
00046 Symbol* Symbol::get(const string& str)
00047 {
00048     char    buf[1024];
00049     int     i;
00050     int     n = str.length();
00051     
00052     if (n>1023) n = 1023;
00053     for (i = 0; i < n; i++) { buf[i] = str[i]; }
00054     buf[i] = 0;
00055     
00056     return Symbol::get(buf);
00057 }
00058 
00059 
00060 
00067 Symbol* Symbol::get(const char* str)
00068 {
00069     unsigned int            hsh  = calcHashKey(str);
00070     int             bckt = hsh % kHashTableSize;
00071     Symbol*         item = gSymbolTable[bckt];
00072 
00073     while ( item && !item->equiv(hsh,str) ) item = item->fNext;
00074     Symbol* r = item ? item : gSymbolTable[bckt] = new Symbol(str, hsh, gSymbolTable[bckt]);
00075     return r;
00076 }
00077 
00078 
00085 bool Symbol::isnew(const char* str)
00086 {
00087     unsigned int            hsh  = calcHashKey(str);
00088     int             bckt = hsh % kHashTableSize;
00089     Symbol*         item = gSymbolTable[bckt];
00090     
00091     while ( item && !item->equiv(hsh,str) ) item = item->fNext;
00092     return item == 0;
00093 }
00094 
00095 
00102 Symbol* Symbol::prefix (const char* str)
00103 {
00104     char    name[256];
00105     
00106     static map<const char*, unsigned int> gPrefixCounters;
00107     
00108     for (int n = 0; n<10000; n++) {
00109         snprintf(name, 256, "%s%d", str, gPrefixCounters[str]++);
00110         if (isnew(name)) return get(name);
00111     }
00112     assert(false);
00113     return get("UNIQUEOVERFLOW");
00114 }   
00115 
00116 
00127 bool Symbol::equiv (unsigned int hash, const char *str) const
00128 {
00129     return (fHash == hash) && (strcmp(fName,str) == 0);
00130 }
00131 
00132 
00133 
00140 unsigned int Symbol::calcHashKey (const char* str)
00141 {
00142     unsigned int h = 0;
00143 
00144     while (*str) h = (h << 1) ^ (h >> 20) ^ (*str++);
00145     return h;
00146 }
00147 
00148 
00149 
00158 Symbol::Symbol(const char* str, unsigned int hsh, Symbol* nxt)
00159 {
00160     int len = strlen(str);
00161     
00162     fName = new char [len+1];
00163     memcpy(fName, str, len+1);
00164     fHash = hsh;
00165     fNext = nxt;
00166     fData = 0;
00167 }
00168 
00169 Symbol::~Symbol ()
00170 {
00171     delete [] fName;
00172 }
00173 
00174 ostream& Symbol::print (ostream& fout) const                    
00175 {
00176     return fout << fName;
00177 }