IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Nov 29, 2004, 2:29:06 PM (22 years ago)
Author:
harman
Message:

Added XML parser

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/collections/psMetadataIO.c

    r2318 r2521  
    99*  @author Ross Harman, MHPCC
    1010*
    11 *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
    12 *  @date $Date: 2004-11-10 18:26:46 $
     11*  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
     12*  @date $Date: 2004-11-30 00:27:40 $
    1313*
    1414*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    1515*/
    1616
     17#include <libxml/parser.h>
    1718#include <fitsio.h>
    1819#include <string.h>
     
    3233#include "psAstronomyErrors.h"
    3334
     35
     36typedef struct
     37{
     38    int y;
     39}
     40myStruct;
    3441
    3542/******************************************************************************/
     
    103110/*****************************************************************************/
    104111
     112void p_saxEndElement(void *ctx, const xmlChar *tagName);
     113void p_psInitVectorXml(void *ctx, char *tagName);
     114void p_psInitMetadataItemXml(void *ctx, char *tagName);
     115void p_saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts);
    105116
    106117/** Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
     
    329340        break;
    330341    default:
    331         psError(PS_ERR_BAD_PARAMETER_TYPE,true,
    332                 PS_ERRORTEXT_psMetadata_METATYPE_INVALID,
    333                 (int)type);
     342        psError(PS_ERR_BAD_PARAMETER_TYPE,true, PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type);
    334343    }
    335344}
     
    680689    return failedLines;
    681690}
     691
     692void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts)
     693{
     694    psU64 i = 0;
     695    psU64 lineNumber = 0;
     696    char* psTagName = NULL;
     697    char *psAttName = NULL;
     698    char *psAttValue = NULL;
     699    const xmlChar *attName = NULL;
     700    const xmlChar *attValue = NULL;
     701    psMetadata* md = NULL;
     702    psHash* htAtts = NULL;
     703    xmlParserCtxtPtr ctxt = NULL;
     704    xmlParserInputPtr input = NULL;
     705
     706
     707    // Get and check initial data pointers
     708    ctxt = (xmlParserCtxtPtr)ctx;
     709    PS_PTR_CHECK_NULL_GENERAL(ctxt, return);
     710    md = (psMetadata*)ctxt->sax->_private;
     711    PS_PTR_CHECK_NULL_GENERAL(md, return);
     712    input = (xmlParserInputPtr)ctxt->input;
     713    PS_PTR_CHECK_NULL_GENERAL(input, return);
     714
     715    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
     716    psTagName = psStringCopy(tagName);
     717
     718    // Metadata containter for housing element attributes used by other SAX events
     719    htAtts = psHashAlloc(10);
     720
     721    // Get tag name
     722    if(psTagName != NULL) {
     723        psHashAdd(htAtts, "tagName", psTagName);
     724    } else {
     725        PS_PTR_CHECK_NULL_GENERAL(psTagName, return);
     726        psFree(htAtts);
     727        psFree(psTagName);
     728        return;
     729    }
     730
     731    // Get all attribute names and attribute values
     732    if(atts != NULL) {
     733        attName = atts[i++];
     734        attValue = atts[i++];
     735        while(attName != NULL) {
     736            if(attValue != NULL) {
     737
     738                // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
     739                psAttName = psStringCopy(attName);
     740                psAttValue = psStringCopy(attValue);
     741                psHashAdd(htAtts, psAttName, psAttValue);
     742                psFree(psAttName);
     743                psFree(psAttValue);
     744            } else {
     745                PS_PTR_CHECK_NULL_GENERAL(psAttValue, return);
     746                psFree(htAtts);
     747                psFree(psTagName);
     748                return;
     749            }
     750            attName = atts[i++];
     751            attValue = atts[i++];
     752        }
     753    }
     754
     755    // Add attributes to metadata
     756    psMetadataAdd(md, PS_LIST_TAIL, "htAtts", PS_META_HASH, NULL, htAtts);
     757
     758    psFree(psTagName);
     759
     760    return;
     761}
     762
     763void p_psInitMetadataItemXml(void *ctx, char *tagName)
     764{
     765    psBool overwrite = false;
     766    psBool tempBool = false;
     767    psS32 status = 0;
     768    psU64 lineNumber = 0;
     769    psF64 tempDbl = 0.0;
     770    psS32 tempInt = 0.0;
     771    psElemType elemType;
     772    psMetadataType mdType;
     773    char *fileName = NULL;
     774    char *strName = NULL;
     775    char *strType = NULL;
     776    char *strValue = NULL;
     777    psMetadata* md = NULL;
     778    psHash* htAtts = NULL;
     779    psMetadataItem *metadataItem = NULL;
     780    xmlParserCtxtPtr ctxt = NULL;
     781    xmlParserInputPtr input = NULL;
     782
     783
     784    // Get and check initial data pointers
     785    ctxt = (xmlParserCtxtPtr)ctx;
     786    PS_PTR_CHECK_NULL_GENERAL(ctxt, return);
     787    md = (psMetadata*)ctxt->sax->_private;
     788    PS_PTR_CHECK_NULL_GENERAL(md, return);
     789    input = (xmlParserInputPtr)ctxt->input;
     790    PS_PTR_CHECK_NULL_GENERAL(input, return);
     791    metadataItem = psMetadataLookup(md, "htAtts");
     792    PS_PTR_CHECK_NULL_GENERAL(metadataItem, return);
     793    PS_PTR_CHECK_NULL_GENERAL(metadataItem->items, return);
     794    psListSetIterator(metadataItem->items, PS_LIST_TAIL);
     795    metadataItem = (psMetadataItem*)psListGetCurrent(metadataItem->items);
     796    htAtts = (psHash*)metadataItem->data.V;
     797    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
     798    fileName = (char*)input->filename;
     799    PS_PTR_CHECK_NULL_GENERAL(fileName, return);
     800    lineNumber = input->line;
     801
     802    // Get attribute name
     803    strName = psHashLookup(htAtts, "name");
     804    if(strName == NULL) {
     805        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_NO_NAME, lineNumber, fileName);
     806        return;
     807    }
     808
     809    // Get attribute type, if there is one
     810    strType = psHashLookup(htAtts, "psType");
     811    if(strType!= NULL) {
     812        if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psString")) {
     813            mdType = PS_META_STR;
     814            elemType = PS_TYPE_PTR;
     815        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
     816            mdType = PS_META_BOOL;
     817            elemType = PS_TYPE_U8;
     818        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
     819            mdType = PS_META_S32;
     820            elemType = PS_TYPE_S32;
     821        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
     822            mdType = PS_META_F32;
     823            elemType = PS_TYPE_F32;
     824        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
     825            mdType = PS_META_F64;
     826            elemType = PS_TYPE_F64;
     827        } else {
     828            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strType, lineNumber,
     829                    fileName);
     830            return;
     831        }
     832    }
     833
     834    // Get attribute value, if there is one
     835    strValue = psHashLookup(htAtts, "value");
     836
     837    /* If metadata item is found, and is not a folder node, and overwrite is allowed, then remove
     838    existing and allow switch/case below to add new item. If overwrite is false, then report error. If
     839    found item is folder node, then psMetadataAdd will automatically add a new child. */
     840    metadataItem = psMetadataLookup(md, "overwrite");
     841    if(metadataItem != NULL) {
     842        overwrite = parseBool((char*)strValue, &status);
     843        if(status) {
     844            status = 0;
     845            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
     846                    lineNumber, fileName);
     847        }
     848        metadataItem = psMetadataLookup(md, strName);
     849        if(metadataItem != NULL) {
     850            if(metadataItem->type != PS_META_ITEM_SET) {
     851                if(overwrite) {
     852                    psMetadataRemove(md, PS_LIST_UNKNOWN, strName);
     853                } else {
     854                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
     855                            fileName);
     856                    return;
     857                }
     858            }
     859        }
     860    }
     861
     862    // Create metadata item and add to metadata
     863    switch(mdType) {
     864    case PS_META_ITEM_SET:
     865        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
     866        break;
     867    case PS_META_BOOL:
     868        tempBool = parseBool((char*)strValue, &status);
     869        if(!status) {
     870            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempBool);
     871        } else {
     872            status = 0;
     873            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
     874                    lineNumber, fileName);
     875        }
     876        break;
     877    case PS_META_S32:
     878        tempInt = (psS32)parseValue((char*)strValue, &status);
     879        if(!status) {
     880            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempInt);
     881        } else {
     882            status = 0;
     883            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
     884                    lineNumber, fileName);
     885        }
     886        break;
     887    case PS_META_F32:
     888    case PS_META_F64:
     889        tempDbl = parseValue((char*)strValue, &status);
     890        if(!status) {
     891            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, tempDbl);
     892        } else {
     893            status = 0;
     894            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
     895                    lineNumber, fileName);
     896        }
     897        break;
     898    case PS_META_STR:
     899        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, strValue);
     900        break;
     901    default:
     902        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineNumber, fileName);
     903    } // End switch
     904
     905    return;
     906}
     907
     908
     909void p_psInitVectorXml(void *ctx, char *tagName)
     910{
     911    bool overwrite = false;
     912    psS32 status = 0;
     913    psU64 lineNumber = 0;
     914    psElemType elemType;
     915    psMetadataType mdType;
     916    char *strName = NULL;
     917    char *strType = NULL;
     918    char *strValue = NULL;
     919    char *fileName = NULL;
     920    psMetadataItem *table = NULL;
     921    psMetadataItem *tables = NULL;
     922    psMetadataItem *metadataItem = NULL;
     923    psVector *vec = NULL;
     924    psMetadata* md = NULL;
     925    psHash* htAtts = NULL;
     926    xmlParserCtxtPtr ctxt = NULL;
     927    xmlParserInputPtr input = NULL;
     928
     929
     930    // Get and check initial data pointers
     931    ctxt = (xmlParserCtxtPtr)ctx;
     932    PS_PTR_CHECK_NULL_GENERAL(ctxt, return);
     933    md = (psMetadata*)ctxt->sax->_private;
     934    PS_PTR_CHECK_NULL_GENERAL(md, return);
     935    input = (xmlParserInputPtr)ctxt->input;
     936    PS_PTR_CHECK_NULL_GENERAL(input, return);
     937    tables = psMetadataLookup(md, "htAtts");
     938    PS_PTR_CHECK_NULL_GENERAL(tables, return);
     939    PS_PTR_CHECK_NULL_GENERAL(tables->items, return);
     940    psListSetIterator(tables->items, PS_LIST_TAIL);
     941    table = (psMetadataItem*)psListGetCurrent(tables->items);
     942    htAtts = (psHash*)table->data.V;
     943    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
     944    fileName = (char*)input->filename;
     945    PS_PTR_CHECK_NULL_GENERAL(fileName, return);
     946    lineNumber = input->line;
     947
     948    // Get attribute name
     949    strName = psHashLookup(htAtts, "name");
     950    if(strName == NULL) {
     951        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_NO_NAME, lineNumber, fileName);
     952        return;
     953    }
     954
     955    // Get attribute type, if there is one
     956    strType = psHashLookup(htAtts, "psType");
     957    if(strType!= NULL) {
     958        if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psString")) {
     959            mdType = PS_META_STR;
     960            elemType = PS_TYPE_PTR;
     961        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
     962            mdType = PS_META_BOOL;
     963            elemType = PS_TYPE_U8;
     964        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
     965            mdType = PS_META_S32;
     966            elemType = PS_TYPE_S32;
     967        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
     968            mdType = PS_META_F32;
     969            elemType = PS_TYPE_F32;
     970        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
     971            mdType = PS_META_F64;
     972            elemType = PS_TYPE_F64;
     973        } else {
     974            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strName, lineNumber,
     975                    fileName);
     976            return;
     977        }
     978    }
     979
     980    strValue = psHashLookup(htAtts, "value");
     981    PS_PTR_CHECK_NULL_GENERAL(strValue, return);
     982
     983
     984    /* If metadata item is found, and is not a folder node, and overwrite is allowed, then remove
     985    existing and allow switch/case below to add new item. If overwrite is false, then report error. If
     986    found item is folder node, then psMetadataAdd will automatically add a new child. */
     987    metadataItem = psMetadataLookup(md, "overwrite");
     988    if(metadataItem != NULL) {
     989        overwrite = parseBool((char*)strValue, &status);
     990        if(status) {
     991            status = 0;
     992            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
     993                    input->line, input->filename);
     994        }
     995        metadataItem = psMetadataLookup(md, strName);
     996        if(metadataItem != NULL) {
     997            if(metadataItem->type != PS_META_ITEM_SET) {
     998                if(overwrite) {
     999                    psMetadataRemove(md, PS_LIST_UNKNOWN, strName);
     1000                } else {
     1001                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
     1002                            fileName);
     1003                    return;
     1004                }
     1005            }
     1006        }
     1007    }
     1008
     1009    // Get value
     1010    vec = parseVector((char*)strValue, elemType, &status);
     1011    if(!status) {
     1012        psMetadataAdd(md, PS_LIST_TAIL, strName+1, mdType, NULL, vec);
     1013    } else {
     1014        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
     1015                lineNumber, fileName);
     1016    }
     1017    psFree(vec);
     1018}
     1019
     1020void saxEndElement(void *ctx, const xmlChar *tagName)
     1021{
     1022    psU64 lineNumber = 0;
     1023    char *psStartTagName = NULL;
     1024    char *psEndTagName = NULL;
     1025    psMetadataType mdType;
     1026    psMetadata* md = NULL;
     1027    psHash* htAtts = NULL;
     1028    psMetadataItem *table = NULL;
     1029    psMetadataItem *tables = NULL;
     1030    xmlParserCtxtPtr ctxt = NULL;
     1031    xmlParserInputPtr input = NULL;
     1032
     1033
     1034    // Get and check initial data pointers
     1035    ctxt = (xmlParserCtxtPtr)ctx;
     1036    PS_PTR_CHECK_NULL_GENERAL(ctxt, return);
     1037    md = (psMetadata*)ctxt->sax->_private;
     1038    PS_PTR_CHECK_NULL_GENERAL(md, return);
     1039    input = (xmlParserInputPtr)ctxt->input;
     1040    PS_PTR_CHECK_NULL_GENERAL(input, return);
     1041    tables = psMetadataLookup(md, "htAtts");
     1042    PS_PTR_CHECK_NULL_GENERAL(tables, return);
     1043    PS_PTR_CHECK_NULL_GENERAL(tables->items, return);
     1044    psListSetIterator(tables->items, PS_LIST_TAIL);
     1045    table = (psMetadataItem*)psListGetCurrent(tables->items);
     1046    htAtts = (psHash*)table->data.V;
     1047    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
     1048
     1049    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
     1050    psEndTagName = psStringCopy(tagName);
     1051
     1052    // Compare start and end tag names
     1053    psStartTagName = psHashLookup(htAtts, "tagName");
     1054    PS_PTR_CHECK_NULL_GENERAL(psStartTagName, return);
     1055    if(strcmp(psEndTagName, psStartTagName)) {
     1056        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TAG_MISMATCH, psStartTagName, psEndTagName);
     1057    }
     1058
     1059    // Initialize psLib structs
     1060    if(!strcmp(psEndTagName, "psMetadataItem")) {
     1061        p_psInitMetadataItemXml(ctx, psEndTagName);
     1062    } else if(!strcmp(psEndTagName, "psVector")) {
     1063        p_psInitVectorXml(ctx, psEndTagName);
     1064    } else if(strcmp(psEndTagName, "psRoot")) {
     1065        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TAG_UNKNOWN, psEndTagName);
     1066    }
     1067
     1068    // Free temporary metadata item and its hash table
     1069    psListRemove(tables->items, PS_LIST_TAIL, table);
     1070
     1071    psFree(psEndTagName);
     1072
     1073    return;
     1074}
     1075
     1076psS32 psMetadataParseConfigXml(psMetadata** md, const char *fileName)
     1077{
     1078    psS32 status = 0;
     1079    FILE *fp = NULL;
     1080    xmlSAXHandler saxHandler;
     1081
     1082
     1083    // Error checks
     1084    PS_PTR_CHECK_NULL(fileName,-1);
     1085
     1086    // Allocate metadata if necessary
     1087    if (*md == NULL) {
     1088        *md = psMetadataAlloc();
     1089    }
     1090
     1091    // Sax handler initializations
     1092    saxHandler.internalSubset           = NULL;
     1093    saxHandler.isStandalone             = NULL;
     1094    saxHandler.hasInternalSubset        = NULL;
     1095    saxHandler.hasExternalSubset        = NULL;
     1096    saxHandler.resolveEntity            = NULL;
     1097    saxHandler.getEntity                = NULL;
     1098    saxHandler.entityDecl               = NULL;
     1099    saxHandler.notationDecl             = NULL;
     1100    saxHandler.attributeDecl            = NULL;
     1101    saxHandler.elementDecl              = NULL;
     1102    saxHandler.unparsedEntityDecl       = NULL;
     1103    saxHandler.setDocumentLocator       = NULL;
     1104    saxHandler.startDocument            = NULL;
     1105    saxHandler.endDocument              = NULL;
     1106    saxHandler.startElement             = saxStartElement;
     1107    saxHandler.endElement               = saxEndElement;
     1108    saxHandler.reference                = NULL;
     1109    saxHandler.characters               = NULL;
     1110    saxHandler.ignorableWhitespace      = NULL;
     1111    saxHandler.processingInstruction    = NULL;
     1112    saxHandler.comment                  = NULL;
     1113    saxHandler.warning                  = xmlParserError;
     1114    saxHandler.error                    = xmlParserError;
     1115    saxHandler.fatalError               = xmlParserError;
     1116    saxHandler.getParameterEntity       = NULL;
     1117    saxHandler.cdataBlock               = NULL;
     1118    saxHandler.externalSubset           = NULL;
     1119    saxHandler.initialized              = 1;
     1120    saxHandler._private                 = *md;
     1121    saxHandler.startElementNs           = NULL;
     1122    saxHandler.endElementNs             = NULL;
     1123    saxHandler.serror                   = NULL;
     1124
     1125    // Parse XML file
     1126    if (xmlSAXUserParseFile(&saxHandler, NULL, fileName)) {
     1127        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_OPEN_FAILED, fileName);
     1128        return -1;
     1129    }
     1130
     1131    // Parser and memory cleanups for libxml2
     1132    xmlCleanupParser();
     1133    xmlMemoryDump();
     1134
     1135    return 0;
     1136}
Note: See TracChangeset for help on using the changeset viewer.