00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <ctype.h>
00039 #ifndef WIN32
00040 #include <unistd.h>
00041 #endif
00042 #ifdef WIN32
00043 #include <io.h>
00044 #ifndef _SSIZE_T_DEFINED
00045 typedef int ssize_t;
00046 #define _SSIZE_T_DEFINED
00047 #endif
00048 #endif
00049
00050 #include <sys/types.h>
00051 #include <sys/stat.h>
00052 #include <fcntl.h>
00053 #include <errno.h>
00054
00055 #include "xData.h"
00056
00057 #if defined __cplusplus
00058 namespace GIDI {
00059 using namespace GIDI;
00060 #endif
00061
00062 static void *xData_parseFreeElement( statusMessageReporting *smr, xData_element *element );
00063 static void xData_parseFreeElementItems( statusMessageReporting *smr, xData_element *element );
00064 static void XMLCALL xData_parseStartElement( void *userData, const char *name, const char **attris );
00065 static void XMLCALL xData_parseEndElement( void *userData, const char *name );
00066 static void XMLCALL xData_parseCharacterData( void *userData, const XML_Char *s, int len );
00067 static void xData_parseInitializeRootElement( xData_document *doc, xData_rootElement *re, xData_element *parentElement,
00068 int depth );
00069 static int xData_parseInitializeText( xData_document *doc, xData_text *text );
00070 static int xData_parseAddElementToRoot( statusMessageReporting *smr, xData_rootElement *parentRoot, const char *name, const char **attris );
00071 static enum xData_errorCodes xData_parseGetCurrentPosition( xData_document *doc, xData_docInfo *docInfo );
00072 static int xData_init_xDataTypeNone( xDataType *xDT, xData_element *element );
00073 static char *xData_getTraceback( statusMessageReporting *smr, xData_element *element );
00074 static char *xData_getTraceback2( statusMessageReporting *smr, xData_rootElement *parentRoot, int n );
00075 static int xData_elementList_defaultSorter( void const *p1, void const *p2 );
00076 static int xData_elementList_indexSorter( void const *p1, void const *p2 );
00077 static int xData_smrUserInterfaceInitialize( xData_document *doc );
00078 static int xData_smrUserInterfaceFree( xData_document *doc );
00079 static int xData_smrUserInterface( void *userData, char **smr );
00080 static char const *xData_shortStringForMessage( size_t size, char *Out, char const *In );
00081
00082
00083
00084 xData_document *xData_parseReadFile( statusMessageReporting *smr, const char *fileName, xData_xDataTypeOk func, void *userData ) {
00085
00086
00087
00088 int f;
00089 char buffer[10 * 1000];
00090 ssize_t count, n = sizeof( buffer ) - 1;
00091 ssize_t s = 0;
00092 xData_document *doc = NULL;
00093
00094 if( ( doc = xData_parseMalloc( smr, func, userData ) ) != NULL ) {
00095 if( xData_setFileName( smr, doc, fileName ) == 0 ) {
00096 f = open( fileName, O_RDONLY );
00097 if( f == -1 ) {
00098 xData_parseEndOfXML( smr, doc );
00099 smr_setMessageError( smr, NULL, __FILE__, __LINE__, xData_errFileError, "could not open file %s", fileName ); }
00100 else {
00101 while( ( count = read( f, buffer, n ) ) > 0 ) {
00102 s += count;
00103 buffer[count] = 0;
00104 if( xData_parse( doc, buffer ) ) break;
00105 if( !smr_isOk( doc->smr ) ) break;
00106 }
00107 close( f );
00108 xData_parseEndOfXML( smr, doc );
00109 if( count < 0 ) smr_setMessageError( smr, NULL, __FILE__, __LINE__, xData_errFileError,
00110 "read failed with errno = %d for %s", errno, fileName );
00111 }
00112 }
00113 if( ( doc != NULL ) && ( !smr_isOk( smr ) ) ) {
00114 xData_parseFree( smr, doc );
00115 doc = NULL;
00116 }
00117 }
00118 return( doc );
00119 }
00120
00121
00122
00123 xData_document *xData_parseString( statusMessageReporting *smr, const char *str, xData_xDataTypeOk func, void *userData ) {
00124
00125
00126
00127 xData_document *doc = NULL;
00128 if( ( doc = xData_parseMalloc( smr, func, userData ) ) != NULL ) {
00129 xData_parse( doc, str );
00130 xData_parseEndOfXML( smr, doc );
00131 if( !smr_isOk( smr ) ) {
00132 xData_parseFree( smr, doc );
00133 doc = NULL;
00134 }
00135 }
00136 return( doc );
00137 }
00138
00139
00140
00141 xData_document *xData_parseMalloc( statusMessageReporting *smr, xData_xDataTypeOk func, void *userData ) {
00142
00143
00144
00145 xData_document *doc;
00146
00147
00148 if( ( doc = (xData_document*) xData_malloc2( smr, sizeof( xData_document ), 1, "xData_document" ) ) != NULL ) {
00149
00150 if( xData_parseInitialize( smr, doc, func, userData ) ) doc = (xData_document*) xData_parseFree( smr, doc );
00151 }
00152 return( doc );
00153 }
00154
00155
00156
00157 int xData_parseInitialize( statusMessageReporting *smr, xData_document *doc, xData_xDataTypeOk func, void *userData ) {
00158
00159 XML_Parser xmlParser;
00160
00161 doc->status = xData_statusParsing;
00162 doc->error = xData_errNone;
00163
00164 doc->err = (XML_Error) 0;
00165 doc->err_line = 0;
00166 doc->err_column = 0;
00167 doc->fileName = NULL;
00168 doc->xDataTypeOk_userFunction = func;
00169 doc->xDataTypeOk_userData = userData;
00170 xData_smrUserInterfaceInitialize( doc );
00171 doc->smr= smr;
00172 doc->xmlParser = xmlParser = XML_ParserCreate( NULL );
00173 if( xmlParser == NULL ) {
00174 smr_setMessageError( smr, NULL, __FILE__, __LINE__, xData_errXML_ParserCreate, "XML_ParserCreate failed" ); }
00175 else {
00176 XML_SetUserData( doc->xmlParser, doc );
00177 xData_parseInitializeRootElement( doc, &(doc->root), NULL, 0 );
00178 doc->currentRoot = &(doc->root);
00179 XML_SetElementHandler( xmlParser, xData_parseStartElement, xData_parseEndElement );
00180 XML_SetCharacterDataHandler( xmlParser, xData_parseCharacterData );
00181 }
00182 return( !smr_isOk( smr ) );
00183 }
00184
00185
00186
00187 int xData_parseEndOfXML( statusMessageReporting *smr, xData_document *doc ) {
00188
00189 if( doc->xmlParser ) {
00190 doc->err = XML_GetErrorCode( doc->xmlParser );
00191 doc->err_line = XML_GetCurrentLineNumber( doc->xmlParser );
00192 doc->err_column = XML_GetCurrentColumnNumber( doc->xmlParser );
00193 if( smr_isOk( smr ) && ( XML_Parse( doc->xmlParser, NULL, 0, 1 ) == XML_STATUS_ERROR ) ) {
00194 doc->status = xData_statusError;
00195 smr_setMessageError( smr, xData_get_smrUserInterfaceFromDocument( doc ), __FILE__, __LINE__, xData_errXMLParser,
00196 "status = %d\nXML_Error code = %d\nXML_ErrorString = %s\nerror line, column = %d, %d", xData_errXMLParser,
00197 doc->err, XML_ErrorString( doc->err ), doc->err_line, doc->err_column );
00198 }
00199 XML_ParserFree( doc->xmlParser );
00200 doc->xmlParser = NULL;
00201 if( doc->status != xData_statusError ) doc->status = xData_statusCompleted;
00202 }
00203 return( 0 );
00204 }
00205
00206
00207
00208 void *xData_parseFree( statusMessageReporting *smr, xData_document *doc ) {
00209
00210 xData_parseEndOfXML( smr, doc );
00211
00212 doc->root.children = (xData_element*) xData_parseFreeElement( smr, doc->root.children );
00213
00214 doc->fileName = (char*) xData_free( smr, doc->fileName );
00215 xData_smrUserInterfaceFree( doc );
00216 xData_free( smr, doc );
00217 return( NULL );
00218 }
00219
00220
00221
00222 static void *xData_parseFreeElement( statusMessageReporting *smr, xData_element *element ) {
00223
00224 xData_element *next;
00225
00226 if( element == NULL ) return( NULL );
00227 for( ; element != NULL; element = next ) {
00228 next = element->next;
00229 xData_parseFreeElementItems( smr, element );
00230 xData_free( smr, element );
00231 }
00232 return( NULL );
00233 }
00234
00235
00236
00237 static void xData_parseFreeElementItems( statusMessageReporting *smr, xData_element *element ) {
00238
00239
00240 element->childrenRoot.children = (xData_element*) xData_parseFreeElement( smr, element->childrenRoot.children );
00241 if( ( !strcmp( element->name, "xData" ) ) && ( element->xDataTypeInfo.release != NULL ) ) element->xDataTypeInfo.release( smr,
00242 &(element->xDataTypeInfo) );
00243 xData_free( smr, element->name );
00244 xData_free( smr, element->fullName );
00245 if( element->attributes.attributes ) xData_free( smr, element->attributes.attributes );
00246 if( element->text.text ) xData_free( smr, element->text.text );
00247 }
00248
00249
00250
00251 int xData_parse( xData_document *doc, const char *s ) {
00252
00253 if( doc->status != xData_statusParsing ) return( doc->status );
00254 if( XML_Parse( doc->xmlParser, s, strlen( s ), 0 ) == XML_STATUS_ERROR ) return( -1 );
00255 return( 0 );
00256 }
00257
00258
00259
00260 static void XMLCALL xData_parseStartElement( void *userData, const char *name, const char **attris ) {
00261
00262 xData_document *doc = (xData_document *) userData;
00263
00264 if( !smr_isOk( doc->smr ) ) return;
00265 xData_parseAddElementToRoot( doc->smr, doc->currentRoot, name, attris );
00266 }
00267
00268
00269
00270 static void XMLCALL xData_parseEndElement( void *userData, const char *name ) {
00271
00272 int status = 0;
00273 xData_document *doc = (xData_document *) userData;
00274
00275 if( !smr_isOk( doc->smr ) ) return;
00276 if( !strcmp( name, "xData" ) ) {
00277 xData_element *element = doc->currentRoot->parentRoot->currentChild;
00278 xData_text *text = &(element->text);
00279 const char *value = xData_getAttributesValueInElement( element, "type" );
00280 if( !strcmp( value, xData_oned_x_ID ) ) {
00281 xData_init_1d_x( doc->smr, element ); }
00282 else if( !strcmp( value, xData_twod_xy_ID ) ) {
00283 xData_init_2d_xy( doc->smr, element ); }
00284 else if( !strcmp( value, xData_twod_xindex_y_ID ) ) {
00285 xData_init_2d_xindex_y( doc->smr, element ); }
00286 else if( !strcmp( value, xData_twod_xShared_yHistogram_ID ) ) {
00287 xData_init_2d_xShared_yHistogram( doc->smr, element ); }
00288 else if( !strcmp( value, xData_matrix_ID ) ) {
00289 xData_init_matrix( doc->smr, element ); }
00290 else {
00291 status = -1;
00292 if( doc->xDataTypeOk_userFunction != NULL ) {
00293 if( doc->xDataTypeOk_userFunction( value, doc, doc->xDataTypeOk_userData ) ) status = 1;
00294 }
00295 if( status < 0 ) smr_setMessageError( doc->smr, xData_get_smrUserInterfaceFromElement( element ), __FILE__, __LINE__, -1,
00296 "Unsupported xData type = %s", value );
00297 }
00298 if( ( status == 0 ) && ( smr_isOk( doc->smr ) ) ) status = element->xDataTypeInfo.toData( doc->smr, &(element->xDataTypeInfo),
00299 &(element->attributes), text->text );
00300 }
00301 doc->currentRoot->currentChild = NULL;
00302 doc->currentRoot = doc->currentRoot->parentRoot;
00303 }
00304
00305
00306
00307 static void XMLCALL xData_parseCharacterData( void *userData, const XML_Char *s, int len ) {
00308
00309
00310
00311
00312 xData_document *doc = (xData_document*) userData;
00313 xData_text *text = &(doc->currentRoot->parentRoot->currentChild->text);
00314 int needSize = text->length + len + 1, l;
00315 char *p;
00316
00317 if( !smr_isOk( doc->smr ) ) return;
00318 if( needSize < 8 ) needSize = 8;
00319
00320 if( needSize > (int) text->allocated ) {
00321 if( text->allocated != 0 ) {
00322 l = ( 20 * text->allocated ) / 100;
00323 if( l < 100 ) l = 100;
00324
00325 if( needSize < ( (int) text->allocated + l ) ) needSize = text->allocated + l;
00326 }
00327 text->allocated = needSize;
00328
00329 text->text = (char*) xData_realloc2( doc->smr, text->text, text->allocated, "text" );
00330 if( !smr_isOk( doc->smr ) ) return;
00331 }
00332 p = &(text->text[text->length]);
00333 strncpy( p, s, len );
00334 text->length += len;
00335 p[len] = 0;
00336 }
00337
00338
00339
00340 static void xData_parseInitializeRootElement( xData_document *doc, xData_rootElement *re,
00341 xData_element *parentElement, int depth ) {
00342
00343 re->xData_doc = doc;
00344 re->parentElement = parentElement;
00345 re->parentRoot = NULL;
00346 if( parentElement != NULL ) re->parentRoot = parentElement->parentRoot;
00347 re->depth = depth;
00348 re->numberOfElements = 0;
00349 re->children = NULL;
00350 re->currentChild = NULL;
00351 }
00352
00353
00354
00355 static int xData_parseInitializeText( xData_document *doc, xData_text *text ) {
00356
00357 xData_parseGetCurrentPosition( doc, &(text->docInfo) );
00358 text->allocated = 0;
00359 text->length = 0;
00360 text->text = NULL;
00361 return( 0 );
00362 }
00363
00364
00365
00366 static int xData_parseAddElementToRoot( statusMessageReporting *smr, xData_rootElement *parentRoot, const char *name, const char **attris ) {
00367
00368 xData_document *doc = parentRoot->xData_doc;
00369 xData_element *element;
00370 int i, n, status = 1;
00371 size_t lens;
00372 char *p, *e;
00373 const char **pAttris;
00374 xData_attribute *a;
00375 void *smrUser;
00376
00377
00378 element = (xData_element*) xData_malloc2( doc->smr, sizeof( xData_element ), 1, "xData_element" );
00379 if( element == NULL ) return( 1 );
00380 xData_parseGetCurrentPosition( doc, &(element->docInfo) );
00381 element->ordinal = parentRoot->numberOfElements;
00382 element->index = -1;
00383 element->accessed = 0;
00384 element->parentRoot = parentRoot;
00385 xData_parseInitializeRootElement( doc, &(element->childrenRoot), element, parentRoot->depth + 1 );
00386 element->next = NULL;
00387
00388 if( ( element->name = (char*) xData_malloc2( doc->smr, strlen( name ) + 1, 0, "name" ) ) == NULL ) {
00389 xData_free( smr, element );
00390 return( 1 );
00391 }
00392 strcpy( element->name, name );
00393 if( ( element->fullName = xData_getTraceback( smr, element ) ) == NULL ) {
00394 xData_free( smr, element->name );
00395 xData_free( smr, element );
00396 return( 1 );
00397 }
00398 for( i = 0, lens = 0, pAttris = attris; *pAttris; i++, pAttris++ ) lens += strlen( *pAttris ) + 1;
00399 n = i / 2;
00400 element->attributes.size = n * sizeof( xData_attribute ) + lens;
00401 element->attributes.number = n;
00402 element->attributes.attributes = NULL;
00403 smrUser = xData_get_smrUserInterfaceFromElement( element );
00404 if( element->attributes.size ) {
00405
00406 if( ( element->attributes.attributes = (xData_attribute*) xData_malloc2( doc->smr, element->attributes.size, 0, "attributes") ) == NULL ) {
00407 status = 0; }
00408 else {
00409 a = element->attributes.attributes;
00410 p = (char *) &(element->attributes.attributes[n]);
00411 for( i = 0, pAttris = attris; ( i < n ) && status; i++, a++, pAttris++ ) {
00412 lens = strlen( *pAttris ) + 1;
00413 a->name = p;
00414 strcpy( p, *pAttris );
00415 p += lens;
00416 pAttris++;
00417 lens = strlen( *pAttris ) + 1;
00418 a->value= p;
00419 strcpy( p, *pAttris );
00420 p += lens;
00421 if( !strcmp( "index", a->name ) ) {
00422 #ifndef WIN32
00423 element->index = strtoll( a->value, &e, 10 );
00424 #endif
00425 #ifdef WIN32
00426 element->index = strtol( a->value, &e, 10 );
00427 #endif
00428 if( *e != 0 ) {
00429 status = 0;
00430 smr_setMessageError( doc->smr, smrUser, __FILE__, __LINE__, -1, "could not convert index attribute = %s to integer", a->value );
00431 }
00432 }
00433 }
00434 }
00435 }
00436 if( !status ) {
00437 xData_free( smr, element->attributes.attributes );
00438 xData_free( smr, element->name );
00439 xData_free( smr, element->fullName );
00440 xData_free( smr, element );
00441 return( 1 );
00442 }
00443 xData_init_xDataTypeNone( &(element->xDataTypeInfo), element );
00444 element->textOffset = 0;
00445 xData_parseInitializeText( doc, &(element->text) );
00446 if( parentRoot->parentElement != NULL ) element->textOffset = parentRoot->parentElement->text.length;
00447 if( parentRoot->currentChild == NULL ) {
00448 parentRoot->children = element; }
00449 else {
00450 parentRoot->currentChild->next = element;
00451 }
00452 parentRoot->numberOfElements++;
00453 parentRoot->currentChild = element;
00454 doc->currentRoot = &(element->childrenRoot);
00455 return( 0 );
00456 }
00457
00458
00459
00460 static enum xData_errorCodes xData_parseGetCurrentPosition( xData_document *doc, xData_docInfo *docInfo ) {
00461
00462 docInfo->column = XML_GetCurrentColumnNumber( doc->xmlParser );
00463 docInfo->line = XML_GetCurrentLineNumber( doc->xmlParser );
00464 return( xData_errNone );
00465 }
00466
00467
00468
00469 int xData_parseIsError( xData_document *doc ) {
00470
00471 return( doc->status == xData_statusError );
00472 }
00473
00474
00475
00476 xData_element *xData_getDocumentsElement( xData_document *doc ) { return( doc->root.children ); }
00477 xData_element *xData_getFirstElement( xData_element *element ) { return( element->childrenRoot.children ); }
00478 xData_element *xData_getNextElement( xData_element *element ) { return( element->next ); }
00479
00480
00481
00482 enum xData_itemMode xData_getFirstItem( xData_element *element, xData_item *item ) {
00483
00484 item->parentElement = element;
00485 item->element = xData_getFirstElement( element );
00486 if( item->element == NULL ) {
00487 item->mode = xData_itemModeText;
00488 if( element->text.length == 0 ) item->mode = xData_itemModeEnd; }
00489 else {
00490 item->mode = xData_itemModeElement;
00491 if( 0 < item->element->textOffset ) item->mode = xData_itemModeText;
00492 }
00493 item->textOffset = 0;
00494 item->textLength = element->text.length;
00495 if( item->element != NULL ) item->textLength = item->element->textOffset;
00496 item->text = element->text.text;
00497 return( item->mode );
00498 }
00499
00500
00501
00502 enum xData_itemMode xData_getNextItem( xData_item *item ) {
00503
00504 if( item->mode != xData_itemModeEnd ) {
00505 if( item->mode == xData_itemModeText ) {
00506 item->mode = xData_itemModeElement;
00507 if( item->element == NULL ) item->mode = xData_itemModeEnd;
00508 item->textOffset += item->textLength;
00509 item->textLength = 0;
00510 item->text = &(item->parentElement->text.text[item->textOffset]); }
00511 else {
00512 item->element = item->element->next;
00513 item->mode = xData_itemModeText;
00514 if( item->element == NULL ) {
00515 if( item->textOffset < item->parentElement->text.length ) {
00516 item->textLength = item->parentElement->text.length - item->textOffset; }
00517 else {
00518 item->mode = xData_itemModeEnd;
00519 } }
00520 else {
00521 item->textLength = item->element->textOffset - item->textOffset;
00522 }
00523 }
00524 }
00525 return( item->mode );
00526 }
00527
00528
00529
00530 char *xData_getAttributesValue( xData_attributionList *attributes, const char *name ) {
00531
00532 int i;
00533 char *value = NULL;
00534
00535 for( i = 0; i < attributes->number; i++ ) {
00536 if( !strcmp( attributes->attributes[i].name, name ) ) {
00537 value = attributes->attributes[i].value;
00538 break;
00539 }
00540 }
00541 return( value );
00542 }
00543
00544
00545
00546 const char *xData_getAttributesValueInElement( xData_element *element, const char *name ) {
00547
00548 return( (const char *) xData_getAttributesValue( &(element->attributes), name ) );
00549 }
00550
00551
00552
00553
00554 int xData_initializeAttributionList( statusMessageReporting *, xData_attributionList *attributes ) {
00555
00556 attributes->number = 0;
00557 attributes->size = 0;
00558 attributes->attributes = NULL;
00559 return( 0 );
00560 }
00561
00562
00563
00564 int xData_copyAttributionList( statusMessageReporting *smr, xData_attributionList *dest, xData_attributionList *src ) {
00565
00566
00567
00568 int i;
00569 size_t lens;
00570 xData_attribute *d, *s;
00571 char *p;
00572
00573
00574 if( ( dest->attributes = (xData_attribute*) xData_malloc2( smr, src->size, 0, "attributes" ) ) == NULL ) return( 1 );
00575 dest->number = src->number;
00576 dest->size = src->size;
00577 d = dest->attributes;
00578 s = src->attributes;
00579 p = (char *) &(dest->attributes[src->number]);
00580 for( i = 0; i < src->number; i++, s++, d++ ) {
00581 lens = strlen( s->name ) + 1;
00582 d->name = p;
00583 strcpy( p, s->name );
00584 p += lens;
00585 lens = strlen( s->value ) + 1;
00586 d->value= p;
00587 strcpy( p, s->value );
00588 p += lens;
00589 }
00590
00591 return( 0 );
00592 }
00593
00594
00595
00596 int xData_attributeListLength( xData_attributionList *attributes ) {
00597
00598 return( attributes->number );
00599 }
00600
00601
00602
00603 xData_attribute *xData_attributeByIndex( xData_attributionList *attributes, int index ) {
00604
00605 if( index >= attributes->number ) return( NULL );
00606 return( &(attributes->attributes[index]) );
00607 }
00608
00609
00610
00611 int xData_releaseAttributionList( statusMessageReporting *smr, xData_attributionList *attributes ) {
00612
00613 attributes->number = 0;
00614 attributes->size = 0;
00615
00616 attributes->attributes = (xData_attribute*) xData_free( smr, attributes->attributes );
00617 return( 0 );
00618 }
00619
00620
00621
00622 xData_element *xData_getElements_xDataElement( statusMessageReporting *smr, xData_element *element ) {
00623
00624
00625 return( xData_getOneElementByTagName( smr, element, (char*) "xData", 1 ) );
00626 }
00627
00628
00629
00630 static int xData_init_xDataTypeNone( xDataType *xDT, xData_element *element ) {
00631
00632 xDT->status = xData_xDataType_Ok;
00633 xDT->typeString = NULL;
00634 xDT->element = element;
00635 xDT->toData = NULL;
00636 xDT->toString = NULL;
00637 xDT->release = NULL;
00638 xDT->indexPresent = 1;
00639 xDT->startPresent = 1;
00640 xDT->endPresent = 1;
00641 xDT->lengthPresent = 1;
00642 xDT->index = -1;
00643 xDT->start = -1;
00644 xDT->end = -1;
00645 xDT->length = -1;
00646 xDT->data = NULL;
00647 return( 0 );
00648 }
00649
00650
00651
00652 int xData_getCommonData( statusMessageReporting *smr, xData_element *element, xData_Int *index, xData_Int *start, xData_Int *end,
00653 xData_Int *length ) {
00654
00655 if( element->xDataTypeInfo.typeString == NULL ) {
00656 smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( element ), __FILE__, __LINE__, 1, "element %s is not xData", element->fullName );
00657 return( 1 );
00658 }
00659 *index = element->xDataTypeInfo.index;
00660 *start = element->xDataTypeInfo.start;
00661 *end = element->xDataTypeInfo.end;
00662 *length = element->xDataTypeInfo.length;
00663 return( 0 );
00664 }
00665
00666
00667
00668 int xData_xDataTypeConvertAttributes( statusMessageReporting *smr, xData_element *element ) {
00669
00670 xDataType *xDT = &(element->xDataTypeInfo);
00671 void *smrUser = xData_get_smrUserInterfaceFromElement( element );
00672
00673 xDT->index = -1;
00674 xDT->start = -1;
00675 xDT->end = -1;
00676 xDT->length = -1;
00677 if( ( xDT->indexPresent = xData_convertAttributeTo_xData_Int( smr, element, "index", &(xDT->index) ) ) < 0 ) return( 1 );
00678 if( ( xDT->startPresent = xData_convertAttributeTo_xData_Int( smr, element, "start", &(xDT->start) ) ) < 0 ) return( 1 );
00679 if( ( xDT->endPresent = xData_convertAttributeTo_xData_Int( smr, element, "end", &(xDT->end) ) ) < 0 ) return( 1 );
00680 if( ( xDT->lengthPresent = xData_convertAttributeTo_xData_Int( smr, element, "length", &(xDT->length) ) ) < 0 ) return( 1 );
00681 if( ( xDT->endPresent > 0 ) ) {
00682 if( xDT->lengthPresent > 0 ) {
00683 smr_setMessageError( smr, smrUser, __FILE__, __LINE__, 1, "missing length (or end) in xData" );
00684 return( 1 );
00685 }
00686 xDT->end = xDT->length; }
00687 else {
00688 if( xDT->lengthPresent > 0 ) xDT->length = xDT->end;
00689 }
00690
00691 if( xDT->startPresent > 0 ) xDT->start = 0;
00692 if( xDT->start < 0 ) {
00693 smr_setMessageError( smr, smrUser, __FILE__, __LINE__, 1, "start = %d < 0", xDT->start );
00694 return( 1 );
00695 }
00696 if( xDT->end < xDT->start ) {
00697 smr_setMessageError( smr, smrUser, __FILE__, __LINE__, 1, "start = %d >= end = %d", xDT->start, xDT->end );
00698 return( 1 );
00699 }
00700 if( xDT->length < 0 ) {
00701 smr_setMessageError( smr, smrUser, __FILE__, __LINE__, 1, "length = %d < 0", xDT->length );
00702 return( 1 );
00703 }
00704
00705 return( 0 );
00706 }
00707
00708
00709
00710 xData_Int xData_convertAttributeTo_xData_Int( statusMessageReporting *smr, xData_element *element, const char *name, xData_Int *n ) {
00711
00712
00713
00714 const char *value;
00715 char *e;
00716
00717 if( ( value = xData_getAttributesValueInElement( element, name ) ) == NULL ) return( 1 );
00718
00719 *n = strtol( value, &e, 10 );
00720 if( *e != 0 ) {
00721 smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( element ), __FILE__, __LINE__, 1,
00722 "could not convert attribute %s's value = %s to an integer", name, value );
00723 return( -1 );
00724 }
00725 return( 0 );
00726 }
00727
00728
00729
00730 int xData_convertAttributeToDouble( statusMessageReporting *smr, xData_element *element, const char *name, double *d ) {
00731
00732
00733
00734 const char *value;
00735 char *e;
00736
00737 if( ( value = xData_getAttributesValueInElement( element, name ) ) == NULL ) return( 1 );
00738 *d = strtod( value, &e );
00739 if( *e != 0 ) {
00740 smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( element) , __FILE__, __LINE__, 1,
00741 "could not convert attribute %s's values = %s to a double", name, value );
00742 return( -1 );
00743 }
00744 return( 0 );
00745 }
00746
00747
00748
00749
00750 int xData_numberOfElementsByTagName( statusMessageReporting *, xData_element *element, const char *tagName ) {
00751
00752 int n = 0;
00753 xData_element *child;
00754
00755 for( child = xData_getFirstElement( element ); child != NULL; child = xData_getNextElement( child ) ) if( !strcmp( child->name, tagName ) ) n++;
00756 return( n );
00757 }
00758
00759
00760
00761 xData_elementList *xData_getElementsByTagName( statusMessageReporting *smr, xData_element *element, const char *tagName ) {
00762
00763 int n = xData_numberOfElementsByTagName( smr, element, tagName );
00764 size_t size;
00765 xData_element *child;
00766 xData_elementListItem *p;
00767 xData_elementList *list = NULL;
00768
00769
00770 size = sizeof( xData_elementList ) + n * sizeof( xData_elementListItem );
00771
00772 if( ( list = (xData_elementList*) xData_malloc2( smr, size, 0, "list" ) ) != NULL ) {
00773 list->n = n;
00774 p = list->items = (xData_elementListItem *) &(list[1]);
00775 for( child = xData_getFirstElement( element ); child != NULL; child = xData_getNextElement( child ) ) {
00776 if( !strcmp( child->name, tagName ) ) {
00777 p->element = child;
00778 p->sortString = NULL;
00779 p++;
00780 }
00781 }
00782 }
00783 return( list );
00784 }
00785
00786
00787
00788 xData_elementList *xData_getElementsByTagNameAndSort( statusMessageReporting *smr, xData_element *element, const char *tagName,
00789 const char *sortAttributeName, xData_sortElementFunc sortFunction ) {
00790
00791 int i;
00792 xData_elementList *list = xData_getElementsByTagName( smr, element, tagName );
00793 xData_elementListItem *p;
00794
00795 if( list != NULL ) {
00796 if( sortFunction == NULL ) {
00797 sortFunction = (xData_sortElementFunc) xData_elementList_defaultSorter;
00798 if( sortAttributeName == NULL ) sortFunction = (xData_sortElementFunc) xData_elementList_indexSorter;
00799 }
00800 if( sortAttributeName == NULL ) sortAttributeName = "index";
00801 for( i = 0, p = list->items; i < list->n; i++, p++ ) p->sortString = xData_getAttributesValueInElement( p->element, sortAttributeName );
00802 qsort( list->items, list->n, sizeof( xData_elementListItem ), sortFunction );
00803 }
00804
00805 return( list );
00806 }
00807
00808
00809
00810 xData_element *xData_getOneElementByTagName( statusMessageReporting *smr, xData_element *element, char *name, int required ) {
00811
00812 xData_elementList *list;
00813 xData_element *xData = NULL;
00814
00815 if( ( list = xData_getElementsByTagName( smr, element, name ) ) != NULL ) {
00816 if( list->n == 0 ) {
00817 if( required ) smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( element ), __FILE__, __LINE__,
00818 1, "element %s does not have sub-element named %s", element->fullName, name ); }
00819 else if( list->n > 1 ) {
00820 smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( element ), __FILE__, __LINE__, 1,
00821 "element %s contains more than one sub-element named %s", element->fullName, name ); }
00822 else {
00823 xData = list->items[0].element;
00824 }
00825 xData_freeElementList( smr, list );
00826 }
00827 return( xData );
00828 }
00829
00830
00831
00832 void xData_freeElementList( statusMessageReporting *smr, xData_elementList *list ) {
00833
00834 xData_free( smr, list );
00835 }
00836
00837
00838
00839 static char *xData_getTraceback( statusMessageReporting *smr, xData_element *element ) {
00840
00841
00842
00843 int size;
00844 char *s, *name;
00845
00846 name = element->name;
00847 size = strlen( name ) + 1;
00848 if( ( s = xData_getTraceback2( smr, element->parentRoot, size ) ) != NULL ) {
00849 strcat( s, "/" );
00850 strcat( s, name );
00851 }
00852 return( s );
00853 }
00854
00855
00856
00857 static char *xData_getTraceback2( statusMessageReporting *smr, xData_rootElement *parentRoot, int n ) {
00858
00859 int size;
00860 char *s, *name;
00861
00862 if( parentRoot->parentRoot == NULL ) {
00863
00864 s = (char*) xData_malloc2( smr, n + 1, 0, "traceback string" );
00865 *s = 0; }
00866 else {
00867 name = parentRoot->parentElement->name;
00868 size = strlen( name ) + 1;
00869 n += size;
00870 if( ( s = xData_getTraceback2( smr, parentRoot->parentRoot, n ) ) != NULL ) {
00871 strcat( s, "/" );
00872 strcat( s, name );
00873 }
00874 }
00875 return( s );
00876 }
00877
00878
00879
00880 static int xData_elementList_defaultSorter( void const *p1, void const *p2 ) {
00881
00882 const char *s1 = ((xData_elementListItem *) p1)->sortString, *s2 = ((xData_elementListItem *) p2)->sortString;
00883
00884 if( s2 == NULL ) return( -1 );
00885 if( s1 == NULL ) return( 1 );
00886 return( strcmp( s1, s2 ) );
00887 }
00888
00889
00890
00891 static int xData_elementList_indexSorter( void const *p1, void const *p2 ) {
00892
00893 xData_element *e1 = ((xData_elementListItem *) p1)->element, *e2 = ((xData_elementListItem *) p2)->element;
00894
00895 return( e1->index - e2->index );
00896 }
00897
00898
00899
00900 int xData_is_xDataType( statusMessageReporting *smr, xDataType *xDT, char const * const type, int setMsg ) {
00901
00902 if( xDT->typeString == NULL ) {
00903 if( setMsg ) smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( xDT->element ), __FILE__, __LINE__, 1,
00904 "element %s not xData object", xDT->element->fullName ); }
00905 else if( xDT->typeString != type ) {
00906 if( setMsg ) smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( xDT->element ), __FILE__, __LINE__, 1,
00907 "Element %s is not xData object of type %s", type );
00908 }
00909 return( xDT->typeString == type );
00910 }
00911
00912
00913
00914 char const *xData_getFileName( xData_document *doc ) {
00915
00916 return( doc->fileName );
00917 }
00918
00919
00920
00921 int xData_setFileName( statusMessageReporting *smr, xData_document *doc, char const *fileName ) {
00922
00923 doc->fileName = (char*) xData_free( smr, doc->fileName );
00924 if( fileName != NULL ) {
00925
00926 if( ( doc->fileName = (char*) xData_malloc2( smr, strlen( fileName ) + 1, 0, "doc->fileName" ) ) == NULL ) return( 1 );
00927 strcpy( doc->fileName, fileName );
00928 }
00929 return( 0 );
00930 }
00931
00932
00933
00934 xData_document *xData_getElementsDocument( xData_element *element ) {
00935
00936 xData_rootElement* root = element->parentRoot;
00937
00938 while( root->parentRoot != NULL ) root = root->parentRoot;
00939 return( root->xData_doc );
00940 }
00941
00942
00943
00944 void *xData_get_smrUserInterfaceFromDocument( xData_document *doc ) {
00945
00946 if( doc == NULL ) return( NULL );
00947 return( &(doc->smrUserInterface ) );
00948 }
00949
00950
00951
00952 void *xData_get_smrUserInterfaceFromElement( xData_element *element ) {
00953
00954 return( xData_get_smrUserInterfaceFromDocument( xData_getElementsDocument( element ) ) );
00955 }
00956
00957
00958
00959 static int xData_smrUserInterfaceInitialize( xData_document *doc ) {
00960
00961 doc->smrUserInterface.smrUserInterface = xData_smrUserInterface;
00962 doc->smrUserInterface.doc = doc;
00963 return( 0 );
00964 }
00965
00966
00967
00968 static int xData_smrUserInterfaceFree( xData_document *doc ) {
00969
00970 doc->smrUserInterface.smrUserInterface = NULL;
00971 doc->smrUserInterface.doc = NULL;
00972 return( 0 );
00973 }
00974
00975
00976
00977 static int xData_smrUserInterface( void *userData, char **str ) {
00978
00979 int size, fileNameSize = 0, elementSize = 0;
00980 xData_smr *smrUserInterface = (xData_smr *) userData;
00981 static char lcl[] = "\nat line %d and column %d", el[] = "\nin element ", fl[] = "\nof file ";
00982 char str_lcl[sizeof( lcl ) + 40];
00983 xData_rootElement *currentRoot = smrUserInterface->doc->currentRoot;
00984
00985 if( smrUserInterface->doc->fileName != NULL ) fileNameSize = strlen( smrUserInterface->doc->fileName ) + strlen( fl );
00986 if( currentRoot != NULL ) {
00987 if( currentRoot->parentElement != NULL ) {
00988 sprintf( str_lcl, lcl, currentRoot->parentElement->docInfo.line, currentRoot->parentElement->docInfo.column );
00989 elementSize = strlen( str_lcl ) + strlen( currentRoot->parentElement->fullName ) + strlen( el );
00990 }
00991 }
00992 size = fileNameSize + elementSize;
00993 if( ( fileNameSize != 0 ) && ( elementSize != 0 ) ) size++;
00994 if( ( size > 0 ) && ( str != NULL ) ) {
00995
00996 if( ( *str = (char*) malloc( size + 1 ) ) == NULL ) return( -1 );
00997 if( ( size != 0 ) && ( elementSize != 0 ) ) {
00998 sprintf( *str, "%s%s%s%s%s", str_lcl, el, currentRoot->parentElement->fullName, fl, smrUserInterface->doc->fileName ); }
00999 else if( size != 0 ) {
01000 sprintf( *str, "%s%s", fl, smrUserInterface->doc->fileName ); }
01001 else {
01002 sprintf( *str, "%s%s%s", str_lcl, el, currentRoot->parentElement->fullName );
01003 }
01004 }
01005 return( size );
01006 }
01007
01008
01009
01010 int xData_stringTo_xData_Int( statusMessageReporting *smr, void *smrUserInterface, char const *c, xData_Int *value, char const *endings, char **e ) {
01011
01012 char const *s;
01013 char tmp[64];
01014 int status = 1, n = sizeof( tmp );
01015
01016 for( s = c; *s != 0; s++ ) if( !isspace( *s ) ) break;
01017
01018 *value = strtol( s, e, 10 );
01019 if( *e == s ) {
01020 smr_setMessageError(smr, smrUserInterface, __FILE__, __LINE__, 1, "could not convert \"%s\" to an integer", xData_shortStringForMessage( n, tmp, c ));}
01021 else {
01022 if( *endings == 0 ) while( isspace( **e ) ) (*e)++;
01023 if( **e == 0 ) {
01024 status = 0; }
01025 else {
01026 if( *endings == 0 ) {
01027 smr_setMessageError( smr, smrUserInterface, __FILE__, __LINE__, 1, "integer string \"%s\" does not end with a '\\0'",
01028 xData_shortStringForMessage( n, tmp, c ) ); }
01029 else {
01030 if( strchr( endings, **e ) == NULL ) {
01031 smr_setMessageError( smr, smrUserInterface, __FILE__, __LINE__, 1, "integer string \"%s\" does not end with a white space or a '\\0\'",
01032 xData_shortStringForMessage( n, tmp, c ) ); }
01033 else {
01034 status = 0;
01035 }
01036 }
01037 }
01038 }
01039 return( status );
01040 }
01041
01042
01043
01044 int xData_stringTo_double( statusMessageReporting *smr, void *smrUserInterface, char const *c, double *value, char const *endings, char **e ) {
01045
01046 char const *s;
01047 char tmp[64];
01048 int status = 1, n = sizeof( tmp );
01049
01050 for( s = c; *s != 0; s++ ) if( !isspace( *s ) ) break;
01051 *value = strtod( s, e );
01052 if( *e == s ) {
01053 smr_setMessageError(smr, smrUserInterface, __FILE__, __LINE__, 1, "could not convert \"%s\" to an double", xData_shortStringForMessage( n, tmp, c ));}
01054 else {
01055 if( *endings == 0 ) while( isspace( **e ) ) (*e)++;
01056 if( **e == 0 ) {
01057 status = 0; }
01058 else {
01059 if( *endings == 0 ) {
01060 smr_setMessageError( smr, smrUserInterface, __FILE__, __LINE__, 1, "double string \"%s\" does not end with a '\\0'",
01061 xData_shortStringForMessage( n, tmp, c ) ); }
01062 else {
01063 if( strchr( endings, **e ) == NULL ) {
01064 smr_setMessageError( smr, smrUserInterface, __FILE__, __LINE__, 1, "double string \"%s\" does not end with a white space or a '\\0\'",
01065 xData_shortStringForMessage( n, tmp, c ) ); }
01066 else {
01067 status = 0;
01068 }
01069 }
01070 }
01071 }
01072 return( status );
01073 }
01074
01075
01076
01077
01078 int xData_addToAccessed( statusMessageReporting *, xData_element *element, int increment ) {
01079
01080 element->accessed += increment;
01081 return( element->accessed );
01082 }
01083
01084
01085
01086
01087 int xData_getAccessed( statusMessageReporting *, xData_element *element ) {
01088
01089 return( element->accessed );
01090 }
01091
01092
01093
01094 static char const *xData_shortStringForMessage( size_t size, char *Out, char const *In ) {
01095
01096 if( strlen( In ) > size ) {
01097 strncpy( Out, In, size - 5 );
01098 Out[size-5] = 0;
01099 strcat( Out, " ..." );
01100 return( Out );
01101 }
01102 return( In );
01103 }
01104
01105 #if defined __cplusplus
01106 }
01107 #endif