SerializableXmlFile.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 2010 Soeren Sonnenburg
00008  * Copyright (C) 2010 Berlin Institute of Technology
00009  */
00010 
00011 #include <shogun/lib/config.h>
00012 #ifdef HAVE_XML
00013 
00014 #include <shogun/io/SerializableXmlFile.h>
00015 #include <shogun/io/SerializableXmlReader00.h>
00016 
00017 #define STR_ROOT_NAME_00 \
00018     "_SHOGUN_SERIALIZABLE_XML_FILE_V_00_"
00019 
00020 using namespace shogun;
00021 
00022 CSerializableXmlFile::CSerializableXmlFile()
00023     :CSerializableFile() { init(false); }
00024 
00025 CSerializableXmlFile::CSerializableXmlFile(const char* fname, char rw,
00026                                            bool format)
00027     :CSerializableFile()
00028 {
00029     CSerializableFile::init(NULL, rw, fname);
00030     init(format);
00031 }
00032 
00033 CSerializableXmlFile::~CSerializableXmlFile()
00034 {
00035     close();
00036 }
00037 
00038 CSerializableFile::TSerializableReader*
00039 CSerializableXmlFile::new_reader(char* dest_version, size_t n)
00040 {
00041     xmlChar* name;
00042 
00043     if ((name = xmlGetNodePath(m_stack_stream.back())) == NULL)
00044         return NULL;
00045 
00046     strncpy(dest_version, (const char*) (name+1), n);
00047     xmlFree(name);
00048 
00049     if (strcmp(STR_ROOT_NAME_00, dest_version) == 0)
00050         return new SerializableXmlReader00(this);
00051 
00052     return NULL;
00053 }
00054 
00055 bool
00056 CSerializableXmlFile::push_node(const xmlChar* name)
00057 {
00058     xmlNode* node
00059         = xmlNewChild(m_stack_stream.back(), NULL, name, NULL);
00060 
00061     m_stack_stream.push_back(node);
00062 
00063     return node != NULL;
00064 }
00065 
00066 bool
00067 CSerializableXmlFile::join_node(const xmlChar* name)
00068 {
00069     for (xmlNode* cur=m_stack_stream.back()->children; cur!=NULL;
00070          cur=cur->next) {
00071         if (cur->type != XML_ELEMENT_NODE
00072             || xmlStrcmp(cur->name, name) != 0) continue;
00073 
00074         m_stack_stream.push_back(cur);
00075         return true;
00076     }
00077 
00078     return false;
00079 }
00080 
00081 bool
00082 CSerializableXmlFile::next_node(const xmlChar* name)
00083 {
00084     for (xmlNode* cur=m_stack_stream.back()->next; cur!=NULL;
00085          cur=cur->next) {
00086         if (cur->type != XML_ELEMENT_NODE
00087             || xmlStrcmp(cur->name, name) != 0) continue;
00088 
00089         pop_node();
00090         m_stack_stream.push_back(cur);
00091         return true;
00092     }
00093 
00094     return false;
00095 }
00096 
00097 void
00098 CSerializableXmlFile::pop_node()
00099 {
00100     m_stack_stream.pop_back();
00101 }
00102 
00103 void
00104 CSerializableXmlFile::init(bool format)
00105 {
00106     m_format = format, m_doc = NULL;
00107 
00108     LIBXML_TEST_VERSION;
00109 
00110     if (m_filename == NULL || *m_filename == '\0') {
00111         SG_WARNING("Filename not given for opening file!\n");
00112         close(); return;
00113     }
00114 
00115     SG_DEBUG("Opening '%s'\n", m_filename);
00116 
00117     xmlNode* tmp;
00118     switch (m_task) {
00119     case 'r':
00120         if ((m_doc = xmlReadFile(m_filename, NULL, XML_PARSE_HUGE | XML_PARSE_NONET)) == NULL
00121             || (tmp = xmlDocGetRootElement(m_doc)) == NULL)
00122         {
00123             SG_WARNING("Could not open file `%s' for reading!\n", m_filename);
00124             close(); return;
00125         }
00126         m_stack_stream.push_back(tmp);
00127         break;
00128     case 'w':
00129         m_doc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
00130         m_stack_stream.push_back(xmlNewNode(
00131                                      NULL, BAD_CAST STR_ROOT_NAME_00));
00132         xmlDocSetRootElement(m_doc, m_stack_stream.back());
00133         break;
00134     default:
00135         SG_WARNING("Could not open file `%s', unknown mode!\n",
00136                    m_filename);
00137         close(); return;
00138     }
00139 }
00140 
00141 void
00142 CSerializableXmlFile::close()
00143 {
00144     while (m_stack_stream.get_num_elements() > 0) pop_node();
00145 
00146     if (is_opened()) {
00147         if (m_task == 'w'
00148             &&  xmlSaveFormatFileEnc(m_filename, m_doc, "UTF-8",
00149                                      m_format) < 0) {
00150             SG_WARNING("Could not close file `%s' for writing!\n",
00151                        m_filename);
00152         }
00153 
00154         xmlFreeDoc(m_doc); m_doc = NULL;
00155         xmlCleanupParser();
00156     }
00157 }
00158 
00159 bool
00160 CSerializableXmlFile::is_opened()
00161 {
00162     return m_doc != NULL;
00163 }
00164 
00165 bool
00166 CSerializableXmlFile::write_scalar_wrapped(
00167     const TSGDataType* type, const void* param)
00168 {
00169     string_t buf;
00170 
00171     switch (type->m_ptype) {
00172     case PT_BOOL:
00173         if (snprintf(buf, STRING_LEN, "%s", *(bool*) param? STR_TRUE
00174                      : STR_FALSE) <= 0) return false;
00175         break;
00176     case PT_CHAR:
00177         if (snprintf(buf, STRING_LEN, "%c", *(char*) param
00178                 ) <= 0) return false;
00179         break;
00180     case PT_INT8:
00181         if (snprintf(buf, STRING_LEN, "%"PRIi8, *(int8_t*) param
00182                 ) <= 0) return false;
00183         break;
00184     case PT_UINT8:
00185         if (snprintf(buf, STRING_LEN, "%"PRIu8, *(uint8_t*) param
00186                 ) <= 0) return false;
00187         break;
00188     case PT_INT16:
00189         if (snprintf(buf, STRING_LEN, "%"PRIi16, *(int16_t*) param
00190                 ) <= 0) return false;
00191         break;
00192     case PT_UINT16:
00193         if (snprintf(buf, STRING_LEN, "%"PRIu16, *(uint16_t*) param
00194                 ) <= 0) return false;
00195         break;
00196     case PT_INT32:
00197         if (snprintf(buf, STRING_LEN, "%"PRIi32, *(int32_t*) param
00198                 ) <= 0) return false;
00199         break;
00200     case PT_UINT32:
00201         if (snprintf(buf, STRING_LEN, "%"PRIu32, *(uint32_t*) param
00202                 ) <= 0) return false;
00203         break;
00204     case PT_INT64:
00205         if (snprintf(buf, STRING_LEN, "%"PRIi64, *(int64_t*) param
00206                 ) <= 0) return false;
00207         break;
00208     case PT_UINT64:
00209         if (snprintf(buf, STRING_LEN, "%"PRIu64, *(uint64_t*) param
00210                 ) <= 0) return false;
00211         break;
00212     case PT_FLOAT32:
00213         if (snprintf(buf, STRING_LEN, "%.16g", *(float32_t*) param
00214                 ) <= 0) return false;
00215         break;
00216     case PT_FLOAT64:
00217         if (snprintf(buf, STRING_LEN, "%.16lg", *(float64_t*) param
00218                 ) <= 0) return false;
00219         break;
00220     case PT_FLOATMAX:
00221         if (snprintf(buf, STRING_LEN, "%.16Lg", *(floatmax_t*)
00222                      param) <= 0) return false;
00223         break;
00224     case PT_SGOBJECT:
00225         SG_ERROR("write_scalar_wrapped(): Implementation error during"
00226                  " writing XmlFile!");
00227         return false;
00228     }
00229 
00230     xmlNodeAddContent(m_stack_stream.back(), BAD_CAST buf);
00231     return true;
00232 }
00233 
00234 bool
00235 CSerializableXmlFile::write_cont_begin_wrapped(
00236     const TSGDataType* type, index_t len_real_y, index_t len_real_x)
00237 {
00238     return true;
00239 }
00240 
00241 bool
00242 CSerializableXmlFile::write_cont_end_wrapped(
00243     const TSGDataType* type, index_t len_real_y, index_t len_real_x)
00244 {
00245     if (type->m_ctype==CT_MATRIX || type->m_ctype==CT_SGMATRIX)
00246         if (len_real_y*len_real_x>0)
00247             pop_node();
00248 
00249     return true;
00250 }
00251 
00252 bool
00253 CSerializableXmlFile::write_string_begin_wrapped(
00254     const TSGDataType* type, index_t length)
00255 {
00256     return true;
00257 }
00258 
00259 bool
00260 CSerializableXmlFile::write_string_end_wrapped(
00261     const TSGDataType* type, index_t length)
00262 {
00263     return true;
00264 }
00265 
00266 bool
00267 CSerializableXmlFile::write_stringentry_begin_wrapped(
00268     const TSGDataType* type, index_t y)
00269 {
00270     if (!push_node(BAD_CAST STR_STRING)) return false;
00271 
00272     return true;
00273 }
00274 
00275 bool
00276 CSerializableXmlFile::write_stringentry_end_wrapped(
00277     const TSGDataType* type, index_t y)
00278 {
00279     pop_node();
00280 
00281     return true;
00282 }
00283 
00284 bool
00285 CSerializableXmlFile::write_sparse_begin_wrapped(
00286     const TSGDataType* type, index_t vec_index,
00287     index_t length)
00288 {
00289     string_t buf;
00290     snprintf(buf, STRING_LEN, "%"PRIi32, vec_index);
00291     if (xmlNewProp(m_stack_stream.back(), BAD_CAST STR_PROP_VECINDEX,
00292                    BAD_CAST buf) == NULL) return false;
00293 
00294     return true;
00295 }
00296 
00297 bool
00298 CSerializableXmlFile::write_sparse_end_wrapped(
00299     const TSGDataType* type, index_t vec_index,
00300     index_t length)
00301 {
00302     return true;
00303 }
00304 
00305 bool
00306 CSerializableXmlFile::write_sparseentry_begin_wrapped(
00307     const TSGDataType* type, const SGSparseVectorEntry<char>* first_entry,
00308     index_t feat_index, index_t y)
00309 {
00310     push_node(BAD_CAST STR_SPARSE);
00311 
00312     string_t buf;
00313     snprintf(buf, STRING_LEN, "%"PRIi32, feat_index);
00314     if (xmlNewProp(m_stack_stream.back(), BAD_CAST STR_PROP_FEATINDEX,
00315                    BAD_CAST buf) == NULL) return false;
00316     return true;
00317 }
00318 
00319 bool
00320 CSerializableXmlFile::write_sparseentry_end_wrapped(
00321     const TSGDataType* type, const SGSparseVectorEntry<char>* first_entry,
00322     index_t feat_index, index_t y)
00323 {
00324     pop_node();
00325 
00326     return true;
00327 }
00328 
00329 bool
00330 CSerializableXmlFile::write_item_begin_wrapped(
00331     const TSGDataType* type, index_t y, index_t x)
00332 {
00333     if (type->m_ctype==CT_MATRIX || type->m_ctype==CT_SGMATRIX) {
00334         if (y==0)
00335         {
00336             if (x != 0) pop_node();
00337 
00338             string_t buf_x; snprintf(buf_x, STRING_LEN, "x%"PRIi32, x);
00339             if (!push_node(BAD_CAST buf_x)) return false;
00340         }
00341     }
00342 
00343     push_node(BAD_CAST STR_ITEM);
00344 
00345     return true;
00346 }
00347 
00348 bool
00349 CSerializableXmlFile::write_item_end_wrapped(
00350     const TSGDataType* type, index_t y, index_t x)
00351 {
00352     pop_node();
00353 
00354     return true;
00355 }
00356 
00357 bool
00358 CSerializableXmlFile::write_sgserializable_begin_wrapped(
00359     const TSGDataType* type, const char* sgserializable_name,
00360     EPrimitiveType generic)
00361 {
00362     if (*sgserializable_name == '\0') {
00363         if (xmlNewProp(m_stack_stream.back(), BAD_CAST STR_PROP_IS_NULL,
00364                        BAD_CAST STR_TRUE) == NULL) return false;
00365         return true;
00366     }
00367 
00368     if (xmlNewProp(m_stack_stream.back(),
00369                    BAD_CAST STR_PROP_INSTANCE_NAME,
00370                    BAD_CAST sgserializable_name) == NULL) return false;
00371 
00372     if (generic != PT_NOT_GENERIC) {
00373         string_t buf;
00374         TSGDataType::ptype_to_string(buf, generic, STRING_LEN);
00375         if (xmlNewProp(m_stack_stream.back(),
00376                        BAD_CAST STR_PROP_GENERIC_NAME, BAD_CAST buf)
00377             == NULL) return false;
00378     }
00379 
00380     return true;
00381 }
00382 
00383 bool
00384 CSerializableXmlFile::write_sgserializable_end_wrapped(
00385     const TSGDataType* type, const char* sgserializable_name,
00386     EPrimitiveType generic)
00387 {
00388     return true;
00389 }
00390 
00391 bool
00392 CSerializableXmlFile::write_type_begin_wrapped(
00393     const TSGDataType* type, const char* name, const char* prefix)
00394 {
00395     if (!push_node(BAD_CAST name)) return false;
00396 
00397     SG_SET_LOCALE_C;
00398 
00399     string_t buf;
00400     type->to_string(buf, STRING_LEN);
00401     if (xmlNewProp(m_stack_stream.back(), BAD_CAST STR_PROP_TYPE,
00402                    BAD_CAST buf) == NULL) return false;
00403 
00404     return true;
00405 }
00406 
00407 bool
00408 CSerializableXmlFile::write_type_end_wrapped(
00409     const TSGDataType* type, const char* name, const char* prefix)
00410 {
00411     pop_node();
00412 
00413     SG_RESET_LOCALE;
00414 
00415     return true;
00416 }
00417 
00418 #endif /* HAVE_XML  */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation