diff options
Diffstat (limited to 'Source/cmCableData.cxx')
-rw-r--r-- | Source/cmCableData.cxx | 190 |
1 files changed, 141 insertions, 49 deletions
diff --git a/Source/cmCableData.cxx b/Source/cmCableData.cxx index 15954b9..02fd0f6 100644 --- a/Source/cmCableData.cxx +++ b/Source/cmCableData.cxx @@ -16,104 +16,196 @@ #include "cmCableData.h" #include "cmCacheManager.h" +#include "cmCablePackageCommand.h" /** - * Free all data that was stored here. + * The cmCableData instance is owned by one cmCableCommand, which is given + * to this constructor. + */ +cmCableData::cmCableData(const cmCableCommand* owner): + m_Owner(owner), + m_Indentation(0), + m_Package(NULL), + m_PackageNamespaceDepth(0) +{ + this->OpenOutputFile("cable_config.xml"); +} + + +/** + * Free all data that was stored here. Also close the output file. */ cmCableData::~cmCableData() { - for(OutputFiles::iterator i = m_OutputFiles.begin(); - i != m_OutputFiles.end(); ++i) + // End last package, if any. + this->EndPackage(); + + // Finish up the output file. + this->CloseOutputFile(); +} + + +/** + * Open the configuration output file with the given name. This + * writes the configuration header. + */ +void cmCableData::OpenOutputFile(const std::string& name) +{ + m_OutputFile.open(name.c_str()); + + if(m_OutputFile) { - delete i->second; + this->WriteConfigurationHeader(); } } /** - * The constructor attempts to open the file for writing. + * Close the configuration output file. This writes the configuration + * footer. */ -cmCableData::OutputFile -::OutputFile(std::string file, const cmCableCommand* command): - m_FileStream(file.c_str()), - m_FirstReferencingCommand(command), - m_LastReferencingCommand(command) +void cmCableData::CloseOutputFile() { - if(!m_FileStream) + if(m_OutputFile) { - cmSystemTools::Error("Error can not open for write: ", file.c_str()); + this->WriteConfigurationFooter(); + m_OutputFile.close(); } } /** - * Destructor closes the file, if it was open. + * Write a CABLE configuration file header. */ -cmCableData::OutputFile -::~OutputFile() +void cmCableData::WriteConfigurationHeader() { - if(m_FileStream) - m_FileStream.close(); + m_OutputFile << m_Indentation << "<?xml version=\"1.0\"?>" << std::endl + << m_Indentation << "<CableConfiguration>" << std::endl; + this->Indent(); } /** - * Get the output stream associated with this OutputFile. + * Write a CABLE configuration file footer. */ -std::ostream& -cmCableData::OutputFile -::GetStream() +void cmCableData::WriteConfigurationFooter() { - return m_FileStream; + this->Unindent(); + m_OutputFile << m_Indentation << "</CableConfiguration>" << std::endl; } +/** + * Print indentation spaces. + */ void -cmCableData::OutputFile -::SetLastReferencingCommand(const cmCableCommand* command) +cmCableData::Indentation +::Print(std::ostream& os) const +{ + if(m_Indent <= 0) + { return; } + + // Use blocks of 8 spaces to speed up big indents. + unsigned int blockCount = m_Indent >> 3; + unsigned int singleCount = m_Indent & 7; + while(blockCount-- > 0) + { + os << " "; + } + while(singleCount-- > 0) + { + os << " "; + } +} + + +/** + * Open a namespace with the given name. + */ +void cmCableData::OpenNamespace(const std::string& name) { - m_LastReferencingCommand = command; + m_NamespaceStack.push_back(name); } -bool -cmCableData::OutputFile -::FirstReferencingCommandIs(const cmCableCommand* command) const +/** + * Close the current namespace, checking whether it has the given name. + */ +void cmCableData::CloseNamespace(const std::string& name) { - return (m_FirstReferencingCommand == command); + if(m_NamespaceStack.empty()) + { + cmSystemTools::Error("Unbalanced close-namespace = ", name.c_str()); + return; + } + if(m_NamespaceStack.back() != name) + { + cmSystemTools::Error("Wrong name on close-namespace = ", name.c_str()); + } + + // If this closes the namespace where the current package was opened, + // the package must end as well. + if(m_Package && (m_PackageNamespaceDepth == m_NamespaceStack.size())) + { + this->EndPackage(); + } + + m_NamespaceStack.pop_back(); } -bool -cmCableData::OutputFile -::LastReferencingCommandIs(const cmCableCommand* command) const +/** + * Begin a new package definition. If there is a current one, it + * will be ended. + */ +void cmCableData::BeginPackage(cmCablePackageCommand* command) { - return (m_LastReferencingCommand == command); + // Close the current package, if any. + this->EndPackage(); + + // Open this package. + m_Package = command; + + // Save the package's opening namespace depth for later verification + // on the end of the package. + m_PackageNamespaceDepth = m_NamespaceStack.size(); } /** - * Get the OutputFile for the file with the given name. Automatically - * maintains first and last referencing commands. + * End a package definition. */ -cmCableData::OutputFile* -cmCableData::GetOutputFile(const std::string& name, - const cmCableCommand* command) +void cmCableData::EndPackage() { - OutputFiles::iterator f = m_OutputFiles.find(name); - // If the file hasn't yet been opened, create an entry for it. - if(f == m_OutputFiles.end()) + // Make sure we have an open package. + if(!m_Package) { - OutputFile* outputFile = new OutputFile(name, command); - m_OutputFiles[name] = outputFile; - - return outputFile; + return; } - // The file has already been opened. Set the command as the last - // referencing command. - f->second->SetLastReferencingCommand(command); + // Make sure the namespace nesting depth matches the opening depth + // of the package. + if(m_PackageNamespaceDepth != m_NamespaceStack.size()) + { + cmSystemTools::Error("Package ended at different namespace depth than" + "it was created!", ""); + } + // Write out the package's footer. + m_Package->WritePackageFooter(); - return f->second; + // Done with the package. + m_Package = NULL; +} + + +/** + * Simplify indentation printing by allowing Indentation objects to be added + * to streams. + */ +std::ostream& operator<<(std::ostream& os, + const cmCableData::Indentation& indent) +{ + indent.Print(os); + return os; } |