xData.cc

Go to the documentation of this file.
00001 /*
00002 # <<BEGIN-copyright>>
00003 # Copyright (c) 2010, Lawrence Livermore National Security, LLC. 
00004 # Produced at the Lawrence Livermore National Laboratory 
00005 # Written by Bret R. Beck, beck6@llnl.gov. 
00006 # CODE-461393
00007 # All rights reserved. 
00008 #  
00009 # This file is part of GIDI. For details, see nuclear.llnl.gov. 
00010 # Please also read the "Additional BSD Notice" at nuclear.llnl.gov. 
00011 # 
00012 # Redistribution and use in source and binary forms, with or without modification, 
00013 # are permitted provided that the following conditions are met: 
00014 #
00015 #      1) Redistributions of source code must retain the above copyright notice, 
00016 #         this list of conditions and the disclaimer below.
00017 #      2) Redistributions in binary form must reproduce the above copyright notice, 
00018 #         this list of conditions and the disclaimer (as noted below) in the 
00019 #          documentation and/or other materials provided with the distribution.
00020 #      3) Neither the name of the LLNS/LLNL nor the names of its contributors may be 
00021 #         used to endorse or promote products derived from this software without 
00022 #         specific prior written permission. 
00023 #
00024 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
00025 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00026 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT 
00027 # SHALL LAWRENCE LIVERMORE NATIONAL SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR 
00028 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00029 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
00030 # OR SERVICES;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
00031 # AND ON  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00032 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
00033 # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00034 # <<END-copyright>>
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 *   Returns NULL is any error occurred. If an error occurs in an expat routine, xData_parseEndOfXML will set smr appropriately.
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 *   Returns NULL is any error occurred. If an error occurs in an expat routine, xData_parseEndOfXML will set smr appropriately.
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 *   Returns NULL is any error occurred.
00144 */
00145     xData_document *doc;
00146 
00147     //if( ( doc = xData_malloc2( smr, sizeof( xData_document ), 1, "xData_document" ) ) != NULL ) {
00148     if( ( doc = (xData_document*) xData_malloc2( smr, sizeof( xData_document ), 1, "xData_document" ) ) != NULL ) {
00149         //if( xData_parseInitialize( smr, doc, func, userData ) ) doc = xData_parseFree( smr, doc );
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     //doc->err = 0;
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     //doc->root.children = xData_parseFreeElement( smr, doc->root.children );
00212     doc->root.children = (xData_element*) xData_parseFreeElement( smr, doc->root.children );
00213     //doc->fileName = xData_free( smr, doc->fileName );
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     //element->childrenRoot.children = xData_parseFreeElement( smr, element->childrenRoot.children );
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 *   Always terminates text with a 0.
00310 */
00311     //xData_document *doc = userData;
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     //if( needSize > text->allocated ) {
00320     if( needSize > (int) text->allocated ) {
00321         if( text->allocated != 0 ) {
00322             l = ( 20 * text->allocated ) / 100;
00323             if( l < 100 ) l = 100;
00324             //if( needSize < ( text->allocated + l ) ) needSize = text->allocated + l;
00325             if( needSize < ( (int) text->allocated + l ) ) needSize = text->allocated + l;
00326         }
00327         text->allocated = needSize;
00328         //text->text = xData_realloc2( doc->smr, text->text, text->allocated, "text" );
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     //element = xData_malloc2( doc->smr, sizeof( xData_element ), 1, "xData_element" );
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     //if( ( element->name = xData_malloc2( doc->smr, strlen( name ) + 1, 0, "name" ) ) == NULL ) {
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         //if( ( element->attributes.attributes = xData_malloc2( doc->smr, element->attributes.size, 0, "attributes") ) == NULL ) {
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 //int xData_initializeAttributionList( statusMessageReporting *smr, xData_attributionList *attributes ) {
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 *   The dest must not be active, else a memory leak will occur, as this routine does no free-ing.
00567 */
00568     int i;
00569     size_t lens;
00570     xData_attribute *d, *s;
00571     char *p;
00572 
00573     //if( ( dest->attributes = xData_malloc2( smr, src->size, 0, "attributes" ) ) == NULL ) return( 1 );
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     //attributes->attributes = xData_free( smr, attributes->attributes );
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     //return( xData_getOneElementByTagName( smr, element, "xData", 1 ) );
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;                  /* The following describes the meaning of present variables. */
00639     xDT->startPresent = 1;                  /* If < 0, an error occured in converting value to an integer. */
00640     xDT->endPresent = 1;                    /* If > 0, not present as an attribute. */
00641     xDT->lengthPresent = 1;                 /* Else, if 0, present and converted without an error. */
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 *   Returns 1 if no such attribute, -1 if error converting to xData_Int and 0 if successful.
00713 */
00714     const char *value;
00715     char *e;
00716 
00717     if( ( value = xData_getAttributesValueInElement( element, name ) ) == NULL ) return( 1 );
00718     //*n = strtoll( value, &e, 10 );
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 *   Returns 1 if no such attribute, -1 if error converting to double and 0 if successful.
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 //int xData_numberOfElementsByTagName( statusMessageReporting *smr, xData_element *element, const char *tagName ) {
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     //if( ( list = xData_malloc2( smr, size, 0, "list" ) ) != NULL ) {
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 *   Returned string must be freed by calling routine.
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         //s = xData_malloc2( smr, n + 1, 0, "traceback string" );
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         //if( ( doc->fileName = xData_malloc2( smr, strlen( fileName ) + 1, 0, "doc->fileName" ) ) == NULL ) return( 1 );
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         //if( ( *str = malloc( size + 1 ) ) == NULL ) return( -1 );
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     //*value = strtoll( s, e, 10 );
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 //int xData_addToAccessed( statusMessageReporting *smr, xData_element *element, int increment ) {
01078 int xData_addToAccessed( statusMessageReporting *, xData_element *element, int increment ) {
01079 
01080     element->accessed += increment;
01081     return( element->accessed );
01082 }
01083 /*
01084 ************************************************************
01085 */
01086 //int xData_getAccessed( statusMessageReporting *smr, xData_element *element ) {
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

Generated on Mon May 27 17:50:36 2013 for Geant4 by  doxygen 1.4.7