00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef USE_PCH
00017 #include "sys.h"
00018 #include <cassert>
00019 #include <fstream>
00020 #include <iterator>
00021 #include <libxml/xmlmemory.h>
00022 #include <libxml/parser.h>
00023 #include "debug.h"
00024 #endif
00025
00026 #include "PersistXML.h"
00027
00028 PersistXML::PersistXML(void) : M_openmode(not_open)
00029 {
00030 Dout(dc::persist, "PersistXML::PersistXML(void) is called.");
00031 }
00032
00033 PersistXML::~PersistXML()
00034 {
00035 Dout(dc::persist, "PersistXML::~PersistXML() is called.");
00036 if (M_openmode != not_open)
00037 close();
00038 }
00039
00040
00041 void PersistXML::parse_archive(void)
00042 {
00043 M_doc = xmlParseFile(M_archivename.c_str());
00044
00045
00046 if (!M_doc)
00047 throw xml_parse_error("Document not parsed successfully.");
00048 M_cur = xmlDocGetRootElement(M_doc);
00049 if (!M_cur)
00050 {
00051 xmlFreeDoc(M_doc);
00052 throw xml_parse_error("Empty document.");
00053 }
00054 if (xmlStrcmp(M_cur->name, (xmlChar const*) "archive"))
00055 {
00056 xmlFreeDoc(M_doc);
00057 throw xml_parse_error("Document of the wrong type, root node isn't <archive>.");
00058 }
00059
00060
00061 M_cur = M_cur->xmlChildrenNode;
00062 }
00063
00064 void PersistXML::open(std::string filename, openmode_type mode)
00065 {
00066 Dout(dc::persist, "PersistXML::open(\"" << filename << "\", " << mode << ") is called.");
00067 assert(M_openmode == not_open);
00068 assert(mode == store || mode == load);
00069 M_archivename = filename;
00070 if (mode == store)
00071 {
00072 M_archive.open(filename.c_str(), std::ios_base::out);
00073 M_archive << "<?xml version=\"1.0\"?>\n";
00074 M_archive << M_indent++ << "<archive>\n";
00075 }
00076 else
00077 parse_archive();
00078 M_openmode = mode;
00079 }
00080
00081 void PersistXML::close(void)
00082 {
00083 Dout(dc::persist, "PersistXML::close() is called.");
00084 assert(M_openmode != not_open);
00085 if (M_openmode == store)
00086 M_archive << --M_indent << "</archive>" << std::endl;
00087 else
00088 xmlFreeDoc(M_doc);
00089 M_archive.close();
00090 M_openmode = not_open;
00091 }
00092
00093 bool valid_label(std::string const& label)
00094 {
00095 if (label.size() == 0)
00096 return false;
00097 char first_char = label[0];
00098 if (first_char != '_' && !std::isalpha(first_char))
00099 return false;
00100 if (label.size() >= 3 &&
00101 std::tolower(first_char) == 'x' &&
00102 std::tolower(label[1]) == 'm' &&
00103 std::tolower(label[2]) == 'l')
00104 return false;
00105 std::string::const_iterator iter = label.begin();
00106 while (++iter != label.end())
00107 {
00108 char next_character = *iter;
00109 if (!std::isalpha(next_character) && !std::isdigit(next_character) && !std::ispunct(next_character))
00110 return false;
00111 }
00112 return true;
00113 }
00114
00115 template<>
00116 void PersistXML::write_escaped(char const& c)
00117 {
00118 switch (c)
00119 {
00120 default:
00121 M_archive.put(c);
00122 break;
00123 case '<':
00124 M_archive << "<";
00125 break;
00126 case '>':
00127 M_archive << ">";
00128 break;
00129 case '&':
00130 M_archive << "&";
00131 break;
00132 case '"':
00133 M_archive << """;
00134 break;
00135 case '\'':
00136 M_archive << "'";
00137 break;
00138 }
00139 }
00140
00141 template<>
00142 void PersistXML::write_escaped(std::string const& builtin)
00143 {
00144 std::stringstream str;
00145 str << builtin;
00146 std::istreambuf_iterator<char> const end;
00147 for (std::istreambuf_iterator<char> iter(str); iter != end; ++iter)
00148 write_escaped(*iter);
00149 }
00150