📄 base.cxx
字号:
CdlLoadableBody::find_relative_file(std::string filename, std::string dirname) const{ CYG_REPORT_FUNCNAME("CdlLoadable::find_relative_file"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != filename); // These variable names should be kept in step with CdlBuildable::update_all_build_info() interp->set_variable("::cdl_topdir", get_toplevel()->get_directory()); interp->set_variable("::cdl_pkgdir", directory); interp->set_variable("::cdl_prefdir", dirname); interp->set_variable("::cdl_target", filename); std::string result; int tmp = interp->eval(find_relative_file_script, result); if (tmp != TCL_OK) { result = ""; } // Replace any backslashes in the repository with forward slashes. // The latter are used throughout the library // NOTE: this is not i18n-friendly. for (unsigned int i = 0; i < result.size(); i++) { if ('\\' == result[i]) { result[i] = '/'; } } CYG_REPORT_RETURN(); return result;}static char has_subdirectory_script[] = " \n\set dirname [file join $::cdl_topdir $::cdl_pkgdir $::cdl_target] \n\if {[file isdirectory $dirname] == 0} { \n\ return 0 \n\} \n\return 1 \n\";boolCdlLoadableBody::has_subdirectory(std::string name) const{ CYG_REPORT_FUNCNAMETYPE("CdlLoadable::has_subdirectory", "result %d"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC("" != name); bool result = false; interp->set_variable("::cdl_topdir", get_toplevel()->get_directory()); interp->set_variable("::cdl_pkgdir", directory); interp->set_variable("::cdl_target", name); std::string tcl_result; int tmp = interp->eval(has_subdirectory_script, tcl_result); if ((TCL_OK == tmp) && ("1" == tcl_result)) { result = true; } CYG_REPORT_RETVAL(result); return result;}//}}}//{{{ Misc // ----------------------------------------------------------------------------std::stringCdlLoadableBody::get_class_name() const{ CYG_REPORT_FUNCNAME("CdlLoadable::get_class_name"); CYG_PRECONDITION_THISC(); CYG_REPORT_RETURN(); return "loadable";}//}}}//{{{ check_this() // ----------------------------------------------------------------------------boolCdlLoadableBody::check_this(cyg_assert_class_zeal zeal) const{ if (CdlLoadableBody_Magic != cdlloadablebody_cookie) { return false; } CYGDBG_MEMLEAK_CHECKTHIS(); if ((zeal == cyg_extreme) || (zeal == cyg_thorough)) { std::vector<CdlNode>::const_iterator node_i; for (node_i = owned.begin(); node_i != owned.end(); node_i++) { if ((!(*node_i)->check_this(cyg_quick)) || ((*node_i)->get_owner() != this)) { return false; } } } return CdlContainerBody::check_this(zeal);}//}}}//}}}//{{{ CdlToplevelBody //{{{ Constructor // ----------------------------------------------------------------------------// A toplevel is a container without a parent or owner. It keeps track// of all the names in the hierarchy, thus guaranteeing uniqueness and// providing a quick lookup facility.//// The member functions add_node() and remove_node() are the only// way of modifying the hierarchy. Adding a node with a zero parent// means adding it to a special container, Orphans.//// An interpreter object must be created explicitly, preventing// toplevel objects from being statically allocated (although// it is possible to play tricks with utility classes...)// There are too many possible error conditions when creating// an interpreter, so this should not happen until the world// is ready to deal with such errors.CdlToplevelBody::CdlToplevelBody(CdlInterpreter interp_arg, std::string directory_arg) : CdlContainerBody(){ CYG_REPORT_FUNCNAME("CdlToplevel:: constructor"); CYG_REPORT_FUNCARG2XV(this, interp_arg); CYG_PRECONDITION_CLASSC(interp_arg); // The STL containers will take care of themselves. interp = interp_arg; directory = directory_arg; transaction = 0; // A toplevel is always active, override the default setting for a node active = true; // Make the object valid before creating the orphans container. orphans = 0; description = ""; cdltoplevelbody_cookie = CdlToplevelBody_Magic; // Arguably creating the orphans container should be left until // it is actually needed. The advantage of creating it at the // start is that it will appear in a fixed location in the contents, // right at the start. Arguably the end would be better, but the // end can move as loadables get added and removed. // // The GUI code will probably want to ignore any empty // containers that are not valuables and not user-visible. orphans = new CdlContainerBody("orphans"); add_node(0, this, orphans); // Let the interpreter know about its owning toplevel, as well as // vice versa. interp->set_toplevel(this); // The orphans container needs to be active as well. orphans->active = true; CYGDBG_MEMLEAK_CONSTRUCTOR(); CYG_POSTCONDITION_THISC(); CYG_REPORT_RETURN();}//}}}//{{{ Destructor // ----------------------------------------------------------------------------// The toplevel should have been mostly cleared already, by the// appropriate derived class. Without any loadables there should not// be any conflicts. It is necessary to clean up the orphans// container, since that was created by the CdlToplevel constructor.// If there are any other special nodes then these should have been// cleared by higher level code.CdlToplevelBody::~CdlToplevelBody(){ CYG_REPORT_FUNCNAME("CdlToplevel:: destructor"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC(0 == loadables.size()); CYG_PRECONDITIONC(0 == conflicts.size()); CYG_PRECONDITIONC(0 == structural_conflicts.size()); CYG_PRECONDITIONC(0 == transaction); CYG_PRECONDITIONC(0 != orphans); this->remove_node_from_toplevel(orphans); CdlToplevelBody::remove_node(0, this, orphans); delete orphans; orphans = 0; CYG_PRECONDITIONC(0 == contents.size()); cdltoplevelbody_cookie = CdlToplevelBody_Magic; description = ""; limbo.clear(); unsupported_savefile_toplevel_strings.clear(); unsupported_savefile_commands.clear(); unsupported_savefile_subcommands.clear(); // Since the interpreter is not created by the toplevel, it is // not destroyed with the toplevel either. This leaves a potential // big memory leak in application code. interp = 0; CYGDBG_MEMLEAK_DESTRUCTOR(); CYG_REPORT_RETURN();}//}}}//{{{ Adding and removing nodes // ----------------------------------------------------------------------------// Adding and removing a node, and changing a parent.//// These routines allow the hierarchy to be manipulated. All nodes should// exist in a hierarchy below a toplevel, except for brief periods after// construction and during destruction.//// Most nodes will belong to a loadable. An owner of 0 is allowed, for// objects internal to the library such as the orphans container.// Everything else must have an owner, and specifically a loadable owns// itself.voidCdlToplevelBody::add_node(CdlLoadable owner, CdlContainer parent, CdlNode node){ CYG_REPORT_FUNCNAME("CdlToplevel::add_node"); CYG_REPORT_FUNCARG4XV(this, owner, parent, node); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_ZERO_OR_CLASSC(owner); CYG_PRECONDITION_CLASSC(parent); CYG_PRECONDITION_CLASSC(node); // The node must not be in the hierarchy already. CYG_ASSERTC(0 == node->toplevel); CYG_ASSERTC(0 == node->owner); CYG_ASSERTC(0 == node->parent); // The node's name should be unique. Checks for that should have happened // in higher-level code. CYG_ASSERTC(lookup_table.find(node->name) == lookup_table.end()); node->toplevel = this; lookup_table[node->name] = node; node->owner = owner; if (0 != owner) { owner->owned.push_back(node); } // If the node is in fact a loadable, it should own itself and // in addition the toplevel class keeps track of its loadables // in a separate vector. if (0 != dynamic_cast<CdlLoadable>(node)) { CYG_ASSERTC(owner == dynamic_cast<CdlLoadable>(node)); this->loadables.push_back(owner); } if (0 == parent) { parent = orphans; } node->parent = parent; parent->contents.push_back(node); CYG_REPORT_RETURN();}// Removing a node from a toplevel. This is the first step in deleting// a node: the step may be undone by a call to add_node_to_toplevel(),// or completed by a call to remove_node(). Removing a node from the// toplevel involves undoing the name->node mapping. In the case// of loadables, it also involves removing the node from the toplevel's// contents and loadables containers.voidCdlToplevelBody::remove_node_from_toplevel(CdlNode node){ CYG_REPORT_FUNCNAME("CdlToplevel::remove_node_from_toplevel"); CYG_REPORT_FUNCARG2XV(this, node); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(node); CYG_ASSERTC(this == node->toplevel); CYG_ASSERTC(lookup_table[node->name] == node); node->toplevel = 0; lookup_table.erase(node->name); CdlLoadable loadable = dynamic_cast<CdlLoadable>(node); if (0 != loadable) { CYG_ASSERTC(loadable == node->owner); CYG_ASSERTC(this == node->parent); // Because remove_node_from_toplevel() is reversible, the // loadable should reappear in its old position. Hence we // had better keep track of that position. Note that // this code assumed that the remove_node and add_node // calls are exactly reversed. int i; for (i = 0; i < (int) this->contents.size(); i++) { if (this->contents[i] == node) { break; } } CYG_ASSERTC(i < (int) this->contents.size()); node->remove_node_container_position = i; this->contents.erase(this->contents.begin() + i); node->parent = 0; // It is not clear that preserving the order of the loadables // in the toplevel is useful, but it is harmless. for (i = 0; i < (int) this->loadables.size(); i++) { if (this->loadables[i] == loadable) { break; } } CYG_ASSERTC(i < (int) this->loadables.size()); loadable->remove_node_loadables_position = i; this->loadables.erase(this->loadables.begin() + i); } CYG_REPORT_RETURN();}voidCdlToplevelBody::remove_loadable_from_toplevel(CdlLoadable loadable){ CYG_REPORT_FUNCNAME("CdlToplevel::remove_loadable_from_toplevel"); CYG_REPORT_FUNCARG2XV(this, loadable); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(loadable); const std::vector<CdlNode>& contents = loadable->get_owned(); for (int i = contents.size() - 1; i >= 0; i--) { CdlToplevel toplevel = contents[i]->get_toplevel(); CYG_LOOP_INVARIANT_ZERO_OR_CLASSC(toplevel); if (0 != toplevel) { CYG_LOOP_INVARIANTC(this == toplevel); this->remove_node_from_toplevel(contents[i]); } } CYG_REPORT_RETURN();}// Re-adding a node to a toplevel. This needs to undo all of the changes// that may have been done by remove_node_from_toplevel() above.voidCdlToplevelBody::add_node_to_toplevel(CdlNode node){ CYG_REPORT_FUNCNAME("CdlToplevel::add_node_to_toplevel"); CYG_REPORT_FUNCARG2XV(this, node); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(node); CYG_ASSERTC(0 == node->toplevel); CYG_ASSERTC(0 != node->owner); CYG_ASSERTC(lookup_table.find(node->name) == lookup_table.end()); node->toplevel = this; lookup_table[node->name] = node; CdlLoadable loadable = dynamic_cast<CdlLoadable>(node); if (0 != loadable) { CYG_ASSERTC(loadable == node->owner); CYG_ASSERTC(0 == node->parent); CYG_ASSERTC(-1 != node->remove_node_container_position); CYG_ASSERTC(node->remove_node_container_position <= (int) this->contents.size()); this->contents.insert(this->contents.begin() + node->remove_node_container_position, node); node->remove_node_container_position = -1; node->parent = this; CYG_ASSERTC(-1 != loadable->remove_node_loadables_position); this->loadables.insert(this->loadables.begin() + loadable->remove_node_loadables_position, loadable); loadable->remove_node_loadables_p
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -