SHOGUN
v3.2.0
|
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_COMPLEX128: 00225 if (snprintf(buf, STRING_LEN, "(%.16lg,%.16lg)", 00226 ((complex128_t*) param)->real(),((complex128_t*) param)->imag() 00227 ) <= 0) return false; 00228 break; 00229 case PT_UNDEFINED: 00230 case PT_SGOBJECT: 00231 SG_ERROR("write_scalar_wrapped(): Implementation error during" 00232 " writing XmlFile!"); 00233 return false; 00234 } 00235 00236 xmlNodeAddContent(m_stack_stream.back(), BAD_CAST buf); 00237 return true; 00238 } 00239 00240 bool 00241 CSerializableXmlFile::write_cont_begin_wrapped( 00242 const TSGDataType* type, index_t len_real_y, index_t len_real_x) 00243 { 00244 return true; 00245 } 00246 00247 bool 00248 CSerializableXmlFile::write_cont_end_wrapped( 00249 const TSGDataType* type, index_t len_real_y, index_t len_real_x) 00250 { 00251 if (type->m_ctype==CT_MATRIX || type->m_ctype==CT_SGMATRIX) 00252 if (len_real_y*len_real_x>0) 00253 pop_node(); 00254 00255 return true; 00256 } 00257 00258 bool 00259 CSerializableXmlFile::write_string_begin_wrapped( 00260 const TSGDataType* type, index_t length) 00261 { 00262 return true; 00263 } 00264 00265 bool 00266 CSerializableXmlFile::write_string_end_wrapped( 00267 const TSGDataType* type, index_t length) 00268 { 00269 return true; 00270 } 00271 00272 bool 00273 CSerializableXmlFile::write_stringentry_begin_wrapped( 00274 const TSGDataType* type, index_t y) 00275 { 00276 if (!push_node(BAD_CAST STR_STRING)) return false; 00277 00278 return true; 00279 } 00280 00281 bool 00282 CSerializableXmlFile::write_stringentry_end_wrapped( 00283 const TSGDataType* type, index_t y) 00284 { 00285 pop_node(); 00286 00287 return true; 00288 } 00289 00290 bool 00291 CSerializableXmlFile::write_sparse_begin_wrapped( 00292 const TSGDataType* type, index_t length) 00293 { 00294 return true; 00295 } 00296 00297 bool 00298 CSerializableXmlFile::write_sparse_end_wrapped( 00299 const TSGDataType* type, index_t length) 00300 { 00301 return true; 00302 } 00303 00304 bool 00305 CSerializableXmlFile::write_sparseentry_begin_wrapped( 00306 const TSGDataType* type, const SGSparseVectorEntry<char>* first_entry, 00307 index_t feat_index, index_t y) 00308 { 00309 push_node(BAD_CAST STR_SPARSE); 00310 00311 string_t buf; 00312 snprintf(buf, STRING_LEN, "%" PRIi32, feat_index); 00313 if (xmlNewProp(m_stack_stream.back(), BAD_CAST STR_PROP_FEATINDEX, 00314 BAD_CAST buf) == NULL) return false; 00315 return true; 00316 } 00317 00318 bool 00319 CSerializableXmlFile::write_sparseentry_end_wrapped( 00320 const TSGDataType* type, const SGSparseVectorEntry<char>* first_entry, 00321 index_t feat_index, index_t y) 00322 { 00323 pop_node(); 00324 00325 return true; 00326 } 00327 00328 bool 00329 CSerializableXmlFile::write_item_begin_wrapped( 00330 const TSGDataType* type, index_t y, index_t x) 00331 { 00332 if (type->m_ctype==CT_MATRIX || type->m_ctype==CT_SGMATRIX) { 00333 if (y==0) 00334 { 00335 if (x != 0) pop_node(); 00336 00337 string_t buf_x; snprintf(buf_x, STRING_LEN, "x%" PRIi32, x); 00338 if (!push_node(BAD_CAST buf_x)) return false; 00339 } 00340 } 00341 00342 push_node(BAD_CAST STR_ITEM); 00343 00344 return true; 00345 } 00346 00347 bool 00348 CSerializableXmlFile::write_item_end_wrapped( 00349 const TSGDataType* type, index_t y, index_t x) 00350 { 00351 pop_node(); 00352 00353 return true; 00354 } 00355 00356 bool 00357 CSerializableXmlFile::write_sgserializable_begin_wrapped( 00358 const TSGDataType* type, const char* sgserializable_name, 00359 EPrimitiveType generic) 00360 { 00361 if (*sgserializable_name == '\0') { 00362 if (xmlNewProp(m_stack_stream.back(), BAD_CAST STR_PROP_IS_NULL, 00363 BAD_CAST STR_TRUE) == NULL) return false; 00364 return true; 00365 } 00366 00367 if (xmlNewProp(m_stack_stream.back(), 00368 BAD_CAST STR_PROP_INSTANCE_NAME, 00369 BAD_CAST sgserializable_name) == NULL) return false; 00370 00371 if (generic != PT_NOT_GENERIC) { 00372 string_t buf; 00373 TSGDataType::ptype_to_string(buf, generic, STRING_LEN); 00374 if (xmlNewProp(m_stack_stream.back(), 00375 BAD_CAST STR_PROP_GENERIC_NAME, BAD_CAST buf) 00376 == NULL) return false; 00377 } 00378 00379 return true; 00380 } 00381 00382 bool 00383 CSerializableXmlFile::write_sgserializable_end_wrapped( 00384 const TSGDataType* type, const char* sgserializable_name, 00385 EPrimitiveType generic) 00386 { 00387 return true; 00388 } 00389 00390 bool 00391 CSerializableXmlFile::write_type_begin_wrapped( 00392 const TSGDataType* type, const char* name, const char* prefix) 00393 { 00394 if (!push_node(BAD_CAST name)) return false; 00395 00396 SG_SET_LOCALE_C; 00397 00398 string_t buf; 00399 type->to_string(buf, STRING_LEN); 00400 if (xmlNewProp(m_stack_stream.back(), BAD_CAST STR_PROP_TYPE, 00401 BAD_CAST buf) == NULL) return false; 00402 00403 return true; 00404 } 00405 00406 bool 00407 CSerializableXmlFile::write_type_end_wrapped( 00408 const TSGDataType* type, const char* name, const char* prefix) 00409 { 00410 pop_node(); 00411 00412 SG_RESET_LOCALE; 00413 00414 return true; 00415 } 00416 00417 #endif /* HAVE_XML */