summaryrefslogtreecommitdiffstats
path: root/Source/cmCableData.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmCableData.cxx')
-rw-r--r--Source/cmCableData.cxx190
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;
}