1 /************************************************************************
2 ************************************************************************
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
26 #include "compatibility.hh"
34 * Hash table used to store the symbols
37 Symbol
* Symbol::gSymbolTable
[kHashTableSize
];
41 * Search the hash table for the symbol of name \p str or returns a new one.
42 * \param str the name of the symbol
43 * \return a symbol of name str
46 Symbol
* Symbol::get(const string
& str
)
53 for (i
= 0; i
< n
; i
++) { buf
[i
] = str
[i
]; }
56 return Symbol::get(buf
);
62 * Search the hash table for the symbol of name \p str or returns a new one.
63 * \param str the name of the symbol
64 * \return a symbol of name str
67 Symbol
* Symbol::get(const char* str
)
69 unsigned int hsh
= calcHashKey(str
);
70 int bckt
= hsh
% kHashTableSize
;
71 Symbol
* item
= gSymbolTable
[bckt
];
73 while ( item
&& !item
->equiv(hsh
,str
) ) item
= item
->fNext
;
74 Symbol
* r
= item
? item
: gSymbolTable
[bckt
] = new Symbol(str
, hsh
, gSymbolTable
[bckt
]);
80 * Static method that searches the symbol table for a string.
81 * \param str string to search
82 * \return true if the string is NOT in the table (it is a new string)
85 bool Symbol::isnew(const char* str
)
87 unsigned int hsh
= calcHashKey(str
);
88 int bckt
= hsh
% kHashTableSize
;
89 Symbol
* item
= gSymbolTable
[bckt
];
91 while ( item
&& !item
->equiv(hsh
,str
) ) item
= item
->fNext
;
97 * Creates a new symbol with a name obtained by concatenating the \p str prefix with a number in order to make it unique
98 * \param str the prefix of the name
99 * \return a symbol of name \p prefix++n
102 Symbol
* Symbol::prefix (const char* str
)
106 static map
<const char*, unsigned int> gPrefixCounters
;
108 for (int n
= 0; n
<10000; n
++) {
109 snprintf(name
, 256, "%s%d", str
, gPrefixCounters
[str
]++);
110 if (isnew(name
)) return get(name
);
113 return get("UNIQUEOVERFLOW");
118 * Check if the name of the symbol is equal to string \p str
119 * This method is used by isnew() and make() when searching the hashtable
120 * for an existing symbol.
122 * \param hash the hash key of the string (used to speedup the comparison)
123 * \param str the string to compare
124 * \return \p true if the name of the symbol and \p str are the same
127 bool Symbol::equiv (unsigned int hash
, const char *str
) const
129 return (fHash
== hash
) && (strcmp(fName
,str
) == 0);
135 * Compute the 32-bits hash key of string \p str
136 * \param str the string
137 * \return a 32-bits hash key
140 unsigned int Symbol::calcHashKey (const char* str
)
144 while (*str
) h
= (h
<< 1) ^ (h
>> 20) ^ (*str
++);
151 * Constructs a symbol ready to be placed in the hash table.
152 * It makes a private copy of its name.
153 * \param str the name of the symbol
154 * \param hsh the hash key of the symbol
155 * \param nxt a pointer to the next symbol in the hash table entry
158 Symbol::Symbol(const char* str
, unsigned int hsh
, Symbol
* nxt
)
160 int len
= strlen(str
);
162 fName
= new char [len
+1];
163 memcpy(fName
, str
, len
+1);
174 ostream
& Symbol::print (ostream
& fout
) const ///< print a symbol on a stream
176 return fout
<< fName
;