| /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying | 
 |    file Copyright.txt or https://cmake.org/licensing for details.  */ | 
 | #pragma once | 
 |  | 
 | #include "cmConfigure.h" // IWYU pragma: keep | 
 |  | 
 | #include <chrono> | 
 | #include <cstddef> // IWYU pragma: keep | 
 | #include <ctime> | 
 | #include <ostream> | 
 | #include <stack> | 
 | #include <string> | 
 | #include <vector> | 
 |  | 
 | #include "cmXMLSafe.h" | 
 |  | 
 | class cmXMLWriter | 
 | { | 
 | public: | 
 |   cmXMLWriter(std::ostream& output, std::size_t level = 0); | 
 |   ~cmXMLWriter(); | 
 |  | 
 |   cmXMLWriter(cmXMLWriter const&) = delete; | 
 |   cmXMLWriter& operator=(cmXMLWriter const&) = delete; | 
 |  | 
 |   void StartDocument(const char* encoding = "UTF-8"); | 
 |   void EndDocument(); | 
 |  | 
 |   void StartElement(std::string const& name); | 
 |   void EndElement(); | 
 |  | 
 |   void BreakAttributes(); | 
 |  | 
 |   template <typename T> | 
 |   void Attribute(const char* name, T const& value) | 
 |   { | 
 |     this->PreAttribute(); | 
 |     this->Output << name << "=\"" << SafeAttribute(value) << '"'; | 
 |   } | 
 |  | 
 |   void Element(const char* name); | 
 |  | 
 |   template <typename T> | 
 |   void Element(std::string const& name, T const& value) | 
 |   { | 
 |     this->StartElement(name); | 
 |     this->Content(value); | 
 |     this->EndElement(); | 
 |   } | 
 |  | 
 |   template <typename T> | 
 |   void Content(T const& content) | 
 |   { | 
 |     this->PreContent(); | 
 |     this->Output << SafeContent(content); | 
 |   } | 
 |  | 
 |   void Comment(const char* comment); | 
 |  | 
 |   void CData(std::string const& data); | 
 |  | 
 |   void Doctype(const char* doctype); | 
 |  | 
 |   void ProcessingInstruction(const char* target, const char* data); | 
 |  | 
 |   void FragmentFile(const char* fname); | 
 |  | 
 |   void SetIndentationElement(std::string const& element); | 
 |  | 
 | private: | 
 |   void ConditionalLineBreak(bool condition); | 
 |  | 
 |   void PreAttribute(); | 
 |   void PreContent(); | 
 |  | 
 |   void CloseStartElement(); | 
 |  | 
 |   static cmXMLSafe SafeAttribute(const char* value) { return { value }; } | 
 |  | 
 |   static cmXMLSafe SafeAttribute(std::string const& value) | 
 |   { | 
 |     return { value }; | 
 |   } | 
 |  | 
 |   template <typename T> | 
 |   static T SafeAttribute(T value) | 
 |   { | 
 |     return value; | 
 |   } | 
 |  | 
 |   static cmXMLSafe SafeContent(const char* value) | 
 |   { | 
 |     return cmXMLSafe(value).Quotes(false); | 
 |   } | 
 |  | 
 |   static cmXMLSafe SafeContent(std::string const& value) | 
 |   { | 
 |     return cmXMLSafe(value).Quotes(false); | 
 |   } | 
 |  | 
 |   /* | 
 |    * Convert a std::chrono::system::time_point to the number of seconds since | 
 |    * the UN*X epoch. | 
 |    * | 
 |    * It would be tempting to convert a time_point to number of seconds by | 
 |    * using time_since_epoch(). Unfortunately the C++11 standard does not | 
 |    * specify what the epoch of the system_clock must be. | 
 |    * Therefore we must assume it is an arbitrary point in time. Instead of this | 
 |    * method, it is recommended to convert it by means of the to_time_t method. | 
 |    */ | 
 |   static std::time_t SafeContent( | 
 |     std::chrono::system_clock::time_point const& value) | 
 |   { | 
 |     return std::chrono::system_clock::to_time_t(value); | 
 |   } | 
 |  | 
 |   template <typename T> | 
 |   static T SafeContent(T value) | 
 |   { | 
 |     return value; | 
 |   } | 
 |  | 
 |   std::ostream& Output; | 
 |   std::stack<std::string, std::vector<std::string>> Elements; | 
 |   std::string IndentationElement; | 
 |   std::size_t Level; | 
 |   std::size_t Indent; | 
 |   bool ElementOpen; | 
 |   bool BreakAttrib; | 
 |   bool IsContent; | 
 | }; | 
 |  | 
 | class cmXMLElement; // IWYU pragma: keep | 
 |  | 
 | class cmXMLDocument | 
 | { | 
 | public: | 
 |   cmXMLDocument(cmXMLWriter& xml) | 
 |     : xmlwr(xml) | 
 |   { | 
 |     this->xmlwr.StartDocument(); | 
 |   } | 
 |   ~cmXMLDocument() { this->xmlwr.EndDocument(); } | 
 |   cmXMLDocument(const cmXMLDocument&) = delete; | 
 |   cmXMLDocument& operator=(const cmXMLDocument&) = delete; | 
 |  | 
 | private: | 
 |   friend class cmXMLElement; | 
 |   cmXMLWriter& xmlwr; | 
 | }; | 
 |  | 
 | class cmXMLElement | 
 | { | 
 | public: | 
 |   cmXMLElement(cmXMLWriter& xml, const char* tag) | 
 |     : xmlwr(xml) | 
 |   { | 
 |     this->xmlwr.StartElement(tag); | 
 |   } | 
 |   cmXMLElement(cmXMLElement& par, const char* tag) | 
 |     : xmlwr(par.xmlwr) | 
 |   { | 
 |     this->xmlwr.StartElement(tag); | 
 |   } | 
 |   cmXMLElement(cmXMLDocument& doc, const char* tag) | 
 |     : xmlwr(doc.xmlwr) | 
 |   { | 
 |     this->xmlwr.StartElement(tag); | 
 |   } | 
 |   ~cmXMLElement() { this->xmlwr.EndElement(); } | 
 |  | 
 |   cmXMLElement(const cmXMLElement&) = delete; | 
 |   cmXMLElement& operator=(const cmXMLElement&) = delete; | 
 |  | 
 |   template <typename T> | 
 |   cmXMLElement& Attribute(const char* name, T const& value) | 
 |   { | 
 |     this->xmlwr.Attribute(name, value); | 
 |     return *this; | 
 |   } | 
 |   template <typename T> | 
 |   void Content(T const& content) | 
 |   { | 
 |     this->xmlwr.Content(content); | 
 |   } | 
 |   template <typename T> | 
 |   void Element(std::string const& name, T const& value) | 
 |   { | 
 |     this->xmlwr.Element(name, value); | 
 |   } | 
 |   void Comment(const char* comment) { this->xmlwr.Comment(comment); } | 
 |  | 
 | private: | 
 |   cmXMLWriter& xmlwr; | 
 | }; |