bsod: use simple XML generator
[enigma2.git] / main / xmlgenerator.cpp
diff --git a/main/xmlgenerator.cpp b/main/xmlgenerator.cpp
new file mode 100644 (file)
index 0000000..eb4f157
--- /dev/null
@@ -0,0 +1,188 @@
+#include <fstream>
+#include <lib/base/eerror.h>
+#include "xmlgenerator.h"
+
+XmlGenerator::XmlGenerator(FILE *f) : m_file(f), m_indent(true), m_level(0)
+{
+       ::fprintf(m_file, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+}
+
+XmlGenerator::~XmlGenerator()
+{
+}
+
+void XmlGenerator::vprint(const char *fmt, va_list ap, bool newline)
+{
+       unsigned int i;
+
+       if (m_indent)
+               for (i = 0; i < m_level; i++)
+                       ::fprintf(m_file, "\t");
+
+       ::vfprintf(m_file, fmt, ap);
+
+       if (newline)
+               ::fprintf(m_file, "\n");
+}
+
+void XmlGenerator::print(const char *fmt, ...)
+{
+       va_list ap;
+
+       ::va_start(ap, fmt);
+       vprint(fmt, ap, false);
+       ::va_end(ap);
+}
+
+void XmlGenerator::printLn(const char *fmt, ...)
+{
+       va_list ap;
+
+       ::va_start(ap, fmt);
+       vprint(fmt, ap, true);
+       ::va_end(ap);
+}
+
+void XmlGenerator::open(const std::string &tag, bool newline)
+{
+       if (newline) {
+               printLn("<%s>", tag.c_str());
+       } else {
+               print("<%s>", tag.c_str());
+               m_indent = false;
+       }
+
+       m_tags.push(tag);
+       m_level++;
+}
+
+void XmlGenerator::open(const std::string &tag)
+{
+       open(tag, true);
+}
+
+void XmlGenerator::close()
+{
+       ASSERT(!m_tags.empty());
+       ASSERT(m_level > 0);
+       m_level--;
+
+       printLn("</%s>", m_tags.top().c_str());
+       m_indent = true;
+
+       m_tags.pop();
+}
+
+void XmlGenerator::comment(const std::string &str)
+{
+       printLn("<!-- %s -->", str.c_str());
+}
+
+void XmlGenerator::commentFromErrno(const std::string &tag)
+{
+       open(tag);
+       comment(strerror(errno));
+       close();
+}
+
+std::string XmlGenerator::cDataEscape(const std::string &str)
+{
+       const std::string search = "]]>";
+       const std::string replace = "]]]]><![CDATA[>";
+       std::string ret;
+       size_t pos = 0, opos;
+
+       for (;;) {
+               opos = pos;
+               pos = str.find(search, opos);
+               if (pos == std::string::npos)
+                       break;
+               ret.append(str, opos, pos - opos);
+               ret.append(replace);
+               pos += search.size();
+       }
+
+       ret.append(str, opos, std::string::npos);
+       return ret;
+}
+
+void XmlGenerator::cDataFromCmd(const std::string &tag, const std::string &cmd)
+{
+       FILE *pipe = ::popen(cmd.c_str(), "re");
+
+       if (pipe == 0) {
+               commentFromErrno(tag);
+               return;
+       }
+
+       std::string result;
+       char *lineptr = NULL;
+       size_t n = 0;
+
+       for (;;) {
+               ssize_t ret = ::getline(&lineptr, &n, pipe);
+               if (ret < 0)
+                       break;
+               result.append(lineptr, ret);
+       }
+
+       if (lineptr)
+               ::free(lineptr);
+
+       ::pclose(pipe);
+       cDataFromString(tag, result);
+}
+
+void XmlGenerator::cDataFromFile(const std::string &tag, const std::string &filename, const char *filter)
+{
+       std::ifstream in(filename.c_str());
+       std::string line;
+       std::string content;
+
+       if (!in.good()) {
+               commentFromErrno(tag);
+               return;
+       }
+
+       while (std::getline(in, line))
+               if (!filter || !line.find(filter))
+                       content += line + '\n';
+
+       in.close();
+       cDataFromString(tag, content);
+}
+
+void XmlGenerator::cDataFromString(const std::string &tag, const std::string &str)
+{
+       bool indent = false;
+
+       open(tag);
+       printLn("<![CDATA[");
+       std::swap(m_indent, indent);
+       print("%s", cDataEscape(str).c_str());
+       printLn("]]>");
+       std::swap(m_indent, indent);
+       close();
+}
+
+void XmlGenerator::string(const std::string &tag, const std::string &str)
+{
+       open(tag, false);
+       print("%s", str.c_str());
+       close();
+}
+
+void XmlGenerator::stringFromFile(const std::string &tag, const std::string &filename)
+{
+       std::ifstream in(filename.c_str());
+       std::string line;
+
+       if (!in.good()) {
+               commentFromErrno(tag);
+               return;
+       }
+
+       std::getline(in, line);
+       in.close();
+       string(tag, line);
+}