Changeset 4786
- Timestamp:
- Aug 16, 2005, 10:13:20 AM (21 years ago)
- Location:
- trunk/psLib/src/xml
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/xml/psXML.c
r4540 r4786 1 1 /** @file psXML.c 2 2 * 3 * @brief Contains XML input/output functions.3 * @brief Contains basic XML definitions and operations 4 4 * 5 * This file defines functions to read metadata from an XML file. 5 * This file defines the basic type for an XML struct and functions useful 6 * in creation and usage of XML documents/files. 6 7 * 7 8 * @ingroup XML 8 9 * 9 * @author Ross Harman, MHPCC 10 * @author Eric Van Alst, MHPCC 10 * @author David Robbins, MHPCC 11 11 * 12 * @version $Revision: 1.3 5$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-0 7-12 19:12:01$12 * @version $Revision: 1.36 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-08-16 20:13:20 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 16 16 */ 17 17 18 #include <libxml/parser.h>19 #include <string.h>20 #include <ctype.h>21 #include <limits.h>22 23 18 #include "psXML.h" 24 #include "psMemory.h" 25 #include "psError.h" 26 #include "psString.h" 27 #include "psConstants.h" 28 #include "psErrorText.h" 19 #include <unistd.h> 20 #include <fcntl.h> 29 21 30 22 /******************************************************************************/ … … 32 24 /******************************************************************************/ 33 25 34 /** Maximum size of a FITS line */35 #define FITS_LINE_SIZE 8036 37 26 /** Maximum size of a string */ 38 #define MAX_STRING_LENGTH 256 39 40 // Returns single parsed value as a double precision number. The input string must be cleaned and null 41 // terminated. 42 static double parseValue(char *inString, psS32 *status) 43 { 44 char *end = NULL; 45 double value = 0.0; 46 47 value = strtod(inString, &end); 48 if(*end != '\0') { 49 *status = 1; 50 } else if(inString==end) { 51 *status = 1; 52 } 53 54 return value; 55 } 56 57 /** Returns true or false. 'T', 't', '1', 'F', 'f', and '0' are acceptable, parsable variations. */ 58 static psBool parseBool(char *inString, psS32 *status) 59 { 60 psBool value = false; 61 62 63 if(*inString=='T' || *inString=='t' || *inString=='1') { 64 value = true; 65 } else if(*inString=='F' || *inString=='f' || *inString=='0') { 66 value = false; 67 } else { 68 *status = 1; 69 } 70 71 return value; 72 } 73 74 /** Returns parsed vector filled with with data. The input string must be null terminated. */ 75 static psVector* parseVector(char *inString, psElemType elemType, psS32 *status) 76 { 77 char* end = NULL; 78 char* saveValue = NULL; 79 psS32 i = 0; 80 psS32 numValues = 0; 81 double value = 0.0; 82 psVector* vec = NULL; 83 84 // Cycle through string and count entries 85 saveValue = inString; 86 while(*inString!='\0') { 87 strtod(inString, &end); 88 if(inString==end) { 89 *status = 1; 27 #define MAXSTR 256 28 #define MAXVEC 2048 29 #define MAXBUF 10000 30 31 32 static void XMLFree(psXMLDoc *XML) 33 { 34 xmlFreeDoc(*XML); 35 } 36 37 psXMLDoc *psXMLDocAlloc(void) 38 { 39 psXMLDoc *XML; 40 XML = psAlloc(sizeof(psXMLDoc)); 41 psMemSetDeallocator(XML, (psFreeFunc) XMLFree); 42 return(XML); 43 } 44 45 psXMLDoc *psMetadataToXMLDoc(const psMetadata *md) 46 { 47 PS_ASSERT_PTR_NON_NULL(md, NULL); 48 49 psXMLDoc *XML = psXMLDocAlloc(); 50 xmlNode *cur_node; 51 xmlNode *root = NULL; 52 xmlAttr *prop = NULL; 53 psDataType type; 54 char content[MAXSTR]; 55 char vec[MAXVEC]; 56 int i; 57 psMetadataIterator *iter = psMetadataIteratorAlloc(*(psMetadata**)&md, PS_LIST_HEAD, NULL); 58 psMetadataItem *item; 59 60 //setup root element 61 if( root == NULL ) { 62 *XML = xmlNewDoc((const xmlChar*)"1.0"); 63 root = xmlNewDocNode(*XML, NULL, (const xmlChar*)"metadata", "\n"); 64 xmlDocSetRootElement(*XML, root); 65 } 66 item = psMetadataGetAndIncrement(iter); 67 while ( item != NULL ) { 68 type = item->type; 69 if ( type == 65537) 70 type = PS_DATA_STRING; 71 if ( type == 65538) 72 type = PS_DATA_VECTOR; 73 if ( type == 65547) 74 type = PS_DATA_METADATA; 75 switch (type) { 76 case PS_DATA_BOOL: 77 cur_node = xmlNewChild(root, NULL, "item", "\n"); 78 prop = xmlNewProp(cur_node, "name", item->name); 79 prop = xmlNewProp(cur_node, "psType", "BOOL"); 80 if ( item->data.B ) 81 strncpy(content, "TRUE", MAXSTR); 82 else 83 strncpy(content, "FALSE", MAXSTR); 84 prop = xmlNewProp(cur_node, "value", content); 85 break; 86 case PS_DATA_S32: 87 snprintf(content, MAXSTR, "%d", item->data.S32); 88 cur_node = xmlNewChild(root, NULL, "item", "\n"); 89 prop = xmlNewProp(cur_node, "name", item->name); 90 prop = xmlNewProp(cur_node, "psType", "S32"); 91 prop = xmlNewProp(cur_node, "value", content); 92 break; 93 case PS_DATA_F32: 94 snprintf(content, MAXSTR, "%f", item->data.F32); 95 cur_node = xmlNewChild(root, NULL, "item", "\n"); 96 prop = xmlNewProp(cur_node, "name", item->name); 97 prop = xmlNewProp(cur_node, "psType", "F32"); 98 prop = xmlNewProp(cur_node, "value", content); 99 break; 100 case PS_DATA_F64: 101 snprintf(content, MAXSTR, "%lf", item->data.F64); 102 cur_node = xmlNewChild(root, NULL, "item", "\n"); 103 prop = xmlNewProp(cur_node, "name", item->name); 104 prop = xmlNewProp(cur_node, "psType", "F64"); 105 prop = xmlNewProp(cur_node, "value", content); 106 break; 107 case PS_DATA_STRING: 108 cur_node = xmlNewChild(root, NULL, "item", "\n"); 109 prop = xmlNewProp(cur_node, "name", item->name); 110 prop = xmlNewProp(cur_node, "psType", "STR"); 111 strncpy(content, ((char *)(item->data.V)), MAXSTR); 112 prop = xmlNewProp(cur_node, "value", content); 113 break; 114 case PS_DATA_METADATA: 115 i = 0; 116 psXMLDoc *newDoc; 117 xmlNode *new_root = NULL; 118 xmlNode *new_node = NULL; 119 newDoc = psMetadataToXMLDoc(item->data.md); 120 new_root = xmlDocGetRootElement(*newDoc); 121 prop = xmlNewProp(new_root, "name", item->name); 122 prop = xmlNewProp(new_root, "psType", "METADATA"); 123 new_node = xmlAddSibling(cur_node, new_root); 124 psFree(newDoc); 125 break; 126 case PS_DATA_VECTOR: 127 cur_node = xmlNewChild(root, NULL, "vector", "\n"); 128 prop = xmlNewProp(cur_node, "name", item->name); 129 type = ((psVector*)(item->data.V))->type.type; 130 strncpy(vec, "", MAXSTR); 131 switch (type) { 132 case PS_DATA_S32: 133 prop = xmlNewProp(cur_node, "psType", "S32"); 134 for (i = 0; ((psVector*)(item->data.V))->data.S32[i] != 0; i++) { 135 snprintf(content, MAXSTR, "%d", 136 ((psVector*)(item->data.V))->data.S32[i]); 137 if ( ((psVector*)(item->data.V))->data.S32[i+1] != 0 ) { 138 strncat(content, ", ", 2); 139 } 140 strncat(vec, content, MAXSTR); 141 } 142 143 break; 144 case PS_DATA_F32: 145 prop = xmlNewProp(cur_node, "psType", "F32"); 146 for (i = 0; ((psVector*)(item->data.V))->data.F32[i] != 0; i++) { 147 snprintf(content, MAXSTR, "%f", 148 ((psVector*)(item->data.V))->data.F32[i]); 149 if ( ((psVector*)(item->data.V))->data.F32[i+1] != 0 ) { 150 strncat(content, ", ", 2); 151 } 152 strncat(vec, content, MAXSTR); 153 } 154 break; 155 case PS_DATA_F64: 156 prop = xmlNewProp(cur_node, "psType", "F64"); 157 for (i = 0; ((psVector*)(item->data.V))->data.F64[i] != 0; i++) { 158 snprintf(content, MAXSTR, "%lf", 159 ((psVector*)(item->data.V))->data.F64[i]); 160 if ( ((psVector*)(item->data.V))->data.F64[i+1] != 0 ) { 161 strncat(content, ", ", 2); 162 } 163 strncat(vec, content, MAXSTR); 164 } 165 break; 166 case PS_DATA_UNKNOWN: 167 default: 168 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 169 PS_ERRORTEXT_psXML_INVALID_DATATYPE); 170 psFree(XML); 171 psFree(iter); 172 return NULL; 173 } 174 prop = xmlNewProp(cur_node, "value", vec); 175 break; 176 case PS_DATA_UNKNOWN: 177 default: 178 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 179 PS_ERRORTEXT_psXML_INVALID_DATATYPE); 180 psFree(XML); 181 psFree(iter); 90 182 return NULL; 91 183 } 92 while(*end==' ' || *end==',') { // Commas or spaces may be used as delimiters for vector values 93 end++; 94 } 95 inString=end; 96 numValues++; 97 } 98 99 // Cycle through string and convert string values to values 100 if(numValues) { 101 inString = saveValue; 102 end = NULL; 103 vec = psVectorAlloc(numValues, elemType); 104 105 while(*inString!='\0') { 106 value = strtod(inString, &end); 107 if(inString==end) { 108 *status = 1; 109 return vec; 110 } 111 switch(elemType) { 112 case PS_TYPE_U8: 113 vec->data.U8[i++] = (psU8)value; 114 break; 115 case PS_TYPE_U16: 116 vec->data.U16[i++] = (psU16)value; 117 break; 118 case PS_TYPE_U32: 119 vec->data.U32[i++] = (psU32)value; 120 break; 121 case PS_TYPE_U64: 122 vec->data.U64[i++] = (psU64)value; 123 break; 124 case PS_TYPE_S8: 125 vec->data.S8[i++] = (psS8)value; 126 break; 127 case PS_TYPE_S16: 128 vec->data.S16[i++] = (psS16)value; 129 break; 130 case PS_TYPE_S32: 131 vec->data.S32[i++] = (psS32)value; 132 break; 133 case PS_TYPE_S64: 134 vec->data.S64[i++] = (psS64)value; 135 break; 136 case PS_TYPE_F32: 137 vec->data.F32[i++] = (psF32)value; 138 break; 139 case PS_TYPE_F64: 140 vec->data.F64[i++] = (psF64)value; 141 break; 142 default: 143 *status = 1; 144 psError(PS_ERR_BAD_PARAMETER_VALUE,true, 145 PS_ERRORTEXT_psMetadataIO_TYPE_INVALID, 146 elemType); 147 } 148 149 while(*end==' ' || *end==',') { 150 end++; 151 } 152 inString=end; 153 } 154 } 155 156 return vec; 157 } 158 159 160 static void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts) 161 { 162 psU64 i = 0; 163 char* psTagName = NULL; 164 char *psAttName = NULL; 165 char *psAttValue = NULL; 166 const xmlChar *attName = NULL; 167 const xmlChar *attValue = NULL; 168 psMetadata* md = NULL; 169 psHash* htAtts = NULL; 170 xmlParserCtxtPtr ctxt = NULL; 171 xmlParserInputPtr input = NULL; 172 173 174 // Get and check initial data pointers 175 ctxt = (xmlParserCtxtPtr)ctx; 176 PS_ASSERT_GENERAL_PTR_NON_NULL(ctxt, return); 177 md = (psMetadata*)ctxt->sax->_private; 178 PS_ASSERT_GENERAL_PTR_NON_NULL(md, return); 179 input = (xmlParserInputPtr)ctxt->input; 180 PS_ASSERT_GENERAL_PTR_NON_NULL(input, return); 181 182 // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems 183 psTagName = psStringCopy((const char*)tagName); 184 185 // Metadata containter for housing element attributes used by other SAX events 186 htAtts = psHashAlloc(10); 187 188 189 // Get tag name 190 if(psTagName != NULL) { 191 psHashAdd(htAtts, "tagName", psTagName); 192 } else { 193 PS_ASSERT_GENERAL_PTR_NON_NULL(psTagName, return); 194 psFree(htAtts); 195 psFree(psTagName); 196 return; 197 } 198 199 // Get all attribute names and attribute values 200 if(atts != NULL) { 201 attName = atts[i++]; 202 attValue = atts[i++]; 203 while(attName != NULL) { 204 if(attValue != NULL) { 205 206 // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems 207 psAttName = psStringCopy((const char*)attName); 208 psAttValue = psStringCopy((const char*)attValue); 209 psHashAdd(htAtts, psAttName, psAttValue); 210 psFree(psAttName); 211 psFree(psAttValue); 212 } else { 213 PS_ASSERT_GENERAL_PTR_NON_NULL(psAttValue, return); 214 psFree(htAtts); 215 psFree(psTagName); 216 return; 217 } 218 attName = atts[i++]; 219 attValue = atts[i++]; 220 } 221 } 222 223 // Add attributes to metadata 224 225 psMetadataAdd(md, PS_LIST_TAIL, "htAtts", 226 PS_META_HASH | PS_META_DUPLICATE_OK, 227 NULL, htAtts); 228 229 psFree(psTagName); 230 psFree(htAtts); 231 232 return; 233 } 234 235 static void initMetadataItemXml(void *ctx, char *tagName) 236 { 237 psBool overwrite = false; 238 psBool tempBool = false; 239 psS32 status = 0; 240 psU32 lineNumber = 0; 241 psF64 tempDbl = 0.0; 242 psS32 tempInt = 0.0; 243 psMetadataType mdType = PS_META_UNKNOWN; 244 char *fileName = NULL; 245 char *strName = NULL; 246 char *strType = NULL; 247 char *strValue = NULL; 248 psMetadata* md = NULL; 249 psHash* htAtts = NULL; 250 psMetadataItem *metadataItem = NULL; 251 xmlParserCtxtPtr ctxt = NULL; 252 xmlParserInputPtr input = NULL; 253 254 255 // Get and check initial data pointers 256 ctxt = (xmlParserCtxtPtr)ctx; 257 PS_ASSERT_GENERAL_PTR_NON_NULL(ctxt, return); 258 md = (psMetadata*)ctxt->sax->_private; 259 PS_ASSERT_GENERAL_PTR_NON_NULL(md, return); 260 input = (xmlParserInputPtr)ctxt->input; 261 PS_ASSERT_GENERAL_PTR_NON_NULL(input, return); 262 metadataItem = psMetadataLookup(md, "htAtts"); 263 PS_ASSERT_GENERAL_PTR_NON_NULL(metadataItem, return); 264 PS_ASSERT_GENERAL_PTR_NON_NULL(metadataItem->data.list, return); 265 metadataItem = (psMetadataItem*)psListGet(metadataItem->data.list,PS_LIST_TAIL); 266 htAtts = (psHash*)metadataItem->data.list; 267 PS_ASSERT_GENERAL_PTR_NON_NULL(htAtts, return); 268 fileName = (char*)input->filename; 269 PS_ASSERT_GENERAL_PTR_NON_NULL(fileName, return); 270 lineNumber = input->line; 271 272 // Get attribute name 273 strName = psHashLookup(htAtts, "name"); 274 if(strName == NULL) { 275 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_NO_NAME, lineNumber, fileName); 276 return; 277 } 278 279 // Get attribute type, if there is one 280 strType = psHashLookup(htAtts, "psType"); 281 if(strType!= NULL) { 282 if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psString")) { 283 mdType = PS_META_STR; 284 } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) { 285 mdType = PS_META_BOOL; 286 } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) { 287 mdType = PS_META_S32; 288 } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) { 289 mdType = PS_META_F32; 290 } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) { 291 mdType = PS_META_F64; 292 } else { 293 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strType, lineNumber, 294 fileName); 295 return; 296 } 297 } 298 299 // Get attribute value, if there is one 300 strValue = psHashLookup(htAtts, "value"); 301 302 /* If metadata item is found, and is not a folder node, and overwrite is allowed, then remove 303 existing and allow switch/case below to add new item. If overwrite is false, then report error. If 304 found item is folder node, then psMetadataAdd will automatically add a new child. */ 305 metadataItem = psMetadataLookup(md, "overwrite"); 306 if(metadataItem != NULL) { 307 overwrite = parseBool((char*)strValue, &status); 308 if(status) { 309 status = 0; 310 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType, 311 lineNumber, fileName); 312 } 313 metadataItem = psMetadataLookup(md, strName); 314 if(metadataItem != NULL) { 315 if(metadataItem->type != PS_META_LIST) { 316 if(overwrite) { 317 psMetadataRemove(md, INT_MIN, strName); 318 } else { 319 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber, 320 fileName); 321 return; 322 } 323 } 324 } 325 } 326 327 // Create metadata item and add to metadata 328 switch(mdType) { 329 case PS_META_LIST: 330 psMetadataAdd(md, PS_LIST_TAIL, strName, 331 mdType | PS_META_DUPLICATE_OK, 332 NULL, NULL); 184 item = psMetadataGetAndIncrement(iter); 185 } 186 // xmlSaveFormatFile("xmlfname", *XML, 1); 187 psFree(iter); 188 return XML; 189 } 190 191 //compares strings and returns the correct data type// 192 static psDataType getType(const char *in) 193 { 194 //Returns types S32, F32, F64, STRING, BOOL, or UNKNOWN on ERROR 195 if ( !strncmp(in, "S32", MAXSTR) ) { 196 return(PS_DATA_S32); 197 } else if ( !strncmp(in, "F32", MAXSTR) ) { 198 return(PS_DATA_F32); 199 } else if ( !strncmp(in, "F64", MAXSTR) ) { 200 return(PS_DATA_F64); 201 } else if ( !strncmp(in, "STR", MAXSTR) ) { 202 return(PS_DATA_STRING); 203 } else if ( !strncmp(in, "BOOL", MAXSTR) ) { 204 return(PS_DATA_BOOL); 205 } 206 207 return(PS_DATA_UNKNOWN); 208 } 209 210 static void storeValues(psVector *inVector, char *in, psDataType type) 211 { 212 int i; 213 char *endp; 214 215 switch (type) { 216 case PS_DATA_S32: 217 i = 0; 218 int intValue = 0; 219 while (i < MAXSTR) { 220 intValue = (int)strtol(in, &endp, 10); 221 if ( intValue != 0 ) { 222 inVector->data.S32[i] = intValue; 223 i++; 224 while (!strncmp(endp, ",", 1)) 225 endp++; 226 in = endp; 227 } else 228 i = MAXSTR; 229 } 333 230 break; 334 case PS_META_STR: 335 psMetadataAdd(md, PS_LIST_TAIL, strName, 336 mdType | PS_META_DUPLICATE_OK, 337 NULL, strValue); 231 case PS_DATA_F32: 232 i = 0; 233 float floatValue = 0.0; 234 while (i < MAXSTR) { 235 floatValue = strtof(in, &endp); 236 if ( floatValue != 0.0 ) { 237 inVector->data.F32[i] = floatValue; 238 i++; 239 while (!strncmp(endp, ",", 1)) 240 endp++; 241 in = endp; 242 } else 243 i = MAXSTR; 244 } 245 338 246 break; 339 case PS_META_BOOL: 340 tempBool = parseBool((char*)strValue, &status); 341 if(!status) { 342 psMetadataAdd(md, PS_LIST_TAIL, strName, 343 mdType | PS_META_DUPLICATE_OK, 344 NULL, tempBool); 345 } else { 346 status = 0; 347 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType, 348 lineNumber, fileName); 349 } 350 break; 351 case PS_META_S32: 352 tempInt = (psS32)parseValue((char*)strValue, &status); 353 if(!status) { 354 psMetadataAdd(md, PS_LIST_TAIL, strName, 355 mdType | PS_META_DUPLICATE_OK, 356 NULL, tempInt); 357 } else { 358 status = 0; 359 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType, 360 lineNumber, fileName); 361 } 362 break; 363 case PS_META_F32: 364 case PS_META_F64: 365 tempDbl = parseValue((char*)strValue, &status); 366 if(!status) { 367 psMetadataAdd(md, PS_LIST_TAIL, strName, 368 mdType | PS_META_DUPLICATE_OK, 369 NULL, tempDbl); 370 } else { 371 status = 0; 372 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType, 373 lineNumber, fileName); 247 case PS_DATA_F64: 248 i = 0; 249 double doubleValue = 0.0; 250 while (i < MAXSTR) { 251 doubleValue = strtod(in, &endp); 252 if ( doubleValue != 0.0 ) { 253 inVector->data.F64[i] = doubleValue; 254 i++; 255 while (!strncmp(endp, ",", 1)) 256 endp++; 257 in = endp; 258 } else 259 i = MAXSTR; 374 260 } 375 261 break; 376 262 default: 377 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineNumber, fileName); 378 } // End switch 379 380 return; 381 } 382 383 384 static void initVectorXml(void *ctx, char *tagName) 385 { 386 bool overwrite = false; 387 psS32 status = 0; 388 psU32 lineNumber = 0; 389 psElemType pType = 0; 390 char *strName = NULL; 391 char *strType = NULL; 392 char *strValue = NULL; 393 char *fileName = NULL; 394 psMetadataItem *table = NULL; 395 psMetadataItem *tables = NULL; 396 psMetadataItem *metadataItem = NULL; 397 psVector *vec = NULL; 398 psMetadata* md = NULL; 399 psHash* htAtts = NULL; 400 xmlParserCtxtPtr ctxt = NULL; 401 xmlParserInputPtr input = NULL; 402 403 404 // Get and check initial data pointers 405 ctxt = (xmlParserCtxtPtr)ctx; 406 PS_ASSERT_GENERAL_PTR_NON_NULL(ctxt, return); 407 md = (psMetadata*)ctxt->sax->_private; 408 PS_ASSERT_GENERAL_PTR_NON_NULL(md, return); 409 input = (xmlParserInputPtr)ctxt->input; 410 PS_ASSERT_GENERAL_PTR_NON_NULL(input, return); 411 tables = psMetadataLookup(md, "htAtts"); 412 PS_ASSERT_GENERAL_PTR_NON_NULL(tables, return); 413 PS_ASSERT_GENERAL_PTR_NON_NULL(tables->data.list, return); 414 table = (psMetadataItem*)psListGet(tables->data.list,PS_LIST_TAIL); 415 htAtts = (psHash*)table->data.list; 416 PS_ASSERT_GENERAL_PTR_NON_NULL(htAtts, return); 417 fileName = (char*)input->filename; 418 PS_ASSERT_GENERAL_PTR_NON_NULL(fileName, return); 419 lineNumber = input->line; 420 421 // Get attribute name 422 strName = psHashLookup(htAtts, "name"); 423 if(strName == NULL) { 424 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_NO_NAME, lineNumber, fileName); 425 return; 426 } 427 428 // Get attribute type, if there is one 429 strType = psHashLookup(htAtts, "psType"); 430 if(strType!= NULL) { 431 if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) { 432 pType = PS_TYPE_U8; 433 } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) { 434 pType = PS_TYPE_S32; 435 } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) { 436 pType = PS_TYPE_F32; 437 } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) { 438 pType = PS_TYPE_F64; 263 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 264 PS_ERRORTEXT_psXML_INVALID_DATATYPE); 265 } 266 } 267 268 //Check the xml item for errors. Returns the data type or PS_DATA_UNKNOWN for errors.// 269 static psDataType chkType(xmlNode *node) 270 { 271 //NEED TO CHECK CONTENTS OF EACH ITEM/NODE // 272 //if item then, 273 if(!strncmp(node->name, "item", MAXSTR) || !strncmp(node->name, "ITEM", MAXSTR)) { 274 if (node->properties != NULL && node->properties->name != NULL 275 && node->properties->next != NULL && node->properties->next->name != NULL 276 && node->properties->next->next != NULL 277 && node->properties->next->next->name != NULL) { 278 psDataType type = getType(node->properties->next->children->content); 279 return type; 439 280 } else { 440 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strName, lineNumber, 441 fileName); 442 return; 443 } 444 } 445 446 strValue = psHashLookup(htAtts, "value"); 447 PS_ASSERT_GENERAL_PTR_NON_NULL(strValue, return); 448 449 450 /* If metadata item is found, and is not a folder node, and overwrite is allowed, then remove 451 existing and allow switch/case below to add new item. If overwrite is false, then report error. If 452 found item is folder node, then psMetadataAdd will automatically add a new child. */ 453 metadataItem = psMetadataLookup(md, "overwrite"); 454 if(metadataItem != NULL) { 455 overwrite = parseBool((char*)strValue, &status); 456 if(status) { 457 status = 0; 458 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType, 459 input->line, input->filename); 460 } 461 metadataItem = psMetadataLookup(md, strName); 462 if(metadataItem != NULL) { 463 if(metadataItem->type != PS_META_LIST) { 464 if(overwrite) { 465 psMetadataRemove(md, INT_MIN, strName); 466 } else { 467 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber, 468 fileName); 469 return; 281 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 282 PS_ERRORTEXT_psXML_INVALID_CONTENT); 283 return(PS_DATA_UNKNOWN); 284 } 285 } 286 //if vector then, 287 if(!strncmp(node->name, "vector", MAXSTR) || !strncmp(node->name, "VECTOR", MAXSTR)) { 288 if (node->properties != NULL && node->properties->name != NULL 289 && node->properties->next != NULL && node->properties->next->name != NULL 290 && node->properties->next->next != NULL 291 && node->properties->next->next->name != NULL) { 292 return(PS_DATA_VECTOR); 293 } else { 294 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 295 PS_ERRORTEXT_psXML_INVALID_CONTENT); 296 return(PS_DATA_UNKNOWN); 297 } 298 299 } 300 //if metadata then, 301 if(!strncmp(node->name, "metadata", MAXSTR)) { 302 if (node->properties != NULL && node->properties->name 303 && node->properties->next != NULL && node->properties->next->name != NULL) { 304 return(PS_DATA_METADATA); 305 } else { 306 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 307 PS_ERRORTEXT_psXML_INVALID_CONTENT); 308 return(PS_DATA_UNKNOWN); 309 } 310 } 311 return(PS_DATA_UNKNOWN); 312 } 313 314 //Sorts the xmlDocPtr data into a usable Metadata structure. Transverses an xml tree.// 315 static psMetadata *xml2metadata(xmlNode *nodePtr, int nodeNum) 316 { 317 psMetadata *meta = NULL; 318 xmlNode *cur_node = NULL; 319 char name[MAXSTR]; 320 char content[MAXSTR]; 321 // char *name = NULL; 322 // char *content = NULL; 323 psDataType type = PS_DATA_UNKNOWN; 324 psDataType elemType = PS_DATA_UNKNOWN; 325 326 meta = psMetadataAlloc(); 327 cur_node = nodePtr; 328 329 // for ( cur_node = nodePtr; cur_node != NULL; cur_node = cur_node->next ) 330 while (cur_node != NULL) { 331 if ( cur_node->type == XML_ELEMENT_NODE ) { 332 //if the root node isn't a metadata// 333 if ( nodeNum == 0 && strncmp(cur_node->name, "metadata", MAXSTR) ) { 334 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 335 PS_ERRORTEXT_psXML_INVALID_CONTENT); 336 psFree(meta); 337 return NULL; 338 } 339 340 if ( nodeNum != 0 ) { 341 type = chkType(cur_node); 342 //name = NULL; 343 //content = NULL; 344 switch ( type ) { 345 case PS_DATA_S32: 346 strncpy(name, (char*)cur_node->properties->children->content, MAXSTR); 347 strncpy(content, 348 (char*)cur_node->properties->next->next->children->content, MAXSTR); 349 psMetadataAddS32(meta, PS_LIST_TAIL, name, "", 350 (int)strtol(content, NULL, 10)); 351 break; 352 case PS_DATA_F32: 353 strncpy(name, cur_node->properties->children->content, MAXSTR); 354 strncpy(content, 355 cur_node->properties->next->next->children->content, MAXSTR); 356 psMetadataAddF32(meta, PS_LIST_TAIL, name, "", strtof(content, NULL)); 357 break; 358 case PS_DATA_F64: 359 strncpy(name, cur_node->properties->children->content, MAXSTR); 360 strncpy(content, 361 cur_node->properties->next->next->children->content, MAXSTR); 362 psMetadataAddF64(meta, PS_LIST_TAIL, name, "", strtod(content, NULL)); 363 break; 364 case PS_DATA_STRING: 365 strncpy(name, cur_node->properties->children->content, MAXSTR); 366 psMetadataAddStr(meta, PS_LIST_TAIL, name, "", 367 cur_node->properties->next->next->children->content); 368 break; 369 case PS_DATA_VECTOR: 370 strncpy(name, cur_node->properties->children->content, MAXSTR); 371 strncpy(content, 372 cur_node->properties->next->next->children->content, MAXSTR); 373 elemType = getType(cur_node->properties->next->children->content); 374 if (elemType == PS_DATA_UNKNOWN || elemType == PS_DATA_STRING 375 || elemType == PS_DATA_BOOL) { 376 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 377 PS_ERRORTEXT_psXML_INVALID_DATATYPE); 378 psFree(meta); 379 return NULL; 380 } 381 382 psVector *vec = psVectorAlloc(strlen(content), elemType); 383 storeValues(vec, content, elemType); 384 psMetadataAddVector(meta, PS_LIST_TAIL, name, "", vec); 385 psFree(vec); 386 break; 387 case PS_DATA_METADATA: 388 strncpy(name, cur_node->properties->children->content, MAXSTR); 389 // psMetadata *temp = psMetadataAlloc(); 390 psMetadata *temp = NULL; 391 temp = xml2metadata(cur_node->children, nodeNum); 392 psMetadataAddMetadata(meta, PS_LIST_TAIL, name, "", temp); 393 psFree(temp); 394 break; 395 case PS_DATA_BOOL: 396 strncpy(name, cur_node->properties->children->content, MAXSTR); 397 strncpy(content, 398 cur_node->properties->next->next->children->content, MAXSTR); 399 if ( !strncmp(content, "true", MAXSTR) || 400 !strncmp(content, "TRUE", MAXSTR) || 401 !strncmp(content, "T", MAXSTR) || 402 !strncmp(content, "t", MAXSTR) ) { 403 psMetadataAddBool(meta, PS_LIST_TAIL, name, "", true); 404 } else if ( !strncmp(content, "false", MAXSTR) || 405 !strncmp(content, "FALSE", MAXSTR) || 406 !strncmp(content, "F", MAXSTR) || 407 !strncmp(content, "f", MAXSTR) ) { 408 psMetadataAddBool(meta, PS_LIST_TAIL, name, "", false); 409 } else { 410 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 411 PS_ERRORTEXT_psXML_INVALID_CONTENT); 412 psFree(meta); 413 return NULL; 414 } 415 break; 416 case PS_DATA_UNKNOWN: 417 default: 418 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 419 PS_ERRORTEXT_psXML_INVALID_DATATYPE); 420 psFree(meta); //XXX: Do I really need this? 421 return NULL; 470 422 } 423 nodeNum++; 424 } else //if root node, then increment nodeNum and go to children// 425 { 426 nodeNum++; 427 cur_node = cur_node->children; 471 428 } 472 429 } 473 } 474 475 // Get value 476 vec = parseVector((char*)strValue, pType, &status); 477 if(!status) { 478 psMetadataAdd(md, PS_LIST_TAIL, strName+1, 479 PS_META_VEC | PS_META_DUPLICATE_OK, 480 NULL, vec); 481 } else { 482 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType, 483 lineNumber, fileName); 484 } 485 psFree(vec); 486 } 487 488 static void saxEndElement(void *ctx, const xmlChar *tagName) 489 { 490 char *psStartTagName = NULL; 491 char *psEndTagName = NULL; 492 psMetadata* md = NULL; 493 psHash* htAtts = NULL; 494 psMetadataItem *table = NULL; 495 psMetadataItem *tables = NULL; 496 xmlParserCtxtPtr ctxt = NULL; 497 xmlParserInputPtr input = NULL; 498 499 500 // Get and check initial data pointers 501 ctxt = (xmlParserCtxtPtr)ctx; 502 PS_ASSERT_GENERAL_PTR_NON_NULL(ctxt, return); 503 md = (psMetadata*)ctxt->sax->_private; 504 PS_ASSERT_GENERAL_PTR_NON_NULL(md, return); 505 input = (xmlParserInputPtr)ctxt->input; 506 PS_ASSERT_GENERAL_PTR_NON_NULL(input, return); 507 tables = psMetadataLookup(md, "htAtts"); 508 PS_ASSERT_GENERAL_PTR_NON_NULL(tables, return); 509 PS_ASSERT_GENERAL_PTR_NON_NULL(tables->data.list, return); 510 table = (psMetadataItem*)psListGet(tables->data.list,PS_LIST_TAIL); 511 htAtts = (psHash*)table->data.list; 512 PS_ASSERT_GENERAL_PTR_NON_NULL(htAtts, return); 513 514 // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems 515 psEndTagName = psStringCopy((const char*)tagName); 516 517 // Compare start and end tag names 518 psStartTagName = psHashLookup(htAtts, "tagName"); 519 PS_ASSERT_GENERAL_PTR_NON_NULL(psStartTagName, return); 520 if(strcmp(psEndTagName, psStartTagName)) { 521 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TAG_MISMATCH, psStartTagName, psEndTagName); 522 } 523 524 // Initialize psLib structs 525 if(!strcmp(psEndTagName, "psMetadataItem")) { 526 initMetadataItemXml(ctx, psEndTagName); 527 } else if(!strcmp(psEndTagName, "psVector")) { 528 initVectorXml(ctx, psEndTagName); 529 } else if(strcmp(psEndTagName, "psRoot")) { 530 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TAG_UNKNOWN, psEndTagName); 531 } 532 533 // Free temporary metadata item and its hash table 534 psListRemove(tables->data.list, PS_LIST_TAIL); 535 536 psFree(psEndTagName); 537 538 return; 539 } 540 541 psMetadata* psMetadataConfigParseXml(psMetadata* md, psU32 *nFail, const char *fileName, psBool overwrite) 542 { 543 xmlSAXHandler saxHandler; 544 545 546 // Error checks 547 PS_ASSERT_PTR_NON_NULL(fileName, NULL); 548 549 // Allocate metadata if necessary 550 if (md == NULL) { 551 md = psMetadataAlloc(); 552 } 553 554 // Sax handler initializations 555 saxHandler.internalSubset = NULL; 556 saxHandler.isStandalone = NULL; 557 saxHandler.hasInternalSubset = NULL; 558 saxHandler.hasExternalSubset = NULL; 559 saxHandler.resolveEntity = NULL; 560 saxHandler.getEntity = NULL; 561 saxHandler.entityDecl = NULL; 562 saxHandler.notationDecl = NULL; 563 saxHandler.attributeDecl = NULL; 564 saxHandler.elementDecl = NULL; 565 saxHandler.unparsedEntityDecl = NULL; 566 saxHandler.setDocumentLocator = NULL; 567 saxHandler.startDocument = NULL; 568 saxHandler.endDocument = NULL; 569 saxHandler.startElement = saxStartElement; 570 saxHandler.endElement = saxEndElement; 571 saxHandler.reference = NULL; 572 saxHandler.characters = NULL; 573 saxHandler.ignorableWhitespace = NULL; 574 saxHandler.processingInstruction = NULL; 575 saxHandler.comment = NULL; 576 saxHandler.warning = xmlParserError; 577 saxHandler.error = xmlParserError; 578 saxHandler.fatalError = xmlParserError; 579 saxHandler.getParameterEntity = NULL; 580 saxHandler.cdataBlock = NULL; 581 saxHandler.externalSubset = NULL; 582 saxHandler.initialized = 1; 583 saxHandler._private = md; 584 saxHandler.startElementNs = NULL; 585 saxHandler.endElementNs = NULL; 586 saxHandler.serror = NULL; 587 588 // Parse XML file 589 if (xmlSAXUserParseFile(&saxHandler, NULL, fileName)) { 590 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_OPEN_FAILED, fileName); 591 return NULL; 592 } 593 594 // Parser and memory cleanups for libxml2 430 cur_node = cur_node->next; 431 } 432 psFree(cur_node); 433 return meta; 434 } 435 436 psMetadata *psXMLDocToMetadata(const psXMLDoc *doc) 437 { 438 PS_ASSERT_PTR_NON_NULL(doc, NULL); 439 // psMetadata *md = psMetadataAlloc(); 440 psMetadata *md = NULL; 441 xmlNode *root_element = NULL; 442 //XXX: doc changed to *doc 443 root_element = xmlDocGetRootElement(*doc); 444 md = xml2metadata(root_element, 0); 445 return md; 446 } 447 448 psXMLDoc *psXMLParseFile(const char *filename) 449 { 450 451 PS_ASSERT_PTR_NON_NULL(filename, NULL); 452 psXMLDoc *XML; 453 XML = psXMLDocAlloc(); 454 *XML = xmlReadFile(filename, NULL, 0); 455 595 456 xmlCleanupParser(); 596 457 xmlMemoryDump(); 597 598 return md; 599 } 458 return XML; 459 } 460 461 bool psXMLDocToFile(const psXMLDoc *doc, 462 const char *filename) 463 { 464 PS_ASSERT_PTR_NON_NULL(doc, 0); 465 PS_ASSERT_PTR_NON_NULL(filename, 0); 466 FILE *file; 467 if( (file = fopen(filename, "w")) == NULL ) { 468 psError(PS_ERR_IO, true, PS_ERRORTEXT_psXML_IO_FILE_OPEN_FAILED, filename); 469 return false; 470 } 471 472 xmlDocDump(file, *doc); 473 fclose(file); 474 return true; 475 } 476 477 psXMLDoc *psXMLParseMem(const char *buffer, 478 int size) 479 { 480 PS_ASSERT_PTR_NON_NULL(buffer, NULL); 481 PS_ASSERT_INT_NONZERO(size, NULL); 482 char *URL = "new.xml"; 483 psXMLDoc *XML; 484 XML = psXMLDocAlloc(); 485 *XML = xmlReadMemory(buffer, size, URL, NULL, 0); 486 487 xmlCleanupParser(); 488 xmlMemoryDump(); 489 490 return XML; 491 } 492 493 bool psXMLDocToMem(const psXMLDoc *doc, 494 char *buffer) 495 { 496 PS_ASSERT_PTR_NON_NULL(doc, 0); 497 int bufferSize; 498 xmlChar *buff; 499 500 xmlDocDumpMemory(*doc, &buff, &bufferSize); 501 if ( MAXVEC < strlen((char *)buff) ) { 502 psError(PS_ERR_LOCATION_INVALID, true, PS_ERRORTEXT_psXML_BUFFER_TOO_SMALL); 503 // xmlFree(buff); 504 return false; 505 } 506 strncpy(buffer, buff, MAXVEC); 507 xmlFree(buff); 508 509 return true; 510 } 511 512 psXMLDoc *psXMLParseFD(int fd) 513 { 514 PS_ASSERT_INT_NONNEGATIVE(fd, NULL); 515 char *URL = "new.xml"; 516 psXMLDoc *XML; 517 XML = psXMLDocAlloc(); 518 *XML = xmlReadFd(fd, URL, NULL, 0); 519 520 xmlCleanupParser(); 521 xmlMemoryDump(); 522 523 return XML; 524 } 525 526 bool psXMLDocToFD(const psXMLDoc *doc, 527 int fd) 528 { 529 PS_ASSERT_PTR_NON_NULL(doc, 0); 530 PS_ASSERT_INT_NONNEGATIVE(fd, 0); 531 532 char buf[MAXBUF]; 533 int n; 534 if ( psXMLDocToMem(doc, buf) ) { 535 n = strlen(buf); 536 write(fd, buf, n); 537 } else { 538 psError(PS_ERR_LOCATION_INVALID, true, PS_ERRORTEXT_psXML_BUFFER_TOO_SMALL); 539 return false; 540 } 541 return true; 542 } -
trunk/psLib/src/xml/psXML.h
r4540 r4786 1 1 /** @file psXML.h 2 2 * 3 * @brief Contains XML functions.3 * @brief Contains basic XML definitions and operations 4 4 * 5 * This file defines functions to read metadata from an XML file. 5 * This file defines the basic type for an XML struct and functions useful 6 * in creation and usage of XML documents/files. 6 7 * 7 8 * @ingroup XML 8 9 * 9 * @author Ross Harman, MHPCC 10 * @author Robert DeSonia, MHPCC 10 * @author David Robbins, MHPCC 11 11 * 12 * @version $Revision: 1.1 6$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-0 7-12 19:12:01$12 * @version $Revision: 1.17 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-08-16 20:13:20 $ 14 14 * 15 * Copyright 200 4-2005 Maui High Performance Computing Center, University of Hawaii15 * Copyright 2005 Maui High Performance Computing Center, University of Hawaii 16 16 */ 17 17 18 #ifndef PS_XML_H 18 19 #define PS_XML_H 19 20 21 //#include <libxml/parser.h> 22 #include <libxml/tree.h> 23 #include <string.h> 24 #include <ctype.h> 25 #include <limits.h> 26 20 27 #include "psMetadata.h" 21 28 #include "psMetadataConfig.h" 29 #include "psMemory.h" 30 #include "psError.h" 31 #include "psString.h" 32 #include "psConstants.h" 33 #include "psErrorText.h" 34 22 35 23 36 /// @addtogroup XML 24 37 /// @{ 25 38 26 psMetadata* psMetadataConfigParseXml( 27 psMetadata* md, ///< Resulting metadata from read. 28 psU32 *nFail, ///< Number of failed lines. 29 const char *fileName, ///< Name of file to read. 30 psBool overwrite ///< Allow overwrite of duplicate specifications. 39 /** XML wrapper pointing to an XML document in memory */ 40 typedef xmlDocPtr psXMLDoc; 41 42 43 /*****************************************************************************/ 44 45 /* FUNCTION PROTOTYPES */ 46 47 /*****************************************************************************/ 48 49 /** Allocates a new psXMLDoc 50 * 51 * @return psXMLDoc* a new psXMLDoc object 52 */ 53 psXMLDoc *psXMLDocAlloc(void); 54 55 /** Converts a psMetadata data structure to a complete psXMLDoc (in memory) 56 * 57 * @return psXMLDoc* Pointer to XML document from read 58 */ 59 psXMLDoc *psMetadataToXMLDoc( 60 const psMetadata *md ///< psMetadata structure to read 61 ); 62 63 /** Converts a complete psXMLDoc (in memory) to a psMetadata data structure 64 * 65 * @return psMetadata* Pointer to psMetadata data structure from read 66 */ 67 psMetadata *psXMLDocToMetadata( 68 const psXMLDoc *doc ///< psXMLDoc to read 69 ); 70 71 /** Loads the data in a named file into a complete psXMLDoc (in memory) 72 * 73 * @return psXMLDoc* Pointer to resulting XML document from read 74 */ 75 psXMLDoc *psXMLParseFile( 76 const char *filename ///< Filename of file to be read 77 ); 78 79 /** Writes out a complete psXMLDoc (in memory) to a named file 80 * 81 * @return bool: True on success or false otherwise. 82 */ 83 bool psXMLDocToFile( 84 const psXMLDoc *doc, ///< psXMLDoc to read 85 const char *filename ///< Filename of file to be written 86 ); 87 88 /** Accepts a block of memory and parses it into a complete psXMLDoc (also in memory) 89 * 90 * @return psXMLDoc* Pointer to resulting XML document from read 91 */ 92 psXMLDoc *psXMLParseMem( 93 const char *buffer, ///< Buffer to read 94 int size ///< Size of buffer 95 ); 96 97 /** Accepts a complete psXMLDoc (in memory) and parses it into a block of memory 98 * 99 * @return bool: True on success or false otherwise. 100 */ 101 bool psXMLDocToMem( 102 const psXMLDoc *doc, ///< psXMLDoc to read 103 char *buffer ///< Buffer to write 104 ); 105 106 /** Reads from a file descriptor and converts the incoming data to a complete 107 * psXMLDoc (in memory) 108 * 109 * @return psXMLDoc* Pointer to resulting XML document from read 110 */ 111 psXMLDoc *psXMLParseFD( 112 int fd ///< File descriptor to read 113 ); 114 115 /** Reads from a complete psXMLDoc (in memory) and writes it to a file descriptor 116 * 117 * @return bool: True on success or false otherwise. 118 */ 119 bool psXMLDocToFD( 120 const psXMLDoc *doc, ///< psXMLDoc to read 121 int fd ///< File descriptor to write 31 122 ); 32 123 … … 34 125 35 126 #endif // #ifndef PS_XML_H 127
Note:
See TracChangeset
for help on using the changeset viewer.
