Changeset 4540 for trunk/psLib/src/xml/psXML.c
- Timestamp:
- Jul 12, 2005, 9:12:01 AM (21 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/xml/psXML.c (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/xml/psXML.c
r4432 r4540 1 /** @file ps MetadataIO.c1 /** @file psXML.c 2 2 * 3 * @brief Contains metadatainput/output functions.3 * @brief Contains XML input/output functions. 4 4 * 5 * This file defines functions to read and write metadata to/from an externalfile.5 * This file defines functions to read metadata from an XML file. 6 6 * 7 * @ingroup Metadata7 * @ingroup XML 8 8 * 9 9 * @author Ross Harman, MHPCC 10 10 * @author Eric Van Alst, MHPCC 11 11 * 12 * @version $Revision: 1.3 4$ $Name: not supported by cvs2svn $13 * @date $Date: 2005-0 6-30 00:04:12$12 * @version $Revision: 1.35 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-07-12 19:12:01 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 17 17 18 18 #include <libxml/parser.h> 19 #include <fitsio.h>20 19 #include <string.h> 21 20 #include <ctype.h> 22 21 #include <limits.h> 23 22 24 #include "psAbort.h" 25 #include "psType.h" 23 #include "psXML.h" 26 24 #include "psMemory.h" 27 25 #include "psError.h" 28 26 #include "psString.h" 29 #include "psList.h"30 #include "psHash.h"31 #include "psVector.h"32 #include "psMetadata.h"33 #include "psMetadataIO.h"34 27 #include "psConstants.h" 35 #include "ps AstronomyErrors.h"28 #include "psErrorText.h" 36 29 37 30 /******************************************************************************/ … … 39 32 /******************************************************************************/ 40 33 41 /** Check for FITS errors */42 #define FITS_ERROR(STRING,PS_ERROR) \43 fits_get_errstatus(status, fitsErr); \44 psError(PS_ERR_IO,true, STRING, PS_ERROR, fitsErr); \45 status = 0; \46 fits_close_file(fd, &status); \47 if(status){ \48 fits_get_errstatus(status, fitsErr); \49 psError(PS_ERR_IO,true, "Couldn't close FITS file. FITS error: %s", fitsErr); \50 } \51 status = 0; \52 psFree(output); \53 return NULL;54 55 34 /** Maximum size of a FITS line */ 56 35 #define FITS_LINE_SIZE 80 … … 59 38 #define MAX_STRING_LENGTH 256 60 39 61 62 /******************************************************************************/63 /* TYPE DEFINITIONS */64 /******************************************************************************/65 66 // None67 68 /*****************************************************************************/69 /* GLOBAL VARIABLES */70 /*****************************************************************************/71 72 // None73 74 /*****************************************************************************/75 /* FILE STATIC VARIABLES */76 /*****************************************************************************/77 78 // None79 80 /*****************************************************************************/81 /* FUNCTION IMPLEMENTATION - LOCAL */82 /*****************************************************************************/83 84 static void saxEndElement(void *ctx, const xmlChar *tagName);85 static void initVectorXml(void *ctx, char *tagName);86 static void initMetadataItemXml(void *ctx, char *tagName);87 static void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts);88 static psMetadata* getMetadataType(char *linePtr);89 static psMetadata* setMetadataItem(psMetadata* template, char* linePtr)90 ;91 static void parseLevelInfoFree(p_psParseLevelInfo* info);92 static psBool parseLine(psS32* level, psArray* levelArray,93 char* linePtr, psS32 lineCount, char* fileName, psBool overwrite);94 static psBool parseMetadataItem(char* keyName, psS32* level, psArray* levelArray,95 char* linePtr, psS32 lineCount, char* fileName, psMetadataFlags flags);96 97 static void parseLevelInfoFree(p_psParseLevelInfo* info)98 {99 psFree(info->nonUniqueKeyArray);100 psFree(info->typeArray);101 psFree(info->templateArray);102 psFree(info->name);103 psFree(info->metadata);104 }105 106 // Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string107 // must be null terminated.108 psBool ignoreLine(char *inString)109 {110 while(*inString!='\0' && *inString!='#') {111 if(!isspace(*inString)) {112 return false;113 }114 inString++;115 }116 117 return true;118 }119 120 121 // Removes leading and trailing whitespace and # characters from a string. The cleaned string is a new null122 // terminated copy of the original input string.123 char *cleanString(char *inString, psS32 sLen, psBool ignoreComment)124 {125 char *ptrB = NULL;126 char *ptrE = NULL;127 char *cleaned = NULL;128 129 // Initialize begining of string pointer130 ptrB = inString;131 132 // Skip over leading # or whitespace133 if(ignoreComment) {134 while (isspace(*ptrB) || *ptrB=='#') {135 ptrB++;136 }137 } else {138 while (isspace(*ptrB)) {139 ptrB++;140 }141 }142 143 // Skip over trailing whitespace, null terminators, and # characters144 ptrE = inString + sLen;145 if(ignoreComment) {146 while(isspace(*ptrE) || *ptrE=='\0' || *ptrE=='#') {147 ptrE--;148 }149 } else {150 while(isspace(*ptrE) || *ptrE=='\0') {151 ptrE--;152 }153 }154 155 // Length, sLen, does not include '\0'156 sLen = ptrE - ptrB + 1;157 158 // Adds '\0' to end of string and +1 to sLen159 if(sLen < 0 ) {160 cleaned = NULL;161 } else {162 cleaned = psStringNCopy(ptrB, sLen);163 }164 165 return cleaned;166 }167 168 // Count repeat occurances of a single character within a line. The input string must be null terminated.169 psS32 repeatedChars(char *inString, char ch)170 {171 psS32 count = 0;172 173 while(*inString!='\0') {174 if(*inString == ch) {175 count++;176 }177 inString++;178 }179 180 return count;181 }182 183 // Returns cleaned token based on delimiter, but not including delimiter. Also changes the pointer location184 // the beginning of the string. Tokens are newly allocated null terminated strings.185 char* getToken(char **inString, char *delimiter, psS32 *status, psBool ignoreComment)186 {187 char *cleanToken = NULL;188 char *convertChar = NULL;189 psS32 sLen = 0;190 191 // Convert tab characters to white space192 while((convertChar=strchr(*inString,'\t')) != NULL ) {193 *convertChar = ' ';194 }195 196 // Skip over leading whitespace197 while(isspace(**inString)) {198 (*inString)++;199 }200 201 // Length of token, not including delimiter202 sLen = strcspn(*inString, delimiter);203 if(sLen) {204 205 // Create new, cleaned, and null terminated token206 cleanToken = cleanString(*inString, sLen,ignoreComment);207 208 // Move to end of token209 (*inString) += sLen;210 } else if(**inString!='\0' && sLen==0) {211 *status = 1;212 }213 214 return cleanToken;215 }216 217 40 // Returns single parsed value as a double precision number. The input string must be cleaned and null 218 41 // terminated. 219 double parseValue(char *inString, psS32 *status)42 static double parseValue(char *inString, psS32 *status) 220 43 { 221 44 char *end = NULL; … … 233 56 234 57 /** Returns true or false. 'T', 't', '1', 'F', 'f', and '0' are acceptable, parsable variations. */ 235 psBool parseBool(char *inString, psS32 *status)58 static psBool parseBool(char *inString, psS32 *status) 236 59 { 237 60 psBool value = false; … … 250 73 251 74 /** Returns parsed vector filled with with data. The input string must be null terminated. */ 252 psVector* parseVector(char *inString, psElemType elemType, psS32 *status)75 static psVector* parseVector(char *inString, psElemType elemType, psS32 *status) 253 76 { 254 77 char* end = NULL; … … 332 155 333 156 return vec; 334 }335 336 /*****************************************************************************/337 /* FUNCTION IMPLEMENTATION - PUBLIC */338 /*****************************************************************************/339 340 p_psParseLevelInfo* p_psParseLevelInfoAlloc(void)341 {342 343 p_psParseLevelInfo* info = NULL;344 345 // Allocate memory for parse level info346 info = (p_psParseLevelInfo*)psAlloc(sizeof(p_psParseLevelInfo));347 348 // If allocation successful then initialize members349 if(info != NULL) {350 351 info->nonUniqueKeyArray = psArrayAlloc(10);352 info->nonUniqueKeyArray->n = 0;353 354 info->typeArray = psArrayAlloc(10);355 info->typeArray->n = 0;356 357 info->templateArray = psArrayAlloc(10);358 info->templateArray->n = 0;359 360 info->metadata = NULL;361 info->name = NULL;362 363 // Set memory deallocator364 psMemSetDeallocator(info,(psFreeFunc)parseLevelInfoFree);365 }366 return info;367 }368 369 bool psMetadataItemPrint(FILE * fd, const char *format, const psMetadataItem* item)370 {371 psMetadataType type;372 psBool success = true;373 374 PS_ASSERT_PTR_NON_NULL(fd, success);375 PS_ASSERT_PTR_NON_NULL(format, success);376 PS_ASSERT_PTR_NON_NULL(item, success);377 378 type = item->type;379 380 // determining the format type381 char* fType = strchr(format,'%');382 if (fType == NULL) {383 // well, the format contains no reference to the metadataItem's data:384 // that is truly trival to do!385 fprintf(fd,format);386 return success;387 }388 389 // skip over any format modifiers390 const char* formatEnd = format+strlen(format);391 while ( (fType < formatEnd) &&392 (strchr(" +-01234567890.$#, hlL",*(++fType)) != NULL) ) {}393 394 #define METADATAITEM_NUMERIC_CAST(FORMAT_TYPE) { \395 switch(type) { \396 case PS_META_BOOL: \397 fprintf(fd, format, (FORMAT_TYPE) item->data.B); \398 break; \399 case PS_META_S32: \400 fprintf(fd,format,(FORMAT_TYPE) item->data.S32); \401 break; \402 case PS_META_F32: \403 fprintf(fd, format,(FORMAT_TYPE) item->data.F32); \404 break; \405 case PS_META_F64: \406 fprintf(fd, format,(FORMAT_TYPE) item->data.F64); \407 break; \408 default: \409 psError(PS_ERR_BAD_PARAMETER_TYPE,true, \410 PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type); \411 success = false; \412 } \413 }414 415 switch(*fType) {416 case 'd':417 case 'i':418 case 'c':419 METADATAITEM_NUMERIC_CAST(int)420 break;421 case 'o':422 case 'u':423 case 'x':424 case 'X':425 METADATAITEM_NUMERIC_CAST(unsigned int)426 break;427 case 'e':428 case 'E':429 case 'f':430 case 'F':431 case 'g':432 case 'G':433 case 'a':434 case 'A':435 METADATAITEM_NUMERIC_CAST(double)436 break;437 case 's':438 if (type == PS_META_STR) {439 fprintf(fd,format,(char*)item->data.V);440 } else {441 psError(PS_ERR_BAD_PARAMETER_TYPE,true,442 PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type);443 success = false;444 }445 break;446 case 'p':447 fprintf(fd,format,item->data.V);448 break;449 default:450 psError(PS_ERR_BAD_PARAMETER_TYPE, true,451 PS_ERRORTEXT_psMetadata_FORMAT_INVALID, *fType);452 break;453 }454 455 return success;456 }457 458 459 psMetadata* psMetadataReadHeader(psMetadata* output, char *extName, psS32 extNum, char *fileName)460 {461 psBool tempBool;462 psBool success;463 char keyType;464 char keyName[FITS_LINE_SIZE];465 char keyValue[FITS_LINE_SIZE];466 char keyComment[FITS_LINE_SIZE];467 char fitsErr[MAX_STRING_LENGTH];468 psS32 i;469 psS32 hduType = 0;470 psS32 status = 0;471 psS32 numKeys = 0;472 psS32 keyNum = 0;473 fitsfile *fd = NULL;474 475 PS_ASSERT_PTR_NON_NULL(fileName,NULL);476 477 fits_open_file(&fd, fileName, READONLY, &status);478 if(fd == NULL || status != 0) {479 FITS_ERROR("FITS error while opening file: %s %s", fileName);480 return NULL;481 }482 483 if (extName == NULL && extNum < 1) {484 psError(PS_ERR_BAD_PARAMETER_VALUE, true,485 PS_ERRORTEXT_psMetadataIO_EXTNUM_NOTPOSITIVE,486 extNum);487 return NULL;488 }489 490 // Allocate metadata if user didn't491 if (output == NULL) {492 output = psMetadataAlloc();493 }494 495 // Move to user designated HDU number or HDU name in FITS file. HDU numbers starts at one.496 if (extName != NULL) {497 if (fits_movnam_hdu(fd, ANY_HDU, extName, 0, &status) != 0) {498 FITS_ERROR("FITS error while locating header %s: %s", extName);499 }500 } else {501 if (fits_movabs_hdu(fd, extNum, &hduType, &status) != 0) {502 FITS_ERROR("FITS error while locating header %d: %s", extNum);503 }504 }505 506 // Get number of key names507 if (fits_get_hdrpos(fd, &numKeys, &keyNum, &status) != 0) {508 FITS_ERROR("FITS error while reading key %d: %s", keyNum);509 }510 511 // Get each key name. Keywords start at one.512 for (i = 1; i <= numKeys; i++) {513 if (fits_read_keyn(fd, i, keyName, keyValue, keyComment, &status) != 0) {514 FITS_ERROR("FITS error while reading key %d: %s", keyNum);515 }516 if (fits_get_keytype(keyValue, &keyType, &status) != 0) {517 fits_get_errstatus(status, fitsErr);518 if (status != VALUE_UNDEFINED) {519 FITS_ERROR("FITS error while determining key %d type: %s", keyNum);520 } else {521 // Some keywords are still valid if they don't have a type (like COMMENTS and HISTORY)522 keyType = 'C';523 status = 0;524 }525 }526 527 switch (keyType) {528 case 'I':529 success = psMetadataAdd(output, PS_LIST_TAIL, keyName,530 PS_META_S32 | PS_META_DUPLICATE_OK,531 keyComment, atoi(keyValue));532 break;533 case 'F':534 success = psMetadataAdd(output, PS_LIST_TAIL, keyName,535 PS_META_F64 | PS_META_DUPLICATE_OK,536 keyComment, atof(keyValue));537 break;538 case 'C':539 success = psMetadataAdd(output, PS_LIST_TAIL, keyName,540 PS_META_STR | PS_META_DUPLICATE_OK,541 keyComment, keyValue);542 break;543 case 'L':544 tempBool = (keyValue[0] == 'T') ? 1 : 0;545 success = psMetadataAdd(output, PS_LIST_TAIL, keyName,546 PS_META_BOOL | PS_META_DUPLICATE_OK,547 keyComment, tempBool);548 break;549 case 'U':550 case 'X':551 default:552 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FITS_METATYPE_INVALID, keyType);553 return output;554 }555 556 if (!success) {557 psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadataIO_ADD_FAILED, keyName);558 return output;559 }560 }561 562 return output;563 }564 565 static psMetadata* getMetadataType(char* linePtr)566 {567 psMetadata* metadataTemplate = NULL;568 psS32 status = 0;569 char* token = NULL;570 psMetadataItem* tempItem = NULL;571 572 // Loop through line and generate metadata items for each token found573 while((token = getToken(&linePtr," ",&status,false)) != NULL ) {574 575 // If not allocated then allocate new metadata576 if(metadataTemplate == NULL) {577 metadataTemplate = psMetadataAlloc();578 }579 580 // Look for comment indicator #581 if(strstr(token,"#") != 0) {582 psFree(token);583 break;584 }585 586 // Create metadata item to represent token read587 tempItem = psMetadataItemAllocStr(token,"","");588 if(tempItem == NULL) {589 psFree(metadataTemplate);590 psFree(token);591 metadataTemplate = NULL;592 break;593 }594 595 // Add item to template596 if(!psMetadataAddItem(metadataTemplate, tempItem, PS_LIST_TAIL, PS_META_DEFAULT)) {597 psFree(metadataTemplate);598 psFree(tempItem);599 psFree(token);600 metadataTemplate = NULL;601 break;602 }603 psFree(tempItem);604 psFree(token);605 }606 607 return metadataTemplate;608 }609 610 static psMetadata* setMetadataItem(psMetadata* template, char* linePtr)611 {612 psMetadata* md = NULL;613 psS32 items = 0;614 char* token = NULL;615 psS32 status = 0;616 psMetadataItem* mdItem = NULL;617 psMetadataItem* templateItem = NULL;618 psListIterator* iter = NULL;619 620 // Determine the number of items in template621 items = template->list->size;622 if(items > 0 ) {623 624 // Allocate metadata625 md = psMetadataAlloc()626 ;627 628 // Point to first item in template629 iter = psListIteratorAlloc(template->630 list,PS_LIST_HEAD,true);631 632 // For each item in template parse line string for values633 for(psS32 i = 0;634 i < items;635 i++) {636 637 // Get template item638 templateItem = psListGetAndIncrement(iter)639 ;640 if(templateItem == NULL) {641 psFree(md);642 md = NULL;643 break;644 }645 646 // Get the next token on the line647 token = getToken(&linePtr," ",&status,false);648 if(token != NULL) {649 // Allocate metadata item650 mdItem = psMetadataItemAllocStr(templateItem->name,templateItem->comment,token);651 if(mdItem == NULL) {652 psFree(md);653 md = NULL;654 psFree(token);655 break;656 }657 // Add item to metadata658 if(!psMetadataAddItem(md, mdItem, PS_LIST_TAIL, PS_META_DEFAULT)) {659 psFree(md);660 md = NULL;661 psFree(mdItem);662 psFree(token);663 break;664 }665 psFree(mdItem);666 } else {667 // Missing items668 psFree(md);669 md = NULL;670 break;671 }672 673 psFree(token);674 }675 psFree(iter);676 }677 return md;678 }679 680 psBool parseMetadataItem(char* keyName, psS32* level, psArray* levelArray,681 char* linePtr, psS32 lineCount, char* fileName, psMetadataFlags flags)682 {683 psBool returnValue = true;684 psBool addStatus = false;685 psMetadataType mdType = PS_META_UNKNOWN;686 psElemType vectorType = PS_TYPE_S8;687 char* strType = NULL;688 char* strValue = NULL;689 char* strComment = NULL;690 psS32 status = 0;691 psMetadata* md = NULL;692 psF64 tempDbl = 0.0;693 psBool tempBool = false;694 psS32 tempInt = 0;695 psVector* tempVec = NULL;696 char* tempStr = NULL;697 psArray* nonUniqueKeys = NULL;698 psBool typeFound = false;699 psArray* typeArray = NULL;700 psArray* templateArray = NULL;701 psMetadata* tempMeta = NULL;702 p_psParseLevelInfo* nextLevelInfo = NULL;703 704 // Get the metadata item type705 strType = getToken(&linePtr, " ", &status,true);706 707 // Check for no type708 if(strType==NULL) {709 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "type",lineCount,710 fileName);711 returnValue = false;712 } else {713 714 // Set metadata type based on type token715 716 // Check if the keyName specifies a vector and if so use strType token to find vector type717 if(*keyName == '@') {718 mdType = PS_META_VEC;719 // Get the type of vector720 if(!strncmp(strType, "U8", 2)) {721 vectorType = PS_TYPE_U8;722 } else if (!strncmp(strType,"U16",3)) {723 vectorType = PS_TYPE_U16;724 } else if (!strncmp(strType,"U32",3)) {725 vectorType = PS_TYPE_U32;726 } else if (!strncmp(strType,"U64",3)) {727 vectorType = PS_TYPE_U64;728 } else if (!strncmp(strType,"S8",2)) {729 vectorType = PS_TYPE_S8;730 } else if (!strncmp(strType,"S16",3)) {731 vectorType = PS_TYPE_S16;732 } else if (!strncmp(strType,"S32",3)) {733 vectorType = PS_TYPE_S32;734 } else if (!strncmp(strType,"S64",3)) {735 vectorType = PS_TYPE_S64;736 } else if (!strncmp(strType,"F32",3)) {737 vectorType = PS_TYPE_F32;738 } else if (!strncmp(strType,"F64",3)) {739 vectorType = PS_TYPE_F64;740 } else {741 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, "", keyName,742 strType, lineCount, fileName);743 psFree(strType);744 return false;745 }746 } else if(!strncmp(strType, "STR", 3)) {747 mdType = PS_META_STR;748 } else if(!strncmp(strType, "BOOL", 4)) {749 mdType = PS_META_BOOL;750 } else if(!strncmp(strType, "S32", 3)) {751 mdType = PS_META_S32;752 } else if(!strncmp(strType, "F32", 3)) {753 mdType = PS_META_F32;754 } else if(!strncmp(strType, "F64", 3)) {755 mdType = PS_META_F64;756 } else if(!strncmp(strType, "MULTI", 5)) {757 mdType = PS_META_MULTI;758 } else if(!strncmp(strType, "METADATA", 8)) {759 mdType = PS_META_META;760 } else {761 // Search through user types762 typeArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->typeArray;763 templateArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->templateArray;764 for(psS32 k = 0; k < typeArray->n; k++) {765 if(strcmp(strType,(char*)typeArray->data[k]) == 0) {766 tempMeta = setMetadataItem((psMetadata*)templateArray->data[k],linePtr);767 if(tempMeta != NULL) {768 // Add metadata item769 md = ((p_psParseLevelInfo*)(levelArray->data[*level]))->metadata;770 addStatus = psMetadataAdd(md,PS_LIST_TAIL,keyName,PS_META_META | flags,"",tempMeta);771 // Check for add failure772 if (! addStatus) {773 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM,774 keyName, lineCount, fileName);775 psFree(strType);776 psFree(tempMeta);777 return false;778 }779 psFree(tempMeta);780 } else {781 // Metadata type read error782 psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL,783 keyName,lineCount,fileName);784 psFree(strType);785 return false;786 }787 typeFound = true;788 break;789 }790 }791 if(!typeFound) {792 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,793 strType, lineCount,fileName);794 psFree(strType);795 return false;796 } else {797 psFree(strType);798 return true;799 }800 }801 }802 803 // If type is not MULTI or META then get the value and comment804 if((mdType != PS_META_MULTI) && (mdType != PS_META_META)) {805 // Get the metadata item value if there is one.806 status = 0;807 strValue = getToken(&linePtr, "#", &status,true);808 if(status) {809 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,810 fileName);811 psFree(strType);812 psFree(strValue);813 return false;814 }815 if(strValue==NULL) {816 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "value", lineCount,817 fileName);818 psFree(strType);819 psFree(strValue);820 return false;821 }822 // Not all lines will have comments, so NULL is ok.823 status = 0;824 strComment = getToken(&linePtr,"~", &status,true);825 if(status) {826 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "comment", lineCount,827 fileName);828 psFree(strType);829 psFree(strValue);830 psFree(strComment);831 }832 }833 834 // Need to add item to metadata so get pointer to metadata835 status = 0;836 md = ((p_psParseLevelInfo*)(levelArray->data[*level]))->metadata;837 nonUniqueKeys = ((p_psParseLevelInfo*)(levelArray->data[*level]))->nonUniqueKeyArray;838 switch(mdType) {839 case PS_META_STR:840 addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,841 mdType | flags,842 strComment, strValue);843 break;844 case PS_META_BOOL:845 tempBool = parseBool(strValue, &status);846 if(!status) {847 addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,848 mdType | flags,849 strComment, tempBool);850 } else {851 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,852 strType, lineCount, fileName);853 returnValue = false;854 }855 break;856 case PS_META_F32:857 case PS_META_F64:858 tempDbl = parseValue(strValue, &status);859 if(!status) {860 addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,861 mdType | flags,862 strComment, tempDbl);863 } else {864 psError(PS_ERR_IO, true,865 PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName, strType, lineCount,866 fileName);867 returnValue = false;868 }869 break;870 case PS_META_S32:871 tempInt = (psS32)parseValue(strValue, &status);872 if(!status) {873 addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName,874 mdType | flags,875 strComment, tempInt);876 } else {877 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,878 strType, lineCount, fileName);879 returnValue = false;880 }881 break;882 case PS_META_VEC:883 tempVec = parseVector(strValue, vectorType, &status);884 if(!status) {885 addStatus = psMetadataAdd(md, PS_LIST_TAIL, keyName+1,886 mdType | flags,887 strComment, tempVec);888 } else {889 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, keyName,890 strType, lineCount, fileName);891 returnValue = false;892 }893 psFree(tempVec);894 break;895 case PS_META_MULTI:896 // Add key to non-unique array of keys897 // Check for duplicate MULTI lines898 addStatus = true;899 for(psS32 k=0; k < nonUniqueKeys->n; k++) {900 if(strcmp(keyName,(char*)nonUniqueKeys->data[k]) == 0) {901 psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_DUPLICATE_MULTI,902 lineCount,fileName);903 psFree(strType);904 return false;905 }906 }907 tempStr = psStringCopy(keyName);908 nonUniqueKeys = psArrayAdd(nonUniqueKeys,0,tempStr);909 addStatus = true;910 psFree(tempStr);911 break;912 case PS_META_META:913 // Create next level info914 nextLevelInfo = p_psParseLevelInfoAlloc();915 // Create new metadata916 nextLevelInfo->metadata = psMetadataAlloc();917 // Save name of metadata918 nextLevelInfo->name = psStringCopy(keyName);919 // Add next level to levelArray920 levelArray = psArrayAdd(levelArray,1,nextLevelInfo);921 psFree(nextLevelInfo);922 // Increment level counter923 (*level)++;924 addStatus = true;925 break;926 default:927 psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,928 lineCount,fileName);929 break;930 }931 932 // Check if the add status was successful933 if (! addStatus) {934 // psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, keyName, lineCount,935 // fileName);936 returnValue = false;937 }938 939 psFree(strComment);940 psFree(strValue);941 psFree(strType);942 943 return returnValue;944 }945 946 psBool parseLine(psS32* level, psArray* levelArray, char* linePtr,947 psS32 lineCount, char* fileName, psBool overwrite)948 {949 psBool returnValue = true;950 psMetadataFlags flags = PS_META_DEFAULT;951 char* keyName = NULL;952 psS32 status = 0;953 psS32 limit = 0;954 psMetadata* tempTemplate = NULL;955 char* strType = NULL;956 psArray* typeArray = NULL;957 psArray* templateArray = NULL;958 p_psParseLevelInfo* upperLevelInfo = NULL;959 p_psParseLevelInfo* lowerLevelInfo = NULL;960 psBool addStatus = 0;961 962 // Set flags if overwrite specified963 if(overwrite) {964 flags = PS_META_REPLACE;965 }966 967 // If line is not a comment or blank, then extract data968 if(!ignoreLine(linePtr)) {969 970 // Check for more than one '@' in a line971 if(repeatedChars(linePtr, '@') > 1) {972 psError(PS_ERR_IO, true,973 PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR, '@', lineCount, fileName);974 return false;975 }976 977 // Get metadata item name978 keyName = getToken(&linePtr, " ", &status,true);979 if(status) {980 psError(PS_ERR_IO, true,981 PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL, "keyName", lineCount, fileName);982 psFree(keyName);983 return false;984 }985 986 // Check for special keyName values "TYPE", "END"987 if(strcmp(keyName,"TYPE") == 0 ) {988 // Get the type name989 strType = getToken(&linePtr," ",&status,true);990 if(strType == NULL) {991 psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL,"type",lineCount,992 fileName);993 psFree(keyName);994 return false;995 }996 tempTemplate = getMetadataType(linePtr);997 // Check if type was parsed succesfully998 if(tempTemplate != NULL) {999 // Access type array1000 typeArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->typeArray;1001 // Check if type already exists in array1002 for(psS32 k=0; k < typeArray->n; k++) {1003 // Compare type name with the list of current types1004 if(strcmp(strType,(char*)typeArray->data[k]) == 0) {1005 psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_TYPE_DUPLICATE,1006 strType,lineCount,fileName);1007 psFree(tempTemplate);1008 psFree(keyName);1009 psFree(strType);1010 return false;1011 }1012 }1013 // Add key name to array of type1014 typeArray = psArrayAdd(typeArray,1,strType);1015 // Add template to array of templates1016 templateArray = ((p_psParseLevelInfo*)(levelArray->data[*level]))->templateArray;1017 templateArray = psArrayAdd(templateArray,1,tempTemplate);1018 psFree(tempTemplate);1019 } else {1020 psError(PS_ERR_IO,true,PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID,1021 strType,lineCount,fileName);1022 psFree(keyName);1023 psFree(strType);1024 return false;1025 }1026 psFree(strType);1027 } else if (strcmp(keyName,"END") == 0 ) {1028 if(*level > 0) {1029 upperLevelInfo = ((p_psParseLevelInfo*)(levelArray->data[*level-1]));1030 lowerLevelInfo = ((p_psParseLevelInfo*)(levelArray->data[*level]));1031 // Check name in nonunique list1032 for(psS32 k=0; k < upperLevelInfo->nonUniqueKeyArray->n; k++) {1033 if(strcmp(upperLevelInfo->nonUniqueKeyArray->data[k],lowerLevelInfo->name) == 0) {1034 flags = PS_META_DUPLICATE_OK;1035 break;1036 }1037 }1038 // Add metadata to upper level metadata1039 addStatus = psMetadataAdd(upperLevelInfo->metadata,1040 PS_LIST_TAIL,lowerLevelInfo->name,1041 PS_META_META | flags,1042 "",1043 lowerLevelInfo->metadata);1044 if(!addStatus) {1045 psFree(keyName);1046 return false;1047 } else {1048 // Remove lower info level1049 if(!psArrayRemove(levelArray,levelArray->data[*level])) {1050 psFree(keyName);1051 return false;1052 }1053 psFree(lowerLevelInfo);1054 (*level)--;1055 }1056 } else {1057 psFree(keyName);1058 return false;1059 }1060 } else {1061 // Check if key name present in array of non-unique key names1062 limit = ((p_psParseLevelInfo*)(levelArray->data[*level]))->nonUniqueKeyArray->n;1063 for(psS32 k=0; k < limit; k++) {1064 char* name = (char*)((p_psParseLevelInfo*)1065 (levelArray->data[*level]))->nonUniqueKeyArray->data[k];1066 if(strcmp(name,keyName) == 0) {1067 flags = PS_META_DUPLICATE_OK;1068 }1069 }1070 // Parse metadataItem1071 if(!parseMetadataItem(keyName,level, levelArray, linePtr, lineCount, fileName, flags)) {1072 psFree(keyName);1073 return false;1074 }1075 }1076 psFree(keyName);1077 }1078 return returnValue;1079 }1080 1081 psMetadata* psMetadataConfigParse(psMetadata* md, unsigned int *nFail, const char *fileName, bool overwrite)1082 {1083 FILE* fp = NULL;1084 char* line = NULL;1085 char* linePtr = NULL;1086 psArray* parseLevelInfoArray = NULL;1087 psS32 lineCount = 0;1088 psS32 nestingLevel = 0;1089 p_psParseLevelInfo* topLevelInfo = NULL;1090 1091 // Check for NULL file name1092 PS_ASSERT_PTR_NON_NULL(fileName,NULL);1093 1094 // Check for NULL nFail1095 PS_ASSERT_PTR_NON_NULL(nFail,NULL);1096 1097 // Attempt to open specified file1098 if((fp=fopen(fileName, "r")) == NULL) {1099 psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_OPEN_FAILED, fileName);1100 return NULL;1101 }1102 1103 // Allocate metadata if necessary1104 if (md == NULL) {1105 md = psMetadataAlloc();1106 }1107 1108 // Allocate array to store parse level information1109 parseLevelInfoArray = psArrayAlloc(10);1110 parseLevelInfoArray->n = 0;1111 1112 // Set parse level info for the top level1113 topLevelInfo = p_psParseLevelInfoAlloc();1114 topLevelInfo->metadata = psMemIncrRefCounter(md);1115 parseLevelInfoArray = psArrayAdd(parseLevelInfoArray,1,topLevelInfo);1116 psFree(topLevelInfo);1117 1118 // Create reusable line for continuous read1119 line = (char*)psAlloc(MAX_STRING_LENGTH*sizeof(char));1120 1121 // While loop to parse the file1122 while(fgets(line, MAX_STRING_LENGTH, fp) != NULL) {1123 1124 // Initialize variables for new line1125 linePtr = line;1126 lineCount++;1127 1128 if(!parseLine(&nestingLevel,parseLevelInfoArray,linePtr,lineCount,(char*)fileName,overwrite)) {1129 (*nFail)++;1130 }1131 }1132 1133 // Free parse array and line buffer1134 psFree(parseLevelInfoArray);1135 psFree(line);1136 1137 return md;1138 157 } 1139 158
Note:
See TracChangeset
for help on using the changeset viewer.
