HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_NameManager.h
Go to the documentation of this file.
1 /*
2 * PROPRIETARY INFORMATION. This software is proprietary to
3 * Side Effects Software Inc., and is not to be reproduced,
4 * transmitted, or disclosed in any way without written permission.
5 *
6 * NAME: UT_NameManager.h
7 *
8 * COMMENTS:
9 *
10 * This class implements a templated name manager, which aims to
11 * provide fast unique name management functions. Note that it
12 * is templated, and thus can be used with any data type.
13 *
14 */
15 
16 #ifndef __UT_NameManager_h__
17 #define __UT_NameManager_h__
18 
19 #include "UT_API.h"
20 #include "UT_ArrayStringMap.h"
21 #include "UT_Defines.h"
22 #include "UT_String.h"
23 #include "UT_StringHolder.h"
24 #include "UT_WorkBuffer.h"
25 
26 /*****************************************************************************/
27 // Faster version and simplier of the previous name manager.
28 // Based on profiling run the other version had a few problems.
29 // Doing lookups was slow because of some operator new calls during the lookups.
30 // Doing a lookup always had to split the string to get the base string.
31 // The multi map behavior was really only required for generating a unique name in a fast way.
32 // Now the hash() function isn't be called everytime because UT_StringHolder keeps a hash.
33 // It means if the string is kept in memory and doesn't change, only the cached hash will be used.
34 template < class DATA_TYPE >
36 {
37 public:
38 
39  /// suffix_start_number determines the starting numerical suffix when unique names are generated.
40  /// For example:
41  /// If set to 0, generating unique names for "base" will result in "base0", "base1", "base2", etc.
42  /// If set to 1, generating unique names for "base" will result in "base", "base1", "base2", etc.
43  /// If set to 2, generating unique names for "base" will result in "base", "base2", "base3", etc.
44  /// And so on.
45  UT_NameManager(int suffix_start_number = 2)
46  {
47  mySuffixStartNumber = suffix_start_number;
48  myNumEntries = 0;
49  }
51 
52  /// Returns the amount of memory owned by this UT_NameManger
53  int64 getMemoryUsage(bool inclusive) const
54  {
55  int64 mem = inclusive ? sizeof(*this) : 0;
56 
57  mem += myMap.getMemoryUsage(false);
58 
59  return mem;
60  }
61 
62  /// Returns the total number of unique names in the manager.
63  unsigned entries() const { return (unsigned) myNumEntries; }
64 
65  /// Returns true if empty, false otherwise.
66  bool empty() const { return myNumEntries == 0; }
67 
68  /// Removes a name, such as "base123", from the manager. If the removed name
69  /// was the last one in a category and the category is now empty, deletes
70  /// the category as well.
71  /// Returns true if removal was successfull, false otherwise.
72  bool deleteSymbol(const UT_StringRef &symbol, bool set_to_null )
73  {
74  if(!symbol.isstring())
75  return false;
76 
77  auto it = myMap.find(symbol);
78  if( it==myMap.end() )
79  return false;
80 
81  if( set_to_null )
82  it->second = nullptr;
83  else
84  myMap.erase(it);
85 
86  myNumEntries--;
87  UT_ASSERT(myNumEntries>=0);
88 
89  return true;
90  }
91 
92  /// Clears all the entries from this manager.
93  /// if set_to_null is true the map entries values will be set to null instead
94  /// of erasing all the entries.
95  void clear(bool set_to_null)
96  {
97  if( set_to_null )
98  {
99  for( auto it = myMap.begin(); !it.atEnd(); ++it )
100  it->second = nullptr;
101  }
102  else
103  myMap.clear();
104 
105  myNumEntries = 0;
106  }
107 
108  /// Generates a new name unique relative to the items alraedy in this collection,
109  /// optionally starting with a given name.
110  bool getUniqueName(const UT_StringRef &orig_name_in, UT_WorkBuffer& unique_name_out) const
111  {
112  unsigned i=mySuffixStartNumber;
113  char number[UT_NUMBUF];
114 
115  UT_String temp_name(
116  orig_name_in.isstring()
117  ? static_cast<const char *>(orig_name_in) : "name",
118  false);
119  UT_String base;
120  temp_name.base(base);
121 
122  unique_name_out.strcpy(base);
123  int base_len = unique_name_out.length();
124 
125  // Get the first available entry, we could add a multimap later on if this is too slow
126  // The old name manager was really slow on the findSymbol which is called more often than this.
127  for(;;)
128  {
129  UT_String::itoa(number, i++);
130  unique_name_out.append(number);
131  UT_StringRef unique_name_ref(unique_name_out.buffer() );
132  if( !findSymbol( unique_name_ref ) )
133  return true;
134 
135  // get back to previous string keeping the same buffer
136  unique_name_out.truncate(base_len);
137  }
138 
139  UT_ASSERT(false);// Shouldn't get here.
140  return false;
141  }
142 
143  /// Adds a new name to this collection. If the name already exists,
144  /// the addition will silently fail, so it is the caller's responsibility
145  /// to assure that the name is unique by calling findSymbol() if
146  /// needed. This is done to avoid extra uniqueness checks that may
147  /// be unnecessary in certain situations.
148  ///
149  /// Returns true if symbol added successfully, false otherwise.
150  bool addSymbol(const UT_StringRef &symbol, DATA_TYPE data)
151  {
152  if(!symbol.isstring())
153  return false;
154 
155  auto it = myMap.find(symbol);
156  if( it!=myMap.end() )
157  {
158  if( it->second == nullptr )
159  {
160  it->second = data;
161  myNumEntries++;
162  return true;
163  }
164  }
165  else
166  {
167  myMap.emplace(symbol, data);
168  myNumEntries++;
169  return true;
170  }
171 
172  return false;
173  }
174 
175  /// Finds the data item associated with a given name. Returns a pointer
176  /// to the item if found, nullptr if the name is not in the collection.
177  DATA_TYPE findSymbol(const UT_StringRef &symbol) const
178  {
179  if(!symbol.isstring())
180  return nullptr;
181 
182  auto it = myMap.find(symbol);
183  if( it==myMap.end() )
184  return nullptr;
185 
186  return it->second;
187 
188  }
189 
190 private:
191 
193  int mySuffixStartNumber;
194  unsigned myNumEntries;
195 
196 };
197 /*****************************************************************************/
198 #endif
void clear()
Definition: UT_ArraySet.h:366
SYS_FORCE_INLINE exint length() const
bool addSymbol(const UT_StringRef &symbol, DATA_TYPE data)
UT_NameManager(int suffix_start_number=2)
bool empty() const
Returns true if empty, false otherwise.
SYS_FORCE_INLINE const char * buffer() const
SYS_FORCE_INLINE void strcpy(const char *src)
iterator end()
Returns a non-const end iterator for the set.
Definition: UT_ArraySet.h:673
void clear(bool set_to_null)
iterator find(const Key &key)
Definition: UT_ArrayMap.h:158
unsigned entries() const
Returns the total number of unique names in the manager.
int64 getMemoryUsage(bool inclusive) const
Returns the amount of memory owned by this UT_NameManger.
DATA_TYPE findSymbol(const UT_StringRef &symbol) const
iterator begin()
Returns a non-const iterator for the beginning of the set.
Definition: UT_ArraySet.h:658
long long int64
Definition: SYS_Types.h:116
bool getUniqueName(const UT_StringRef &orig_name_in, UT_WorkBuffer &unique_name_out) const
static int itoa(char *str, int64 i)
int64 getMemoryUsage(bool inclusive) const
Definition: UT_ArraySet.h:1290
SYS_FORCE_INLINE void truncate(exint new_length)
GLboolean * data
Definition: glcorearb.h:130
std::pair< iterator, bool > emplace(Args &&...args)
Definition: UT_ArraySet.h:1025
bool deleteSymbol(const UT_StringRef &symbol, bool set_to_null)
#define UT_NUMBUF
Definition: UT_Defines.h:24
SYS_FORCE_INLINE void append(char character)
iterator erase(iterator pos)
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:171
const char * base(UT_String &buf) const
SYS_FORCE_INLINE bool isstring() const