// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdpch.h" #include "reflect.h" // Yoyo: Act like a singleton, else registerClass may crash. CReflectSystem::TClassMap *CReflectSystem::_ClassMap= NULL; // hack to register the root class at startup static const struct CRootReflectableClassRegister { CRootReflectableClassRegister() { TReflectedProperties props; CReflectSystem::registerClass("CReflectable", "", props); } } _RootReflectableClassRegisterInstance; //=================================================================================== // release memory void CReflectSystem::release() { delete _ClassMap; _ClassMap = NULL; } //=================================================================================== void CReflectSystem::registerClass(const std::string &className, const std::string &parentName, const TReflectedProperties properties) { if(!_ClassMap) _ClassMap= new TClassMap; TClassMap::const_iterator it = _ClassMap->find(className); if (it != _ClassMap->end()) { nlerror("CReflectSystem::registerClass : Class registered twice : %s!", className.c_str()); } CClassInfo &ci = (*_ClassMap)[className]; ci.Properties = properties; ci.ClassName = className; for(uint k = 0; k < ci.Properties.size(); ++k) { ci.Properties[k].ParentClass = &ci; } if (parentName.empty()) { ci.ParentClass = NULL; } else { it = _ClassMap->find(parentName); if (it == _ClassMap->end()) { nlerror("CReflectSystem::registerClass : Parent class %s not found", parentName.c_str()); } ci.ParentClass = &(it->second); } } //=================================================================================== const CReflectedProperty *CReflectSystem::getProperty(const std::string &className, const std::string &propertyName, bool dspWarning) { if(!_ClassMap) _ClassMap= new TClassMap; TClassMap::const_iterator it = _ClassMap->find(className); if (it == _ClassMap->end()) { nlwarning("CReflectSystem::getProperty : Unkwown class : %s", className.c_str()); return NULL; } const CClassInfo *ci = &it->second; while (ci) { // Linear search should suffice for now for(uint k = 0; k < ci->Properties.size(); ++k) { if (ci->Properties[k].Name == propertyName) { return &(ci->Properties[k]); } } // search in parent ci = ci->ParentClass; } //\ TODO nico : possible optimization : instead of going up in the parents when // searching for a property, it would be simpler to concatenate properties // from parent class at registration. // All that would be left at the end would be a hash_map of properties ... if(dspWarning) nlwarning("CReflectSystem::getProperty : %s is not a property of class : %s", propertyName.c_str(), className.c_str()); return NULL; } //=================================================================================== const CClassInfo *CReflectable::getClassInfo() { if (!CReflectSystem::getClassMap()) return NULL; // TODO nico : a possible optimization would be to use the address of the static function // 'getReflectedProperties' as a key into the CClassInfo map. This pointer uniquely identify // classes that export properties CReflectSystem::TClassMap::const_iterator it = CReflectSystem::getClassMap()->find(this->getReflectedClassName()); if (it == CReflectSystem::getClassMap()->end()) { return NULL; } return &(it->second); } //=================================================================================== const CReflectedProperty *CReflectable::getReflectedProperty(const std::string &propertyName, bool dspWarning) const { return CReflectSystem::getProperty(this->getReflectedClassName(), propertyName, dspWarning); }