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
25 #include "debugging/debugging.h"
27 #include "string/string.h"
28 #include "generic/static.h"
35 Postfix(const char* postfix) : m_value(atoi(postfix))
38 unsigned int number() const
42 void write(char* buffer) const
44 sprintf(buffer, "%u", m_value);
51 bool operator<(const Postfix& other) const
53 return m_value < other.m_value;
55 bool operator==(const Postfix& other) const
57 return m_value == other.m_value;
59 bool operator!=(const Postfix& other) const
61 return !operator==(other);
68 std::pair<unsigned int, unsigned int> m_value;
70 Postfix(unsigned int number, unsigned int leading_zeros)
71 : m_value(leading_zeros, number)
74 Postfix(const char* postfix)
75 : m_value(number_count_leading_zeros(postfix), atoi(postfix))
78 unsigned int number() const
80 return m_value.second;
82 unsigned int leading_zeros() const
86 void write(char* buffer)
88 for(unsigned int count = 0; count < m_value.first; ++count, ++buffer)
90 sprintf(buffer, "%u", m_value.second);
95 if(m_value.first != 0 && m_value.second % 10 == 0)
99 bool operator<(const Postfix& other) const
101 return m_value < other.m_value;
103 bool operator==(const Postfix& other) const
105 return m_value == other.m_value;
107 bool operator!=(const Postfix& other) const
109 return !operator==(other);
115 typedef std::pair<CopiedString, Postfix> name_t;
117 inline void name_write(char* buffer, name_t name)
119 strcpy(buffer, name.first.c_str());
120 name.second.write(buffer + strlen(name.first.c_str()));
123 inline name_t name_read(const char* name)
125 const char* end = name + strlen(name);
126 for(const char* p = end; end != name; --p)
128 if(strrchr("1234567890", *p) == NULL)
133 return name_t(CopiedString(StringRange(name, end)), Postfix(end));
140 typedef std::map<Postfix, unsigned int> postfixes_t;
141 postfixes_t m_postfixes;
144 Postfix find_first_empty() const
146 Postfix postfix("1");
147 for(postfixes_t::const_iterator i = m_postfixes.find(postfix); i != m_postfixes.end(); ++i, ++postfix)
149 if((*i).first != postfix)
158 Postfix make_unique(Postfix postfix) const
160 postfixes_t::const_iterator i = m_postfixes.find(postfix);
161 if(i == m_postfixes.end())
167 return find_first_empty();
171 void insert(Postfix postfix)
173 postfixes_t::iterator i = m_postfixes.find(postfix);
174 if(i == m_postfixes.end())
176 m_postfixes.insert(postfixes_t::value_type(postfix, 1));
184 void erase(Postfix postfix)
186 postfixes_t::iterator i = m_postfixes.find(postfix);
187 if(i == m_postfixes.end())
193 if(--(*i).second == 0)
194 m_postfixes.erase(i);
200 return m_postfixes.empty();
207 typedef std::map<CopiedString, PostFixes> names_t;
210 name_t make_unique(const name_t& name) const
214 name_write(buf, name);
215 globalErrorStream() << "find unique name for " << buf << "\n";
216 globalErrorStream() << "> currently registered names:\n";
217 for(names_t::const_iterator i = m_names.begin(); i != m_names.end(); ++i)
219 globalErrorStream() << ">> " << i->first.c_str() << ": ";
220 for(PostFixes::postfixes_t::const_iterator j = i->second.m_postfixes.begin(); j != i->second.m_postfixes.end(); ++j)
223 globalErrorStream() << " '" << buf << "'";
225 globalErrorStream() << "\n";
227 names_t::const_iterator i = m_names.find(name.first);
228 if(i == m_names.end())
234 r = name_t(name.first, (*i).second.make_unique(name.second));
237 globalErrorStream() << "> unique name is " << buf << "\n";
241 void insert(const name_t& name)
243 m_names[name.first].insert(name.second);
246 void erase(const name_t& name)
248 names_t::iterator i = m_names.find(name.first);
249 if(i == m_names.end())
251 ASSERT_MESSAGE(true, "erase: name not found");
255 (*i).second.erase(name.second);
256 if((*i).second.empty())
263 return m_names.empty();
272 #define ERROR_MESSAGE(message)
276 void name_check_equal(const name_t& name, const char* string, unsigned int postfix)
278 ASSERT_MESSAGE(strcmp(name.first.c_str(), string) == 0
279 && name.second.number() == postfix,
286 names.insert(name_t("func_bleh_", "100"));
287 names.insert(name_t("func_bleh_", "100"));
288 names.insert(name_t("func_bleh_", "100"));
291 names.erase(name_t("func_bleh_", "100"));
292 names.erase(name_t("func_bleh_", "100"));
293 names.erase(name_t("func_bleh_", "100"));
295 ASSERT_MESSAGE(names.empty(), "test failed!");
298 void test_make_unique()
303 name_t name(names.make_unique(name_t("func_bleh_", "01")));
304 name_check_equal(name, "func_bleh_", 1);
308 name_t name(names.make_unique(name_t("func_bleh_", "04")));
309 name_check_equal(name, "func_bleh_", 4);
313 name_t name(names.make_unique(name_t("func_bleh_", "04")));
314 name_check_equal(name, "func_bleh_", 2);
318 name_t name(names.make_unique(name_t("func_bleh_", "1")));
319 name_check_equal(name, "func_bleh_", 3);
323 name_t name(names.make_unique(name_t("func_bleh_", "2")));
324 name_check_equal(name, "func_bleh_", 5);
328 name_t name(names.make_unique(name_t("func_bleh_", "3")));
329 name_check_equal(name, "func_bleh_", 6);
333 names.erase(name_t("func_bleh_", "1"));
334 names.erase(name_t("func_bleh_", "2"));
335 names.erase(name_t("func_bleh_", "3"));
336 names.erase(name_t("func_bleh_", "4"));
337 names.erase(name_t("func_bleh_", "5"));
338 names.erase(name_t("func_bleh_", "6"));
340 ASSERT_MESSAGE(names.empty(), "test failed!");
350 const TestUniqueName g_testuniquename;