📄 class.cc
字号:
//// class.cc//// Copyright (C) 1996 Limit Point Systems, Inc.//// Author: Curtis Janssen <cljanss@limitpt.com>// Maintainer: LPS//// This file is part of the SC Toolkit.//// The SC Toolkit is free software; you can redistribute it and/or modify// it under the terms of the GNU Library General Public License as published by// the Free Software Foundation; either version 2, or (at your option)// any later version.//// The SC Toolkit 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 Library General Public License for more details.//// You should have received a copy of the GNU Library General Public License// along with the SC Toolkit; see the file COPYING.LIB. If not, write to// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.//// The U.S. Government is granted a limited license as per AL 91-7.//#ifdef __GNUG__#pragma implementation#endif#ifdef HAVE_CONFIG_H#include <scconfig.h>#endif#include <string>#include <stdlib.h>#include <string.h>#if defined(HAVE_DLFCN_H)#include <dlfcn.h>#endif // HAVE_DLFCN_H#include <util/misc/formio.h>#include <util/class/class.h>using namespace std;using namespace sc;std::map<std::string,ClassDescP>* ClassDesc::all_ = 0;std::map<type_info_key,ClassDescP>* ClassDesc::type_info_all_ = 0;char * ClassDesc::classlib_search_path_ = 0;std::set<std::string>* ClassDesc::unresolved_parents_ = 0;/////////////////////////////////////////////////////////////////ParentClass::ParentClass(ClassDesc*classdesc,Access access,int is_virtual): _access(access), _is_virtual(is_virtual), _classdesc(classdesc){}ParentClass::ParentClass(const ParentClass&p): _access(p._access), _is_virtual(p._is_virtual), _classdesc(p._classdesc){}ParentClass::~ParentClass(){}int ParentClass::is_virtual() const{ return _is_virtual;}const ClassDesc* ParentClass::classdesc() const{ return _classdesc;}void ParentClass::change_classdesc(ClassDesc*n){ _classdesc = n;}/////////////////////////////////////////////////////////////////ParentClasses::ParentClasses(): _n(0), _classes(0){}voidParentClasses::init(const char* parents){ // if parents is empty then we are done if (!parents || strlen(parents) == 0) return; char* tokens = ::strcpy(new char[strlen(parents)+1],parents); const char* whitesp = "\t\n,() "; char* token; int is_virtual = 0; ParentClass::Access access = ParentClass::Private; for (token = ::strtok(tokens,whitesp); token; token = ::strtok(0,whitesp)) { if (!strcmp(token,"virtual")) { is_virtual = 1; } else if (!strcmp(token,"public")) { access = ParentClass::Public; } else if (!strcmp(token,"protected")) { access = ParentClass::Protected; } else if (!strcmp(token,"private")) { access = ParentClass::Private; } else { std::string parentkey(token); // if the parents class desc does not exist create a temporary // the temporary will be incorrect,because it does not have the // parent's parents if (ClassDesc::all().find(parentkey) == ClassDesc::all().end()) { ClassDesc *tmp_classdesc = new ClassDesc(token); ClassDesc::all()[parentkey] = tmp_classdesc; if (ClassDesc::unresolved_parents_ == 0) { ClassDesc::unresolved_parents_ = new std::set<std::string>; } ClassDesc::unresolved_parents_->insert(token); } ParentClass* p = new ParentClass(ClassDesc::all()[parentkey], access, is_virtual); add(p); access = ParentClass::Private; is_virtual = 0; } } delete[] tokens; }ParentClasses::~ParentClasses(){ for (int i=0; i<_n; i++) delete _classes[i]; if (_classes) delete[] _classes; _classes = 0; _n = 0;}voidParentClasses::add(ParentClass*p){ ParentClass** newpp = new ParentClass*[_n+1]; for (int i=0; i<_n; i++) newpp[i] = _classes[i]; newpp[_n] = p; _n++; delete[] _classes; _classes = newpp;}voidParentClasses::change_parent(ClassDesc*oldcd,ClassDesc*newcd){ for (int i=0; i<_n; i++) { if (parent(i).classdesc() == oldcd) parent(i).change_classdesc(newcd); }}////////////////////////////////////////////////////////////////////////type_info_key&type_info_key::operator=(const type_info_key&t){ ti_ = t.ti_; return *this;}inttype_info_key::operator==(const type_info_key&t) const{ if (!ti_ && !t.ti_) return 1; if (!ti_ || !t.ti_) return 0; return *ti_ == *t.ti_;}inttype_info_key::operator<(const type_info_key&t) const{ if (!ti_ && !t.ti_) return 0; if (!ti_) return 0; if (!t.ti_) return 1; return ti_->before(*t.ti_);}inttype_info_key::cmp(const type_info_key&t) const{ if (*this == t) return 0; if (*this < t) return -1; return 1;}////////////////////////////////////////////////////////////////////////ClassDesc::ClassDesc(const type_info &ti, const char* name, int version, const char* parents, DescribedClass* (*ctor)(), DescribedClass* (*keyvalctor)(const Ref<KeyVal>&), DescribedClass* (*stateinctor)(StateIn&) ){ if (!type_info_all_) { type_info_all_ = new std::map<type_info_key,ClassDescP>; } type_info_key key(&ti); if (type_info_all_->find(key) != type_info_all_->end()) { ExEnv::err0() << indent << "ERROR: duplicate ClassDesc detected for class " << name << " type_info name = " << ti.name() << endl; abort(); } else { (*type_info_all_)[key] = this; } // test the version number to see if it is valid if (version <= 0) { ExEnv::errn() << "ERROR: ClassDesc ctor: version <= 0" << endl; exit(1); } init(name,version,parents,ctor,keyvalctor,stateinctor);}ClassDesc::ClassDesc(const char* name){ init(name, 0);}voidClassDesc::init(const char* name, int version, const char* parents, DescribedClass* (*ctor)(), DescribedClass* (*keyvalctor)(const Ref<KeyVal>&), DescribedClass* (*stateinctor)(StateIn&)){ classname_ = 0; version_ = version; children_ = 0; ctor_ = ctor; keyvalctor_ = keyvalctor; stateinctor_ = stateinctor; // make sure that the static members have been initialized if (!all_) { all_ = new std::map<std::string,ClassDescP>; const char* tmp = getenv("LD_LIBRARY_PATH"); if (tmp) { // Needed for misbehaving getenv's. if (strncmp(tmp, "LD_LIBRARY_PATH=", 16) == 0) { tmp = ::strchr(tmp,'='); tmp++; } } else tmp = "."; classlib_search_path_ = ::strcpy(new char[strlen(tmp)+1],tmp); } // see if I'm already in the list ClassDesc *me = name_to_class_desc(name); int temp_copy_present = 0; if (me && me->version() != 0) { ExEnv::err0() << indent << "ERROR: ClassDesc ctor: ClassDesc already initialized for " << name << endl; abort(); } else if (me) { temp_copy_present = 1; } parents_.init(parents); if (!temp_copy_present && name_to_class_desc(name)) { // I wasn't in the list before, but am in it now ExEnv::err0() << indent << "ERROR: ClassDesc ctor: inheritance loop detected for " << name << endl; abort(); } classname_ = ::strcpy(new char[strlen(name)+1],name); std::string key(name); // let each of the parents know that this is a child for (int i=0; i<parents_.n(); i++) { std::string parentkey(parents_[i].classdesc()->name()); if (!(*all_)[parentkey]->children_) (*all_)[parentkey]->children_ = new std::set<std::string>; // let the parents know about the child ((*all_)[parentkey]->children_)->insert(key); } // if this class is aleady in all_, then it was put there by a child // preserve children info, destroy the old entry, and put this there if (all_->find(key) != all_->end()) { children_ = (*all_)[key]->children_; (*all_)[key]->children_ = 0; if (!children_) { ExEnv::err0() << indent << "ERROR: ClassDesc: inconsistency in initialization for "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -