ircproxy The Ultimate Cyborg |
#include <PersistXML.h>
This object represents an archive to which objects can be written to if they support the serialize(PersistXML&) method.
Definition at line 95 of file PersistXML.h.
Public Types | |
enum | openmode_type { not_open, store, load } |
The open mode type of the archive. More... | |
Public Member Functions | |
PersistXML (void) | |
Construct a new persistent XML archive object. | |
~PersistXML () | |
Destruct the object. An open archive is first finalized. | |
void | open (std::string filename, openmode_type mode) |
Associate the archive with a file for either reading or writing. | |
void | close (void) |
Finalize and close the archive. | |
openmode_type | openmode (void) const |
Return the current state. | |
template<typename T> | |
void | serialize (std::string const &label, T &object) |
Serialize object using the xml tag <label></label>. | |
template<typename T> | |
void | serialize (std::string const &label, boost::shared_ptr< T > &ptr) |
Serialize the object pointed to by a boost::shared_ptr using the xml tag <label></label>. | |
template<typename T> | |
void | serialize (std::string const &label, std::vector< T > &vec) |
Serialize std::vector vec using the xml tag <label></label>. | |
template<typename T> | |
void | serialize (std::string const &label, std::list< T > &list) |
Serialize std::list list using the xml tag <label></label>. | |
template<typename KEY, typename INFO, typename COMPARE> | |
void | serialize (std::string const &label, std::map< KEY, INFO, COMPARE > &map) |
Serialize std::map map using the xml tag <label></label>. | |
template<typename T> | |
void | serialize (std::string const &label, boost::optional< T > &opt) |
Serialize boost::optional opt using the xml tag <label></label>. | |
template<typename T> | |
void | serialize_builtin (std::string const &label, T &builtin) |
Serialize builtin type builtin using the xml tag <label></label>. | |
template<> | |
void | write_escaped (char const &c) |
Write char c to archive. | |
template<> | |
void | write_escaped (std::string const &builtin) |
Write string s to archive. | |
template<> | |
void | write_escaped (unsigned char const &c) |
Write unsigned char c to archive. | |
template<> | |
void | read_data (std::stringstream &ss, std::string &s) |
Read string s from stringstream ss. | |
Protected Attributes | |
openmode_type | M_openmode |
Whether or not the archive is opened for reading or writing. | |
std::string | M_archivename |
The name of the XML file used to write the archive to disk. | |
std::fstream | M_archive |
The file stream of an open archive. | |
Indentation | M_indent |
Current XML indentation. | |
xmlDocPtr | M_doc |
XML document open for reading. | |
xmlNodePtr | M_cur |
Current node in M_doc. | |
std::stack< std::vector < xmlNodePtr > > | M_parent_nodes |
Stack with parents of current node. | |
Private Member Functions | |
void | parse_archive (void) |
Parse the archive. | |
template<typename T> | |
void | write_escaped (T const &builtin) |
Write builtin-type builtin to archive. | |
template<typename T> | |
void | read_data (std::stringstream &ss, T &builtin) |
Read builtin from stringstream ss. | |
Friends | |
class | XMLLabel |
std::ostream & | operator<< (std::ostream &os, openmode_type openmode) |
For debugging purposes. Write a PersistXML::openmode to os. |
The open mode type of the archive.
not_open | Used internally to mark that the archive is not open. |
store | Open for writing objects to the archive. |
load | Open for reading objects from the archive. |
Definition at line 98 of file PersistXML.h.
00098 { 00099 not_open, //!< Used internally to mark that the archive is not open. 00100 store, //!< Open for writing objects to the archive. 00101 load //!< Open for reading objects from the archive. 00102 };
PersistXML::PersistXML | ( | void | ) |
Construct a new persistent XML archive object.
Definition at line 28 of file PersistXML.cc.
References debug::channels::dc::persist.
00028 : M_openmode(not_open) 00029 { 00030 Dout(dc::persist, "PersistXML::PersistXML(void) is called."); 00031 }
PersistXML::~PersistXML | ( | ) |
Destruct the object. An open archive is first finalized.
Definition at line 33 of file PersistXML.cc.
References close(), M_openmode, not_open, and debug::channels::dc::persist.
00034 { 00035 Dout(dc::persist, "PersistXML::~PersistXML() is called."); 00036 if (M_openmode != not_open) 00037 close(); 00038 }
void PersistXML::open | ( | std::string | filename, | |
openmode_type | mode | |||
) |
Associate the archive with a file for either reading or writing.
Definition at line 64 of file PersistXML.cc.
References load, M_archive, M_archivename, M_indent, M_openmode, not_open, parse_archive(), debug::channels::dc::persist, and store.
Referenced by Application::start().
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 }
void PersistXML::close | ( | void | ) |
Finalize and close the archive.
Definition at line 81 of file PersistXML.cc.
References M_archive, M_doc, M_indent, M_openmode, not_open, debug::channels::dc::persist, and store.
Referenced by Application::start(), and ~PersistXML().
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 }
openmode_type PersistXML::openmode | ( | void | ) | const [inline] |
Return the current state.
Definition at line 123 of file PersistXML.h.
References M_openmode.
Referenced by Server::serialize().
00123 { return M_openmode; }
void PersistXML::parse_archive | ( | void | ) | [private] |
Parse the archive.
Definition at line 41 of file PersistXML.cc.
References M_archivename, M_cur, and M_doc.
Referenced by open().
00042 { 00043 M_doc = xmlParseFile(M_archivename.c_str()); 00044 00045 // Do some sanity checks. 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 // Set M_cur to the first node inside <archive>. 00061 M_cur = M_cur->xmlChildrenNode; 00062 }
void PersistXML::write_escaped | ( | T const & | builtin | ) | [inline, private] |
Write builtin-type builtin to archive.
Definition at line 486 of file PersistXML.h.
References M_archive.
Referenced by write_escaped().
00486 { M_archive << builtin; }
void PersistXML::read_data | ( | std::stringstream & | ss, | |
T & | builtin | |||
) | [inline, private] |
void PersistXML::serialize | ( | std::string const & | label, | |
T & | object | |||
) | [inline] |
Serialize object using the xml tag <label></label>.
Definition at line 175 of file PersistXML.h.
References load, M_cur, M_openmode, debug::channels::dc::persist, store, and THROW_EXCEPTION.
Referenced by Server::serialize(), serialize(), Network::serialize(), Identity::serialize(), Application::serialize(), and Application::start().
00176 { 00177 if (M_openmode == store) 00178 { 00179 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (" << 00180 type_info_of<T>().demangled_name() << ") {" << object << "}) is called."); 00181 XMLLabel xml_label(*this, label); 00182 object.serialize(*this); 00183 } 00184 else if (M_openmode == load) 00185 { 00186 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (" << 00187 type_info_of<T>().demangled_name() << ") @" << (void*)&object << ") is called."); 00188 while (M_cur) 00189 { 00190 Dout(dc::persist, "M_cur is \"" << M_cur->name << "\"."); 00191 if (!xmlStrcmp(M_cur->name, (xmlChar const*) label.c_str())) 00192 { 00193 xmlNodePtr cur = M_cur; 00194 M_cur = cur->children; 00195 object.serialize(*this); 00196 M_cur = cur->next; 00197 return; 00198 } 00199 M_cur = M_cur->next; 00200 } 00201 THROW_EXCEPTION(xml_parse_error("Cannot find requested element \"" + label + "\" in current node."), ""); 00202 } 00203 }
void PersistXML::serialize | ( | std::string const & | label, | |
boost::shared_ptr< T > & | ptr | |||
) | [inline] |
Serialize the object pointed to by a boost::shared_ptr using the xml tag <label></label>.
Definition at line 207 of file PersistXML.h.
References load, M_cur, M_openmode, debug::channels::dc::persist, store, THROW_EXCEPTION, and valid_label().
00208 { 00209 if (!valid_label(label)) 00210 THROW_EXCEPTION(xml_invalid_label(label), ""); 00211 if (M_openmode == store) 00212 { 00213 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (boost::shared_ptr<" << 00214 type_info_of<T>().demangled_name() << ">)) is called."); 00215 XMLLabel xml_label(*this, label); 00216 ptr->serialize(*this); 00217 } 00218 else if (M_openmode == load) 00219 { 00220 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (boost::shared_ptr<" << 00221 type_info_of<T>().demangled_name() << ">) @" << (void*)&ptr << ") is called."); 00222 while (M_cur) 00223 { 00224 Dout(dc::persist, "M_cur is \"" << M_cur->name << "\"."); 00225 if (!xmlStrcmp(M_cur->name, (xmlChar const*) label.c_str())) 00226 { 00227 xmlNodePtr cur = M_cur; 00228 M_cur = cur->children; 00229 ptr.reset(new T); 00230 AllocTag(ptr.get(), "Allocated for a boost::shared_ptr<" << libcwd::type_info_of<T>().demangled_name() << "> by PersistXML"); 00231 ptr->serialize(*this); 00232 M_cur = cur->next; 00233 return; 00234 } 00235 M_cur = M_cur->next; 00236 } 00237 THROW_EXCEPTION(xml_parse_error("Cannot find requested element \"" + label + "\" in current node."), ""); 00238 } 00239 }
void PersistXML::serialize | ( | std::string const & | label, | |
std::vector< T > & | vec | |||
) | [inline] |
Serialize std::vector vec using the xml tag <label></label>.
Definition at line 243 of file PersistXML.h.
References load, M_cur, M_openmode, debug::channels::dc::persist, serialize(), store, THROW_EXCEPTION, and valid_label().
00244 { 00245 if (!valid_label(label)) 00246 THROW_EXCEPTION(xml_invalid_label(label), ""); 00247 if (M_openmode == store) 00248 { 00249 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (std::vector<" << 00250 type_info_of<T>().demangled_name() << ">)) is called."); 00251 XMLLabel xml_label(*this, label); 00252 for (typename std::vector<T>::iterator iter = vec.begin(); iter != vec.end(); ++iter) 00253 this->serialize("item", *iter); 00254 } 00255 else if (M_openmode == load) 00256 { 00257 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (std::vector<" << 00258 type_info_of<T>().demangled_name() << ">) @" << (void*)&vec << ") is called."); 00259 while (M_cur) 00260 { 00261 Dout(dc::persist, "M_cur is \"" << M_cur->name << "\"."); 00262 if (!xmlStrcmp(M_cur->name, (xmlChar const*) label.c_str())) 00263 { 00264 if (M_cur->children) 00265 { 00266 xmlNodePtr cur = M_cur; 00267 M_cur = cur->children; 00268 while (M_cur) 00269 { 00270 if (!xmlStrcmp(M_cur->name, (xmlChar const*) "item")) 00271 { 00272 vec.push_back(T()); 00273 this->serialize("item", vec.back()); 00274 } 00275 M_cur = M_cur->next; 00276 } 00277 M_cur = cur->next; 00278 } 00279 return; 00280 } 00281 M_cur = M_cur->next; 00282 } 00283 if (!M_cur) 00284 THROW_EXCEPTION(xml_parse_error("Cannot find element \"" + label + "\"."), ""); 00285 } 00286 }
void PersistXML::serialize | ( | std::string const & | label, | |
std::list< T > & | list | |||
) | [inline] |
Serialize std::list list using the xml tag <label></label>.
Definition at line 290 of file PersistXML.h.
References load, M_cur, M_openmode, debug::channels::dc::persist, serialize(), store, THROW_EXCEPTION, and valid_label().
00291 { 00292 if (!valid_label(label)) 00293 THROW_EXCEPTION(xml_invalid_label(label), ""); 00294 if (M_openmode == store) 00295 { 00296 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (std::list<" << 00297 type_info_of<T>().demangled_name() << ">)) is called."); 00298 XMLLabel xml_label(*this, label); 00299 for (typename std::list<T>::iterator iter = list.begin(); iter != list.end(); ++iter) 00300 this->serialize("item", *iter); 00301 } 00302 else if (M_openmode == load) 00303 { 00304 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (std::list<" << 00305 type_info_of<T>().demangled_name() << ">) @" << (void*)&list << ") is called."); 00306 while (M_cur) 00307 { 00308 Dout(dc::persist, "M_cur is \"" << M_cur->name << "\"."); 00309 if (!xmlStrcmp(M_cur->name, (xmlChar const*) label.c_str())) 00310 { 00311 if (M_cur->children) 00312 { 00313 xmlNodePtr cur = M_cur; 00314 M_cur = cur->children; 00315 while (M_cur) 00316 { 00317 if (!xmlStrcmp(M_cur->name, (xmlChar const*) "item")) 00318 { 00319 list.push_back(T()); 00320 this->serialize("item", list.back()); 00321 } 00322 M_cur = M_cur->next; 00323 } 00324 M_cur = cur->next; 00325 } 00326 return; 00327 } 00328 M_cur = M_cur->next; 00329 } 00330 if (!M_cur) 00331 THROW_EXCEPTION(xml_parse_error("Cannot find element \"" + label + "\"."), ""); 00332 } 00333 }
void PersistXML::serialize | ( | std::string const & | label, | |
std::map< KEY, INFO, COMPARE > & | map | |||
) | [inline] |
Serialize std::map map using the xml tag <label></label>.
Definition at line 337 of file PersistXML.h.
References load, M_cur, M_openmode, debug::channels::dc::persist, serialize(), store, THROW_EXCEPTION, and valid_label().
00338 { 00339 typedef std::map<KEY, INFO, COMPARE> container_type; 00340 if (!valid_label(label)) 00341 THROW_EXCEPTION(xml_invalid_label(label), ""); 00342 if (M_openmode == store) 00343 { 00344 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (std::map<" << 00345 type_info_of<KEY>().demangled_name() << ", " << 00346 type_info_of<INFO>().demangled_name() << ">)) is called."); 00347 XMLLabel xml_label(*this, label); 00348 for (typename container_type::iterator iter = map.begin(); iter != map.end(); ++iter) 00349 { 00350 this->serialize("key", const_cast<KEY&>(iter->first)); 00351 this->serialize("info", iter->second); 00352 } 00353 } 00354 else if (M_openmode == load) 00355 { 00356 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (std::map<" << 00357 type_info_of<KEY>().demangled_name() << ", " << 00358 type_info_of<INFO>().demangled_name() << ">) @" << (void*)&map << ") is called."); 00359 while (M_cur) 00360 { 00361 Dout(dc::persist, "M_cur is \"" << M_cur->name << "\"."); 00362 if (!xmlStrcmp(M_cur->name, (xmlChar const*) label.c_str())) 00363 { 00364 if (M_cur->children) 00365 { 00366 xmlNodePtr cur = M_cur; 00367 M_cur = cur->children; 00368 while (M_cur) 00369 { 00370 Dout(dc::persist, "M_cur is \"" << M_cur->name << "\"."); 00371 if (!xmlStrcmp(M_cur->name, (xmlChar const*) "key")) 00372 { 00373 KEY key; 00374 this->serialize("key", key); 00375 std::pair<typename container_type::iterator, bool> result = 00376 map.insert(typename container_type::value_type(key, INFO())); 00377 if (!result.second) 00378 THROW_EXCEPTION(xml_parse_error("Duplicated key for map."), ""); 00379 M_cur = M_cur->next; 00380 while (M_cur) 00381 { 00382 Dout(dc::persist, "M_cur is \"" << M_cur->name << "\"."); 00383 if (!xmlStrcmp(M_cur->name, (xmlChar const*) "key")) 00384 { 00385 M_cur = NULL; 00386 break; 00387 } 00388 if (!xmlStrcmp(M_cur->name, (xmlChar const*) "info")) 00389 { 00390 this->serialize("info", result.first->second); 00391 Dout(dc::persist, "Inserted in map: " << *result.first); 00392 break; 00393 } 00394 M_cur = M_cur->next; 00395 } 00396 if (!M_cur) 00397 THROW_EXCEPTION(xml_parse_error("Missing element \"info\"."), ""); 00398 } 00399 M_cur = M_cur->next; 00400 } 00401 } 00402 return; 00403 } 00404 M_cur = M_cur->next; 00405 } 00406 if (!M_cur) 00407 THROW_EXCEPTION(xml_parse_error("Cannot find element \"" + label + "\"."), ""); 00408 } 00409 }
void PersistXML::serialize | ( | std::string const & | label, | |
boost::optional< T > & | opt | |||
) | [inline] |
Serialize boost::optional opt using the xml tag <label></label>.
Definition at line 413 of file PersistXML.h.
References ASSERT, load, M_cur, M_openmode, debug::channels::dc::persist, serialize(), store, and THROW_EXCEPTION.
00414 { 00415 if (M_openmode == store) 00416 { 00417 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (boost::optional<" << 00418 type_info_of<T>().demangled_name() << ">)) is called."); 00419 if (opt) 00420 this->serialize(label, *opt); 00421 else 00422 { 00423 std::string unknown("unknown"); 00424 this->serialize(label, unknown); 00425 } 00426 } 00427 else if (M_openmode == load) 00428 { 00429 Dout(dc::persist, "PersistXML::serialize(\"" << label << "\", (boost::optional<" << 00430 type_info_of<T>().demangled_name() << ">) @" << (void*)&opt << ") is called."); 00431 bool unknown = false; 00432 // Peek ahead (look for the label). 00433 while (M_cur) 00434 { 00435 Dout(dc::persist, "M_cur is \"" << M_cur->name << "\"."); 00436 if (!xmlStrcmp(M_cur->name, (xmlChar const*) label.c_str())) 00437 { 00438 unknown = (M_cur->children->type == XML_TEXT_NODE && 00439 !strcmp((char*)M_cur->children->name, "text") && 00440 !strcmp((char*)M_cur->children->content, "unknown")); 00441 break; 00442 } 00443 M_cur = M_cur->next; 00444 } 00445 if (!M_cur) 00446 THROW_EXCEPTION(xml_parse_error("Cannot find element \"" + label + "\"."), ""); 00447 // Read the content. 00448 if (unknown) 00449 { 00450 std::string unknown; 00451 this->serialize(label, unknown); 00452 ASSERT(unknown == "unknown"); 00453 opt = boost::none; 00454 } 00455 else 00456 { 00457 T value; 00458 this->serialize(label, value); 00459 opt = value; 00460 } 00461 } 00462 }
void PersistXML::serialize_builtin | ( | std::string const & | label, | |
T & | builtin | |||
) | [inline] |
Serialize builtin type builtin using the xml tag <label></label>.
Definition at line 506 of file PersistXML.h.
References M_openmode, debug::channels::dc::persist, and store.
00507 { 00508 if (M_openmode == store) 00509 { 00510 Dout(dc::persist, "PersistXML::serialize_builtin<" << 00511 type_info_of<T>().demangled_name() << ">(\"" << label << "\", " << builtin << ") is called."); 00512 M_archive << M_indent << '<' << label << '>'; 00513 write_escaped(builtin); 00514 M_archive << "</" << label << ">\n"; 00515 } 00516 else if (M_openmode == load) 00517 { 00518 Dout(dc::persist, "PersistXML::serialize_builtin<" << 00519 type_info_of<T>().demangled_name() << ">(\"" << label << "\", @" << (void*)&builtin << ") is called."); 00520 while (M_cur) 00521 { 00522 Dout(dc::persist, "M_cur is \"" << M_cur->name << "\"."); 00523 if (!xmlStrcmp(M_cur->name, (xmlChar const*) label.c_str())) 00524 { 00525 if (M_cur->children) 00526 { 00527 std::stringstream is; 00528 is << M_cur->children->content; 00529 read_data(is, builtin); 00530 } 00531 else 00532 builtin = T(); // Should only be used for std::string. 00533 return; 00534 } 00535 M_cur = M_cur->next; 00536 } 00537 if (!M_cur) 00538 THROW_EXCEPTION(xml_parse_error("Cannot find element \"" + label + "\"."), ""); 00539 } 00540 }
void PersistXML::write_escaped | ( | char const & | c | ) | [inline] |
Write char c to archive.
Definition at line 116 of file PersistXML.cc.
References M_archive.
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 }
void PersistXML::write_escaped | ( | std::string const & | builtin | ) | [inline] |
Write string s to archive.
Definition at line 142 of file PersistXML.cc.
References write_escaped().
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 }
void PersistXML::write_escaped | ( | unsigned char const & | c | ) | [inline] |
Write unsigned char c to archive.
Definition at line 492 of file PersistXML.h.
References write_escaped().
00492 { write_escaped(reinterpret_cast<char const&>(c)); }
void PersistXML::read_data | ( | std::stringstream & | ss, | |
std::string & | s | |||
) | [inline] |
std::ostream& operator<< | ( | std::ostream & | os, | |
PersistXML::openmode_type | openmode | |||
) | [friend] |
For debugging purposes. Write a PersistXML::openmode to os.
Definition at line 175 of file debug_ostream_operators.cc.
00176 { 00177 return os << debug::openmode_name(openmode); 00178 }
openmode_type PersistXML::M_openmode [protected] |
Whether or not the archive is opened for reading or writing.
Definition at line 105 of file PersistXML.h.
Referenced by close(), open(), openmode(), serialize(), serialize_builtin(), and ~PersistXML().
std::string PersistXML::M_archivename [protected] |
The name of the XML file used to write the archive to disk.
Definition at line 106 of file PersistXML.h.
Referenced by open(), and parse_archive().
std::fstream PersistXML::M_archive [protected] |
The file stream of an open archive.
Definition at line 107 of file PersistXML.h.
Referenced by close(), open(), write_escaped(), XMLLabel::XMLLabel(), and XMLLabel::~XMLLabel().
Indentation PersistXML::M_indent [protected] |
Current XML indentation.
Definition at line 108 of file PersistXML.h.
Referenced by close(), open(), XMLLabel::XMLLabel(), and XMLLabel::~XMLLabel().
xmlDocPtr PersistXML::M_doc [protected] |
XML document open for reading.
Definition at line 109 of file PersistXML.h.
Referenced by close(), and parse_archive().
xmlNodePtr PersistXML::M_cur [protected] |
Current node in M_doc.
Definition at line 110 of file PersistXML.h.
Referenced by parse_archive(), and serialize().
std::stack<std::vector<xmlNodePtr> > PersistXML::M_parent_nodes [protected] |
Copyright © 2005-2007 Carlo Wood. All rights reserved. |
---|