SHOGUN v0.9.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 "lib/config.h" 00012 #ifdef HAVE_XML 00013 00014 #include "lib/SerializableXmlFile.h" 00015 #include "lib/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(void) 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(void) 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(void) 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(void) 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 && len_real_y *len_real_x > 0) 00246 pop_node(); 00247 00248 return true; 00249 } 00250 00251 bool 00252 CSerializableXmlFile::write_string_begin_wrapped( 00253 const TSGDataType* type, index_t length) 00254 { 00255 return true; 00256 } 00257 00258 bool 00259 CSerializableXmlFile::write_string_end_wrapped( 00260 const TSGDataType* type, index_t length) 00261 { 00262 return true; 00263 } 00264 00265 bool 00266 CSerializableXmlFile::write_stringentry_begin_wrapped( 00267 const TSGDataType* type, index_t y) 00268 { 00269 if (!push_node(BAD_CAST STR_STRING)) return false; 00270 00271 return true; 00272 } 00273 00274 bool 00275 CSerializableXmlFile::write_stringentry_end_wrapped( 00276 const TSGDataType* type, index_t y) 00277 { 00278 pop_node(); 00279 00280 return true; 00281 } 00282 00283 bool 00284 CSerializableXmlFile::write_sparse_begin_wrapped( 00285 const TSGDataType* type, index_t vec_index, 00286 index_t length) 00287 { 00288 string_t buf; 00289 snprintf(buf, STRING_LEN, "%"PRIi32, vec_index); 00290 if (xmlNewProp(m_stack_stream.back(), BAD_CAST STR_PROP_VECINDEX, 00291 BAD_CAST buf) == NULL) return false; 00292 00293 return true; 00294 } 00295 00296 bool 00297 CSerializableXmlFile::write_sparse_end_wrapped( 00298 const TSGDataType* type, index_t vec_index, 00299 index_t length) 00300 { 00301 return true; 00302 } 00303 00304 bool 00305 CSerializableXmlFile::write_sparseentry_begin_wrapped( 00306 const TSGDataType* type, const TSparseEntry<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 TSparseEntry<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 && y == 0) { 00333 if (x != 0) pop_node(); 00334 00335 string_t buf_x; snprintf(buf_x, STRING_LEN, "x%"PRIi32, x); 00336 if (!push_node(BAD_CAST buf_x)) return false; 00337 } 00338 00339 push_node(BAD_CAST STR_ITEM); 00340 00341 return true; 00342 } 00343 00344 bool 00345 CSerializableXmlFile::write_item_end_wrapped( 00346 const TSGDataType* type, index_t y, index_t x) 00347 { 00348 pop_node(); 00349 00350 return true; 00351 } 00352 00353 bool 00354 CSerializableXmlFile::write_sgserializable_begin_wrapped( 00355 const TSGDataType* type, const char* sgserializable_name, 00356 EPrimitiveType generic) 00357 { 00358 if (*sgserializable_name == '\0') { 00359 if (xmlNewProp(m_stack_stream.back(), BAD_CAST STR_PROP_IS_NULL, 00360 BAD_CAST STR_TRUE) == NULL) return false; 00361 return true; 00362 } 00363 00364 if (xmlNewProp(m_stack_stream.back(), 00365 BAD_CAST STR_PROP_INSTANCE_NAME, 00366 BAD_CAST sgserializable_name) == NULL) return false; 00367 00368 if (generic != PT_NOT_GENERIC) { 00369 string_t buf; 00370 TSGDataType::ptype_to_string(buf, generic, STRING_LEN); 00371 if (xmlNewProp(m_stack_stream.back(), 00372 BAD_CAST STR_PROP_GENERIC_NAME, BAD_CAST buf) 00373 == NULL) return false; 00374 } 00375 00376 return true; 00377 } 00378 00379 bool 00380 CSerializableXmlFile::write_sgserializable_end_wrapped( 00381 const TSGDataType* type, const char* sgserializable_name, 00382 EPrimitiveType generic) 00383 { 00384 return true; 00385 } 00386 00387 bool 00388 CSerializableXmlFile::write_type_begin_wrapped( 00389 const TSGDataType* type, const char* name, const char* prefix) 00390 { 00391 if (!push_node(BAD_CAST name)) return false; 00392 00393 SG_SET_LOCALE_C; 00394 00395 string_t buf; 00396 type->to_string(buf, STRING_LEN); 00397 if (xmlNewProp(m_stack_stream.back(), BAD_CAST STR_PROP_TYPE, 00398 BAD_CAST buf) == NULL) return false; 00399 00400 return true; 00401 } 00402 00403 bool 00404 CSerializableXmlFile::write_type_end_wrapped( 00405 const TSGDataType* type, const char* name, const char* prefix) 00406 { 00407 pop_node(); 00408 00409 SG_RESET_LOCALE; 00410 00411 return true; 00412 } 00413 00414 #endif /* HAVE_XML */