#if !defined( INCLUDED_UNIQUENAMES_H ) #define INCLUDED_UNIQUENAMES_H #include "debugging/debugging.h" #include #include "string/string.h" #include "generic/static.h" #if 1 class Postfix { unsigned int m_value; public: Postfix( const char* postfix ) : m_value( atoi( postfix ) ){ } unsigned int number() const { return m_value; } void write( char* buffer ){ sprintf( buffer, "%u", m_value ); } Postfix& operator++(){ ++m_value; return *this; } bool operator<( const Postfix& other ) const { return m_value < other.m_value; } bool operator==( const Postfix& other ) const { return m_value == other.m_value; } bool operator!=( const Postfix& other ) const { return !operator==( other ); } }; #else class Postfix { std::pair m_value; public: Postfix( unsigned int number, unsigned int leading_zeros ) : m_value( leading_zeros, number ){ } Postfix( const char* postfix ) : m_value( number_count_leading_zeros( postfix ), atoi( postfix ) ){ } unsigned int number() const { return m_value.second; } unsigned int leading_zeros() const { return m_value.first; } void write( char* buffer ){ for ( unsigned int count = 0; count < m_value.first; ++count, ++buffer ) *buffer = '0'; sprintf( buffer, "%u", m_value.second ); } Postfix& operator++(){ ++m_value.second; if ( m_value.first != 0 && m_value.second % 10 == 0 ) { --m_value.first; } return *this; } bool operator<( const Postfix& other ) const { return m_value < other.m_value; } bool operator==( const Postfix& other ) const { return m_value == other.m_value; } bool operator!=( const Postfix& other ) const { return !operator==( other ); } }; #endif typedef std::pair name_t; inline void name_write( char* buffer, name_t name ){ strcpy( buffer, name.first.c_str() ); name.second.write( buffer + strlen( name.first.c_str() ) ); } inline name_t name_read( const char* name ){ const char* end = name + strlen( name ); for ( const char* p = end; end != name; --p ) { if ( strrchr( "1234567890", *p ) == NULL ) { break; } end = p; } return name_t( CopiedString( name, end ), Postfix( end ) ); } class PostFixes { typedef std::map postfixes_t; postfixes_t m_postfixes; Postfix find_first_empty() const { Postfix postfix( "1" ); for ( postfixes_t::const_iterator i = m_postfixes.find( postfix ); i != m_postfixes.end(); ++i, ++postfix ) { if ( ( *i ).first != postfix ) { break; } } return postfix; } public: Postfix make_unique( Postfix postfix ) const { postfixes_t::const_iterator i = m_postfixes.find( postfix ); if ( i == m_postfixes.end() ) { return postfix; } else { return find_first_empty(); } } void insert( Postfix postfix ){ postfixes_t::iterator i = m_postfixes.find( postfix ); if ( i == m_postfixes.end() ) { m_postfixes.insert( postfixes_t::value_type( postfix, 1 ) ); } else { ++( *i ).second; } } void erase( Postfix postfix ){ postfixes_t::iterator i = m_postfixes.find( postfix ); if ( i == m_postfixes.end() ) { // error } else { if ( --( *i ).second == 0 ) { m_postfixes.erase( i ); } } } bool empty() const { return m_postfixes.empty(); } }; class UniqueNames { typedef std::map names_t; names_t m_names; public: name_t make_unique( const name_t& name ) const { names_t::const_iterator i = m_names.find( name.first ); if ( i == m_names.end() ) { return name; } else { return name_t( name.first, ( *i ).second.make_unique( name.second ) ); } } void insert( const name_t& name ){ m_names[name.first].insert( name.second ); } void erase( const name_t& name ){ names_t::iterator i = m_names.find( name.first ); if ( i == m_names.end() ) { ASSERT_MESSAGE( true, "erase: name not found" ); } else { ( *i ).second.erase( name.second ); if ( ( *i ).second.empty() ) { m_names.erase( i ); } } } bool empty() const { return m_names.empty(); } }; #if 0 #undef ERROR_MESSAGE #define ERROR_MESSAGE( message ) class TestUniqueName { void name_check_equal( const name_t& name, const char* string, unsigned int postfix ){ ASSERT_MESSAGE( strcmp( name.first.c_str(), string ) == 0 && name.second.number() == postfix, "test failed!" ); } void test_refcount(){ Names names; names.insert( name_t( "func_bleh_", "100" ) ); names.insert( name_t( "func_bleh_", "100" ) ); names.insert( name_t( "func_bleh_", "100" ) ); names.erase( name_t( "func_bleh_", "100" ) ); names.erase( name_t( "func_bleh_", "100" ) ); names.erase( name_t( "func_bleh_", "100" ) ); ASSERT_MESSAGE( names.empty(), "test failed!" ); } void test_make_unique(){ Names names; { name_t name( names.make_unique( name_t( "func_bleh_", "01" ) ) ); name_check_equal( name, "func_bleh_", 1 ); names.insert( name ); } { name_t name( names.make_unique( name_t( "func_bleh_", "04" ) ) ); name_check_equal( name, "func_bleh_", 4 ); names.insert( name ); } { name_t name( names.make_unique( name_t( "func_bleh_", "04" ) ) ); name_check_equal( name, "func_bleh_", 2 ); names.insert( name ); } { name_t name( names.make_unique( name_t( "func_bleh_", "1" ) ) ); name_check_equal( name, "func_bleh_", 3 ); names.insert( name ); } { name_t name( names.make_unique( name_t( "func_bleh_", "2" ) ) ); name_check_equal( name, "func_bleh_", 5 ); names.insert( name ); } { name_t name( names.make_unique( name_t( "func_bleh_", "3" ) ) ); name_check_equal( name, "func_bleh_", 6 ); names.insert( name ); } names.erase( name_t( "func_bleh_", "1" ) ); names.erase( name_t( "func_bleh_", "2" ) ); names.erase( name_t( "func_bleh_", "3" ) ); names.erase( name_t( "func_bleh_", "4" ) ); names.erase( name_t( "func_bleh_", "5" ) ); names.erase( name_t( "func_bleh_", "6" ) ); ASSERT_MESSAGE( names.empty(), "test failed!" ); } public: TestUniqueName(){ test_refcount(); test_make_unique(); } }; const TestUniqueName g_testuniquename; #endif #endif