| 1 | /* | 
|---|
| 2 |    orxonox - the future of 3D-vertical-scrollers | 
|---|
| 3 |  | 
|---|
| 4 |    Copyright (C) 2006 orx | 
|---|
| 5 |  | 
|---|
| 6 |    This program is free software; you can redistribute it and/or modify | 
|---|
| 7 |    it under the terms of the GNU General Public License as published by | 
|---|
| 8 |    the Free Software Foundation; either version 2, or (at your option) | 
|---|
| 9 |    any later version. | 
|---|
| 10 |  | 
|---|
| 11 |    ### File Specific: | 
|---|
| 12 |    main-programmer: Benjamin Grauer | 
|---|
| 13 |    co-programmer: ... | 
|---|
| 14 | */ | 
|---|
| 15 |  | 
|---|
| 16 | //#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_ | 
|---|
| 17 |  | 
|---|
| 18 | #include "object_list.h" | 
|---|
| 19 | #include <cassert> | 
|---|
| 20 |  | 
|---|
| 21 | /** | 
|---|
| 22 |  * @brief Constructor, that creates an ObjectList while checking (development mode) for uniqueness of all Keys (names and ID's) | 
|---|
| 23 |  * @param className The Name of the Class to create an ObjectList for. | 
|---|
| 24 |  * @param id The ID if you like, or -1 otherwise. | 
|---|
| 25 |  * @return a new NewObejctList | 
|---|
| 26 |  */ | 
|---|
| 27 | ObjectListBase::ObjectListBase(const std::string& className) | 
|---|
| 28 |     : _name(className) | 
|---|
| 29 | { | 
|---|
| 30 |   if (ObjectListBase::_classesByID == NULL) | 
|---|
| 31 |   { | 
|---|
| 32 |     ObjectListBase::_classesByID = new IDMap; | 
|---|
| 33 |     assert (ObjectListBase::_classesByName == NULL); | 
|---|
| 34 |     ObjectListBase::_classesByName = new NameMap; | 
|---|
| 35 |   } | 
|---|
| 36 |   assert(!ObjectListBase::classNameExists(className) && "Classes should only be included once, and no two classes should have the same name (key value)"); | 
|---|
| 37 |  | 
|---|
| 38 |   int id = ObjectListBase::_classesByID->size(); | 
|---|
| 39 |   // searching for a free ID | 
|---|
| 40 |   while (ObjectListBase::classIDExists(id)) ++id; | 
|---|
| 41 |  | 
|---|
| 42 |   assert(!ObjectListBase::classIDExists(id) && "Classes should only be included once, and no two classes should have the same ID (key value)"); | 
|---|
| 43 |  | 
|---|
| 44 |   this->_id = id; | 
|---|
| 45 |   /// Some Output, that will fall out later | 
|---|
| 46 |   //  std::cout << "register new ObjectList " << className << " ID: " << this->_id << std::endl; | 
|---|
| 47 |  | 
|---|
| 48 |   this->_identity = ClassID(this); | 
|---|
| 49 |   (*ObjectListBase::_classesByID)[this->_identity.id()] = this; | 
|---|
| 50 |   (*ObjectListBase::_classesByName)[this->_identity.name()] = this; | 
|---|
| 51 | } | 
|---|
| 52 |  | 
|---|
| 53 |  | 
|---|
| 54 | /** | 
|---|
| 55 |  * Destructor. | 
|---|
| 56 |  * | 
|---|
| 57 |  * This destructor deletes the ObjectList, and cleans up the ObjectList sorted Maps. | 
|---|
| 58 |  */ | 
|---|
| 59 | ObjectListBase::~ObjectListBase() | 
|---|
| 60 | { | 
|---|
| 61 |   assert (ObjectListBase::_classesByName != NULL && ObjectListBase::_classesByID != NULL); | 
|---|
| 62 |   /* | 
|---|
| 63 |   std::cout << "Erasing: " << this->_name << " "<< this->_id  << std::endl; | 
|---|
| 64 |   std::cout << "SIZE OF _classByID: " << ObjectListBase::_classesByID->size() << std::endl; | 
|---|
| 65 |   std::cout << "SIZE OF _classByName: " << ObjectListBase::_classesByName->size() << std::endl; | 
|---|
| 66 |   */ | 
|---|
| 67 |   ObjectListBase::_classesByID->erase(this->_identity.id()); | 
|---|
| 68 |   ObjectListBase::_classesByName->erase(this->_identity.name()); | 
|---|
| 69 |  | 
|---|
| 70 |   if (ObjectListBase::_classesByID->empty()) | 
|---|
| 71 |   { | 
|---|
| 72 |     delete ObjectListBase::_classesByID; | 
|---|
| 73 |     ObjectListBase::_classesByID = NULL; | 
|---|
| 74 |     assert(ObjectListBase::_classesByName != NULL); | 
|---|
| 75 |     delete ObjectListBase::_classesByName; | 
|---|
| 76 |     ObjectListBase::_classesByName = NULL; | 
|---|
| 77 |   } | 
|---|
| 78 | } | 
|---|
| 79 |  | 
|---|
| 80 | ObjectListBase::IDMap* ObjectListBase::_classesByID = NULL; | 
|---|
| 81 | ObjectListBase::NameMap* ObjectListBase::_classesByName = NULL; | 
|---|
| 82 | std::list<std::string> ObjectListBase::_classNames; | 
|---|
| 83 |  | 
|---|
| 84 | /** | 
|---|
| 85 |  * @returns the Registered Class Count. | 
|---|
| 86 |  */ | 
|---|
| 87 | unsigned int ObjectListBase::classCount() | 
|---|
| 88 | { | 
|---|
| 89 |   assert (ObjectListBase::_classesByID != NULL); | 
|---|
| 90 |   return ObjectListBase::_classesByID->size(); | 
|---|
| 91 | }; | 
|---|
| 92 |  | 
|---|
| 93 | /** | 
|---|
| 94 |  * @brief Checks if a Class with name already exists. | 
|---|
| 95 |  * @param id The id of the Class to check. | 
|---|
| 96 |  * @return true if such a class already exists. | 
|---|
| 97 |  */ | 
|---|
| 98 | bool ObjectListBase::classIDExists(int id) | 
|---|
| 99 | { | 
|---|
| 100 |   return (ObjectListBase::_classesByID->find(id) != ObjectListBase::_classesByID->end()); | 
|---|
| 101 | } | 
|---|
| 102 |  | 
|---|
| 103 | /** | 
|---|
| 104 |  * @brief Checks if a Class with name already exists. | 
|---|
| 105 |  * @param name The Name of the Class to check. | 
|---|
| 106 |  * @return true if such a class already exists. | 
|---|
| 107 |  */ | 
|---|
| 108 | bool ObjectListBase::classNameExists(const std::string& name) | 
|---|
| 109 | { | 
|---|
| 110 |   return (ObjectListBase::_classesByName->find(name) != ObjectListBase::_classesByName->end()); | 
|---|
| 111 | } | 
|---|
| 112 |  | 
|---|
| 113 | /** | 
|---|
| 114 |  * @brief searches for a ClassID in the list of all ObjectLists, and returns its Identity | 
|---|
| 115 |  * @param id: The Id to search for | 
|---|
| 116 |  * @returns the ClassID if found and NullClass' identity if not. | 
|---|
| 117 |  */ | 
|---|
| 118 | const ClassID& ObjectListBase::retrieveIdentity(int id) | 
|---|
| 119 | { | 
|---|
| 120 |   const ObjectListBase* const base = ObjectListBase::getObjectList(id); | 
|---|
| 121 |  | 
|---|
| 122 |   if (base != NULL) | 
|---|
| 123 |     return base->_identity; | 
|---|
| 124 |   else | 
|---|
| 125 |     return NullClass::staticClassID(); | 
|---|
| 126 | } | 
|---|
| 127 |  | 
|---|
| 128 |  | 
|---|
| 129 | /** | 
|---|
| 130 |  * @brief searches for a ClassID in the list of all ObjectLists, and returns its Identity | 
|---|
| 131 |  * @param name: The Name to search for | 
|---|
| 132 |  * @returns the ClassID if found and NullClass' identity if not. | 
|---|
| 133 |  */ | 
|---|
| 134 | const ClassID& ObjectListBase::retrieveIdentity(const std::string& name) | 
|---|
| 135 | { | 
|---|
| 136 |   const ObjectListBase* const base = ObjectListBase::getObjectList(name); | 
|---|
| 137 |  | 
|---|
| 138 |   if (base != NULL) | 
|---|
| 139 |     return base->_identity; | 
|---|
| 140 |   else | 
|---|
| 141 |     return NullClass::staticClassID(); | 
|---|
| 142 | } | 
|---|
| 143 |  | 
|---|
| 144 |  | 
|---|
| 145 | /** | 
|---|
| 146 |  * @brief Searches for a ObjectList with the ID classID | 
|---|
| 147 |  * @param classID the ID to search for. | 
|---|
| 148 |  * @return The ObjectList if found, NULL otherwise. | 
|---|
| 149 |  */ | 
|---|
| 150 | const ObjectListBase* const ObjectListBase::getObjectList(int classID) | 
|---|
| 151 | { | 
|---|
| 152 |   assert (ObjectListBase::_classesByID != NULL); | 
|---|
| 153 |   ObjectListBase::IDMap::iterator it = ObjectListBase::_classesByID->find(classID); | 
|---|
| 154 |   if (it != ObjectListBase::_classesByID->end()) | 
|---|
| 155 |     return (*it).second; | 
|---|
| 156 |   else | 
|---|
| 157 |     return NULL; | 
|---|
| 158 | } | 
|---|
| 159 |  | 
|---|
| 160 | /** | 
|---|
| 161 |  * @brief Searches for a ObjectList with the Name className | 
|---|
| 162 |  * @param className the Name to search for. | 
|---|
| 163 |  * @return The ObjectList if found, NULL otherwise. | 
|---|
| 164 |  */ | 
|---|
| 165 | const ObjectListBase* const ObjectListBase::getObjectList(const std::string& className) | 
|---|
| 166 | { | 
|---|
| 167 |   assert (ObjectListBase::_classesByName != NULL); | 
|---|
| 168 |   ObjectListBase::NameMap::iterator it = ObjectListBase::_classesByName->find(className); | 
|---|
| 169 |   if (it != ObjectListBase::_classesByName->end()) | 
|---|
| 170 |     return (*it).second; | 
|---|
| 171 |   else | 
|---|
| 172 |     return NULL; | 
|---|
| 173 | } | 
|---|
| 174 |  | 
|---|
| 175 | /** | 
|---|
| 176 |  * @brief Searches for a ObjectList with the ClassID classID | 
|---|
| 177 |  * @param classID the ID to search for. | 
|---|
| 178 |  * @return The ObjectList if found, NULL otherwise. | 
|---|
| 179 |  */ | 
|---|
| 180 | const ObjectListBase* const ObjectListBase::getObjectList(const ClassID& classID) | 
|---|
| 181 | { | 
|---|
| 182 |   return ObjectListBase::getObjectList(classID.id()); | 
|---|
| 183 | } | 
|---|
| 184 |  | 
|---|
| 185 | /** | 
|---|
| 186 |  * @brief Retrieves the first BaseObject matching the name objectName from the List matching classID. | 
|---|
| 187 |  * @param classID the ID of the List. | 
|---|
| 188 |  * @param objectName the Name of the Object to search for | 
|---|
| 189 |  */ | 
|---|
| 190 | BaseObject* ObjectListBase::getBaseObject(int classID, const std::string& objectName) | 
|---|
| 191 | { | 
|---|
| 192 |   const ObjectListBase* const base = ObjectListBase::getObjectList(classID); | 
|---|
| 193 |  | 
|---|
| 194 |   if (base != NULL) | 
|---|
| 195 |     return base->getBaseObject(objectName); | 
|---|
| 196 |   else | 
|---|
| 197 |     return NULL; | 
|---|
| 198 | } | 
|---|
| 199 |  | 
|---|
| 200 | /** | 
|---|
| 201 |  * @brief Retrieves the first BaseObject matching the name objectName from the List matching className. | 
|---|
| 202 |  * @param className the Name of the List. | 
|---|
| 203 |  * @param objectName the Name of the Object to search for | 
|---|
| 204 |  */ | 
|---|
| 205 | BaseObject* ObjectListBase::getBaseObject(const std::string& className, const std::string& objectName) | 
|---|
| 206 | { | 
|---|
| 207 |   const ObjectListBase* const base = ObjectListBase::getObjectList(className); | 
|---|
| 208 |  | 
|---|
| 209 |   if (base != NULL) | 
|---|
| 210 |     return base->getBaseObject(objectName); | 
|---|
| 211 |   else | 
|---|
| 212 |     return NULL; | 
|---|
| 213 | } | 
|---|
| 214 |  | 
|---|
| 215 | /** | 
|---|
| 216 |  * @brief Retrieves the first BaseObject matching the name objectName from the List matching classID. | 
|---|
| 217 |  * @param classID The ClassID of the List. | 
|---|
| 218 |  * @param objectName the Name of the Object to search for | 
|---|
| 219 |  */ | 
|---|
| 220 | BaseObject* ObjectListBase::getBaseObject(const ClassID& classID, const std::string& objectName) | 
|---|
| 221 | { | 
|---|
| 222 |   const ObjectListBase* const base = ObjectListBase::getObjectList(classID); | 
|---|
| 223 |  | 
|---|
| 224 |   if (base != NULL) | 
|---|
| 225 |     return base->getBaseObject(objectName); | 
|---|
| 226 |   else | 
|---|
| 227 |     return NULL; | 
|---|
| 228 | } | 
|---|
| 229 |  | 
|---|
| 230 |  | 
|---|
| 231 | /** | 
|---|
| 232 |  * @returns An alphabetically sorted List of all stored ClassNames. | 
|---|
| 233 |  */ | 
|---|
| 234 | const std::list<std::string>& ObjectListBase::getClassNames() | 
|---|
| 235 | { | 
|---|
| 236 |   if (ObjectListBase::classCount() != ObjectListBase::_classNames.size()) | 
|---|
| 237 |   { | 
|---|
| 238 |     ObjectListBase::_classNames.clear(); | 
|---|
| 239 |  | 
|---|
| 240 |     for (NameMap::const_iterator it = ObjectListBase::_classesByName->begin(); | 
|---|
| 241 |          it != ObjectListBase::_classesByName->end(); | 
|---|
| 242 |          ++it) | 
|---|
| 243 |       ObjectListBase::_classNames.push_back((*it).second->name()); | 
|---|
| 244 |   } | 
|---|
| 245 |   return ObjectListBase::_classNames; | 
|---|
| 246 | } | 
|---|
| 247 |  | 
|---|
| 248 |  | 
|---|
| 249 | #include "base_object.h" | 
|---|
| 250 |  | 
|---|
| 251 | /** | 
|---|
| 252 |  * @brief Prints out some debugging information about a given List. | 
|---|
| 253 |  * @param level: | 
|---|
| 254 |  *  1: List ObjectListsand how many object. | 
|---|
| 255 |  *  2: 1+List ObjectLists entries, and information about Objects. | 
|---|
| 256 |  */ | 
|---|
| 257 | void ObjectListBase::debug(unsigned int level) const | 
|---|
| 258 | { | 
|---|
| 259 |   base_list list; | 
|---|
| 260 |   this->getBaseObjectList(&list); | 
|---|
| 261 |  | 
|---|
| 262 |   if (level > 1 || !list.empty()) | 
|---|
| 263 |     printf(" ObjectList of class %s(id:%d) contains %d objects\n", this->name().c_str(), this->id(), list.size()); | 
|---|
| 264 |  | 
|---|
| 265 |   if (level >= 2) | 
|---|
| 266 |   { | 
|---|
| 267 |     printf("  - listing Instances: \n"); | 
|---|
| 268 |     for (base_iterator it = list.begin(); | 
|---|
| 269 |          it != list.end(); | 
|---|
| 270 |          ++it) | 
|---|
| 271 |     { | 
|---|
| 272 |       printf("   + %s::%s (%p)\n", (*it)->getClassCName(), (*it)->getCName(), (*it)); | 
|---|
| 273 |     } | 
|---|
| 274 |   } | 
|---|
| 275 | } | 
|---|
| 276 |  | 
|---|
| 277 |  | 
|---|
| 278 | /** | 
|---|
| 279 |  * @brief prints out debug output about all Lists | 
|---|
| 280 |  * @param level: | 
|---|
| 281 |  *  0: list number of ClassList and general info. | 
|---|
| 282 |  *  1: 0+List ObjectLists and how many object. | 
|---|
| 283 |  *  2: 1+List ObjectLists entries, and information about Objects. | 
|---|
| 284 |  */ | 
|---|
| 285 | void ObjectListBase::debugAll(unsigned int level) | 
|---|
| 286 | { | 
|---|
| 287 |   printf("Listing all %d ObjectLists \n", ObjectListBase::_classesByID->size()); | 
|---|
| 288 |  | 
|---|
| 289 |   for (NameMap::const_iterator it = ObjectListBase::_classesByName->begin(); | 
|---|
| 290 |        it != ObjectListBase::_classesByName->end(); | 
|---|
| 291 |        ++it) | 
|---|
| 292 |     (*it).second->debug(level); | 
|---|
| 293 | } | 
|---|
| 294 |  | 
|---|
| 295 |  | 
|---|
| 296 |  | 
|---|
| 297 | /** | 
|---|
| 298 |  * @brief Converts an ID into a ClassName String. | 
|---|
| 299 |  * @param classID The ID to convert. | 
|---|
| 300 |  * @return The ClassName or an empty string if the ID was not found. | 
|---|
| 301 |  */ | 
|---|
| 302 | const std::string& ObjectListBase::IDToString(int classID) | 
|---|
| 303 | { | 
|---|
| 304 |   const ObjectListBase* const base = ObjectListBase::getObjectList(classID); | 
|---|
| 305 |  | 
|---|
| 306 |   if (base != NULL) | 
|---|
| 307 |     return base->name(); | 
|---|
| 308 |   else | 
|---|
| 309 |   { | 
|---|
| 310 |     static std::string empty; | 
|---|
| 311 |     return empty; | 
|---|
| 312 |   } | 
|---|
| 313 | } | 
|---|
| 314 |  | 
|---|
| 315 |  | 
|---|
| 316 | /** | 
|---|
| 317 |  * @brief Converts a String into an ID | 
|---|
| 318 |  * @param className the Name of the Class to search for | 
|---|
| 319 |  * @return The Classes ID if found, -1 otherwise. | 
|---|
| 320 |  */ | 
|---|
| 321 | int ObjectListBase::StringToID(const std::string& className) | 
|---|
| 322 | { | 
|---|
| 323 |   const ObjectListBase* const base = ObjectListBase::getObjectList(className); | 
|---|
| 324 |  | 
|---|
| 325 |   if (base != NULL) | 
|---|
| 326 |     return base->id(); | 
|---|
| 327 |   else | 
|---|
| 328 |     return -1; | 
|---|
| 329 | } | 
|---|
| 330 |  | 
|---|
| 331 |  | 
|---|
| 332 | /** | 
|---|
| 333 |  * replace all ids. list must contain all (and no more) ids | 
|---|
| 334 |  * @param str2id list: string -> newId | 
|---|
| 335 |  */ | 
|---|
| 336 | void ObjectListBase::replaceIDMap( const std::map< std::string, int >& str2id ) | 
|---|
| 337 | { | 
|---|
| 338 |   if ( str2id.size() != _classesByID->size() ) | 
|---|
| 339 |   { | 
|---|
| 340 |     assert( false && "size of str2id does not match" ); | 
|---|
| 341 |   } | 
|---|
| 342 |  | 
|---|
| 343 |   IDMap * map = new IDMap(); | 
|---|
| 344 |  | 
|---|
| 345 |   std::map< std::string, int >::const_iterator it; | 
|---|
| 346 |   for ( it = str2id.begin(); it != str2id.end(); it++ ) | 
|---|
| 347 |   { | 
|---|
| 348 |     assert( _classesByName->find( it->first ) != _classesByName->end() ); | 
|---|
| 349 |     (*map)[ it->second ] =  (*_classesByName)[it->first]; | 
|---|
| 350 |     (*map)[ it->second ]->_id = it->second; | 
|---|
| 351 |   } | 
|---|
| 352 |  | 
|---|
| 353 |   delete _classesByID; | 
|---|
| 354 |   _classesByID = map; | 
|---|
| 355 | } | 
|---|
| 356 |  | 
|---|
| 357 | /** | 
|---|
| 358 |  * | 
|---|
| 359 |  * @return | 
|---|
| 360 |  */ | 
|---|
| 361 | std::map< std::string, int > * ObjectListBase::createStrToId( ) | 
|---|
| 362 | { | 
|---|
| 363 |   std::map< std::string, int > * res = new std::map< std::string, int >(); | 
|---|
| 364 |  | 
|---|
| 365 |   NameMap::const_iterator it; | 
|---|
| 366 |   for ( it = _classesByName->begin(); it != _classesByName->end(); it++ ) | 
|---|
| 367 |   { | 
|---|
| 368 |     IDMap::const_iterator it2; | 
|---|
| 369 |     int id = -1; | 
|---|
| 370 |     for ( it2 = _classesByID->begin(); it2 != _classesByID->end(); it2++ ) | 
|---|
| 371 |     { | 
|---|
| 372 |       if ( it->second == it2->second ) | 
|---|
| 373 |       { | 
|---|
| 374 |         id = it2->first; | 
|---|
| 375 |         break; | 
|---|
| 376 |       } | 
|---|
| 377 |     } | 
|---|
| 378 |  | 
|---|
| 379 |     assert( id != -1 ); | 
|---|
| 380 |     (*res)[ it->first ] = id; | 
|---|
| 381 |   } | 
|---|
| 382 |  | 
|---|
| 383 |   return res; | 
|---|
| 384 | } | 
|---|