gtkradiant/tools/urt/libs/uniquenames.h

282 lines
5.8 KiB
C++

#if !defined( INCLUDED_UNIQUENAMES_H )
#define INCLUDED_UNIQUENAMES_H
#include "debugging/debugging.h"
#include <map>
#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<unsigned int, unsigned int> 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<CopiedString, Postfix> 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<Postfix, unsigned int> 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<CopiedString, PostFixes> 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