2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #if !defined( INCLUDED_UNIQUENAMES_H )
23 #define INCLUDED_UNIQUENAMES_H
26 #include "debugging/debugging.h"
28 #include "string/string.h"
29 #include "generic/static.h"
36 Postfix( const char* postfix ) : m_value( atoi( postfix ) ){
38 unsigned int number() const {
41 void write( char* buffer ) const {
42 sprintf( buffer, "%u", m_value );
44 Postfix& operator++(){
48 bool operator<( const Postfix& other ) const {
49 return m_value < other.m_value;
51 bool operator==( const Postfix& other ) const {
52 return m_value == other.m_value;
54 bool operator!=( const Postfix& other ) const {
55 return !operator==( other );
62 std::pair<unsigned int, unsigned int> m_value;
64 Postfix( unsigned int number, unsigned int leading_zeros )
65 : m_value( leading_zeros, number ){
67 Postfix( const char* postfix )
68 : m_value( number_count_leading_zeros( postfix ), atoi( postfix ) ){
70 unsigned int number() const {
71 return m_value.second;
73 unsigned int leading_zeros() const {
76 void write( char* buffer ){
77 for ( unsigned int count = 0; count < m_value.first; ++count, ++buffer )
79 sprintf( buffer, "%u", m_value.second );
81 Postfix& operator++(){
83 if ( m_value.first != 0 && m_value.second % 10 == 0 ) {
88 bool operator<( const Postfix& other ) const {
89 return m_value < other.m_value;
91 bool operator==( const Postfix& other ) const {
92 return m_value == other.m_value;
94 bool operator!=( const Postfix& other ) const {
95 return !operator==( other );
101 typedef std::pair<std::string, Postfix> name_t;
103 inline void name_write( char* buffer, name_t name ){
104 strcpy( buffer, name.first.c_str() );
105 name.second.write( buffer + strlen( name.first.c_str() ) );
108 inline name_t name_read( const char* name ){
109 const char* end = name + strlen( name );
110 for ( const char* p = end; end != name; --p )
112 if ( strrchr( "1234567890", *p ) == NULL ) {
118 return name_t( std::string( StringRange( name, end ) ), Postfix( end ) );
125 typedef std::map<Postfix, unsigned int> postfixes_t;
126 postfixes_t m_postfixes;
129 Postfix find_first_empty() const {
130 Postfix postfix( "1" );
131 for ( postfixes_t::const_iterator i = m_postfixes.find( postfix ); i != m_postfixes.end(); ++i, ++postfix )
133 if ( ( *i ).first != postfix ) {
141 Postfix make_unique( Postfix postfix ) const {
142 postfixes_t::const_iterator i = m_postfixes.find( postfix );
143 if ( i == m_postfixes.end() ) {
148 return find_first_empty();
152 void insert( Postfix postfix ){
153 postfixes_t::iterator i = m_postfixes.find( postfix );
154 if ( i == m_postfixes.end() ) {
155 m_postfixes.insert( postfixes_t::value_type( postfix, 1 ) );
163 void erase( Postfix postfix ){
164 postfixes_t::iterator i = m_postfixes.find( postfix );
165 if ( i == m_postfixes.end() ) {
170 if ( --( *i ).second == 0 ) {
171 m_postfixes.erase( i );
177 return m_postfixes.empty();
184 typedef std::map<std::string, PostFixes> names_t;
187 name_t make_unique( const name_t& name ) const {
190 name_write( buf, name );
191 globalErrorStream() << "find unique name for " << buf << "\n";
192 globalErrorStream() << "> currently registered names:\n";
193 for ( names_t::const_iterator i = m_names.begin(); i != m_names.end(); ++i )
195 globalErrorStream() << ">> " << i->first.c_str() << ": ";
196 for ( PostFixes::postfixes_t::const_iterator j = i->second.m_postfixes.begin(); j != i->second.m_postfixes.end(); ++j )
198 j->first.write( buf );
199 globalErrorStream() << " '" << buf << "'";
201 globalErrorStream() << "\n";
203 names_t::const_iterator i = m_names.find( name.first );
204 if ( i == m_names.end() ) {
209 r = name_t( name.first, ( *i ).second.make_unique( name.second ) );
211 name_write( buf, r );
212 globalErrorStream() << "> unique name is " << buf << "\n";
216 void insert( const name_t& name ){
217 m_names[name.first].insert( name.second );
220 void erase( const name_t& name ){
221 names_t::iterator i = m_names.find( name.first );
222 if ( i == m_names.end() ) {
223 ASSERT_MESSAGE( true, "erase: name not found" );
227 ( *i ).second.erase( name.second );
228 if ( ( *i ).second.empty() ) {
235 return m_names.empty();
244 #define ERROR_MESSAGE( message )
248 void name_check_equal( const name_t& name, const char* string, unsigned int postfix ){
249 ASSERT_MESSAGE( strcmp( name.first.c_str(), string ) == 0
250 && name.second.number() == postfix,
253 void test_refcount(){
256 names.insert( name_t( "func_bleh_", "100" ) );
257 names.insert( name_t( "func_bleh_", "100" ) );
258 names.insert( name_t( "func_bleh_", "100" ) );
261 names.erase( name_t( "func_bleh_", "100" ) );
262 names.erase( name_t( "func_bleh_", "100" ) );
263 names.erase( name_t( "func_bleh_", "100" ) );
265 ASSERT_MESSAGE( names.empty(), "test failed!" );
268 void test_make_unique(){
272 name_t name( names.make_unique( name_t( "func_bleh_", "01" ) ) );
273 name_check_equal( name, "func_bleh_", 1 );
274 names.insert( name );
277 name_t name( names.make_unique( name_t( "func_bleh_", "04" ) ) );
278 name_check_equal( name, "func_bleh_", 4 );
279 names.insert( name );
282 name_t name( names.make_unique( name_t( "func_bleh_", "04" ) ) );
283 name_check_equal( name, "func_bleh_", 2 );
284 names.insert( name );
287 name_t name( names.make_unique( name_t( "func_bleh_", "1" ) ) );
288 name_check_equal( name, "func_bleh_", 3 );
289 names.insert( name );
292 name_t name( names.make_unique( name_t( "func_bleh_", "2" ) ) );
293 name_check_equal( name, "func_bleh_", 5 );
294 names.insert( name );
297 name_t name( names.make_unique( name_t( "func_bleh_", "3" ) ) );
298 name_check_equal( name, "func_bleh_", 6 );
299 names.insert( name );
302 names.erase( name_t( "func_bleh_", "1" ) );
303 names.erase( name_t( "func_bleh_", "2" ) );
304 names.erase( name_t( "func_bleh_", "3" ) );
305 names.erase( name_t( "func_bleh_", "4" ) );
306 names.erase( name_t( "func_bleh_", "5" ) );
307 names.erase( name_t( "func_bleh_", "6" ) );
309 ASSERT_MESSAGE( names.empty(), "test failed!" );
318 const TestUniqueName g_testuniquename;