StrPool.h (5996B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #ifndef __STRPOOL_H__ 30 #define __STRPOOL_H__ 31 32 /* 33 =============================================================================== 34 35 idStrPool 36 37 =============================================================================== 38 */ 39 40 class idStrPool; 41 42 class idPoolStr : public idStr { 43 friend class idStrPool; 44 45 public: 46 idPoolStr() { numUsers = 0; } 47 ~idPoolStr() { assert( numUsers == 0 ); } 48 49 // returns total size of allocated memory 50 size_t Allocated() const { return idStr::Allocated(); } 51 // returns total size of allocated memory including size of string pool type 52 size_t Size() const { return sizeof( *this ) + Allocated(); } 53 // returns a pointer to the pool this string was allocated from 54 const idStrPool * GetPool() const { return pool; } 55 56 private: 57 idStrPool * pool; 58 mutable int numUsers; 59 }; 60 61 class idStrPool { 62 public: 63 idStrPool() { caseSensitive = true; } 64 65 void SetCaseSensitive( bool caseSensitive ); 66 67 int Num() const { return pool.Num(); } 68 size_t Allocated() const; 69 size_t Size() const; 70 71 const idPoolStr * operator[]( int index ) const { return pool[index]; } 72 73 const idPoolStr * AllocString( const char *string ); 74 void FreeString( const idPoolStr *poolStr ); 75 const idPoolStr * CopyString( const idPoolStr *poolStr ); 76 void Clear(); 77 78 private: 79 bool caseSensitive; 80 idList<idPoolStr *> pool; 81 idHashIndex poolHash; 82 }; 83 84 /* 85 ================ 86 idStrPool::SetCaseSensitive 87 ================ 88 */ 89 ID_INLINE void idStrPool::SetCaseSensitive( bool caseSensitive ) { 90 this->caseSensitive = caseSensitive; 91 } 92 93 /* 94 ================ 95 idStrPool::AllocString 96 ================ 97 */ 98 ID_INLINE const idPoolStr *idStrPool::AllocString( const char *string ) { 99 int i, hash; 100 idPoolStr *poolStr; 101 102 hash = poolHash.GenerateKey( string, caseSensitive ); 103 if ( caseSensitive ) { 104 for ( i = poolHash.First( hash ); i != -1; i = poolHash.Next( i ) ) { 105 if ( pool[i]->Cmp( string ) == 0 ) { 106 pool[i]->numUsers++; 107 return pool[i]; 108 } 109 } 110 } else { 111 for ( i = poolHash.First( hash ); i != -1; i = poolHash.Next( i ) ) { 112 if ( pool[i]->Icmp( string ) == 0 ) { 113 pool[i]->numUsers++; 114 return pool[i]; 115 } 116 } 117 } 118 119 poolStr = new (TAG_IDLIB_STRING) idPoolStr; 120 *static_cast<idStr *>(poolStr) = string; 121 poolStr->pool = this; 122 poolStr->numUsers = 1; 123 poolHash.Add( hash, pool.Append( poolStr ) ); 124 return poolStr; 125 } 126 127 /* 128 ================ 129 idStrPool::FreeString 130 ================ 131 */ 132 ID_INLINE void idStrPool::FreeString( const idPoolStr *poolStr ) { 133 int i, hash; 134 135 assert( poolStr->numUsers >= 1 ); 136 assert( poolStr->pool == this ); 137 138 poolStr->numUsers--; 139 if ( poolStr->numUsers <= 0 ) { 140 hash = poolHash.GenerateKey( poolStr->c_str(), caseSensitive ); 141 if ( caseSensitive ) { 142 for ( i = poolHash.First( hash ); i != -1; i = poolHash.Next( i ) ) { 143 if ( pool[i]->Cmp( poolStr->c_str() ) == 0 ) { 144 break; 145 } 146 } 147 } else { 148 for ( i = poolHash.First( hash ); i != -1; i = poolHash.Next( i ) ) { 149 if ( pool[i]->Icmp( poolStr->c_str() ) == 0 ) { 150 break; 151 } 152 } 153 } 154 assert( i != -1 ); 155 assert( pool[i] == poolStr ); 156 delete pool[i]; 157 pool.RemoveIndex( i ); 158 poolHash.RemoveIndex( hash, i ); 159 } 160 } 161 162 /* 163 ================ 164 idStrPool::CopyString 165 ================ 166 */ 167 ID_INLINE const idPoolStr *idStrPool::CopyString( const idPoolStr *poolStr ) { 168 169 assert( poolStr->numUsers >= 1 ); 170 171 if ( poolStr->pool == this ) { 172 // the string is from this pool so just increase the user count 173 poolStr->numUsers++; 174 return poolStr; 175 } else { 176 // the string is from another pool so it needs to be re-allocated from this pool. 177 return AllocString( poolStr->c_str() ); 178 } 179 } 180 181 /* 182 ================ 183 idStrPool::Clear 184 ================ 185 */ 186 ID_INLINE void idStrPool::Clear() { 187 int i; 188 189 for ( i = 0; i < pool.Num(); i++ ) { 190 pool[i]->numUsers = 0; 191 } 192 pool.DeleteContents( true ); 193 poolHash.Free(); 194 } 195 196 /* 197 ================ 198 idStrPool::Allocated 199 ================ 200 */ 201 ID_INLINE size_t idStrPool::Allocated() const { 202 int i; 203 size_t size; 204 205 size = pool.Allocated() + poolHash.Allocated(); 206 for ( i = 0; i < pool.Num(); i++ ) { 207 size += pool[i]->Allocated(); 208 } 209 return size; 210 } 211 212 /* 213 ================ 214 idStrPool::Size 215 ================ 216 */ 217 ID_INLINE size_t idStrPool::Size() const { 218 int i; 219 size_t size; 220 221 size = pool.Size() + poolHash.Size(); 222 for ( i = 0; i < pool.Num(); i++ ) { 223 size += pool[i]->Size(); 224 } 225 return size; 226 } 227 228 #endif /* !__STRPOOL_H__ */