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 <string.h>
00037 #include <limits.h>
00038 #ifdef WIN32
00039    #include <Shlwapi.h>
00040 #endif
00041 #include <tpia_map.h>
00042 
00043 #if defined __cplusplus
00044 namespace GIDI {
00045 using namespace GIDI;
00046 #endif
00047 
00048 static tpia_mapEntry *_tpia_map_addEntry( statusMessageReporting *smr, tpia_map *map, enum tpia_mapEntry_type type, const char *schema, const char *path,
00049     const char *evaluation, const char *projectile, const char *target );
00050 static char *_tpia_map_findTarget2( statusMessageReporting *smr, tpia_map *map, const char *evaluation, const char *projectile, const char *target );
00051 static int _tpia_map_findAllOfTarget2( statusMessageReporting *smr, tpia_map *mapAllOfTarget, tpia_map *map, const char *projectile, const char *targetName );
00052 static int _tpia_map_walkTree2( statusMessageReporting *smr, tpia_map *map, int level, int (*handler)( tpia_mapEntry *entry, int level, void *userData), 
00053     void *userData );
00054 static void _tpia_map_simpleWrite2( FILE *f, tpia_map *map, int level );
00055 static int _tpia_map_smrUserInterface( void *userData, char **str );
00056 
00057 
00058 
00059 tpia_map *tpia_map_create( statusMessageReporting *smr ) {
00060 
00061     tpia_map *map;
00062     
00063     
00064     if( ( map = (tpia_map*) xData_malloc2( smr, sizeof( tpia_map ), 0, "map" ) ) == NULL ) return( NULL );
00065     
00066     if( tpia_map_initialize( smr, map ) ) map = (tpia_map*) tpia_map_free( NULL, map );
00067     return( map );
00068 }
00069 
00070 
00071 
00072 
00073 int tpia_map_initialize( statusMessageReporting *, tpia_map *map ) {
00074 
00075     memset( map, 0, sizeof( tpia_map ) );
00076     map->status = tpia_map_status_Ok;
00077     map->smrUserInterface.smrUserInterface = _tpia_map_smrUserInterface;
00078     map->smrUserInterface.map = map;
00079     map->path = NULL;
00080     map->mapFileName = NULL;
00081     map->numberOfEntries = 0;
00082     map->mapEntries = NULL;
00083     return( 0 );
00084 }
00085 
00086 
00087 
00088 tpia_map *tpia_map_readFile( statusMessageReporting *smr, const char *basePath, const char *mapFileName ) {
00089 
00090 
00091 
00092     int n = 0;
00093     xData_document *doc;
00094     xData_element *element;
00095     xData_element *child;
00096     tpia_map *map;
00097     const char *evaluation, *projectile, *targetName, *path, *schema;
00098 #ifndef WIN32
00099     char realPath[2 * ( PATH_MAX + 1 )], *p = &(realPath[PATH_MAX+1]);
00100 #endif
00101 #ifdef WIN32
00102     char realPath[2 * ( _MAX_PATH + 1 )], *p = &(realPath[_MAX_PATH+1]);
00103 #endif
00104 
00105     if( ( map = tpia_map_create( smr ) ) == NULL ) return( NULL );
00106 
00107     if( ( basePath == NULL ) || ( mapFileName[0] == '/' ) ) {
00108         strcpy( realPath, mapFileName ); }
00109     else {
00110         strcpy( realPath, basePath );
00111         strcat( realPath, "/" );
00112         strcat( realPath, mapFileName );
00113     }
00114 #ifndef WIN32
00115     if( realpath( realPath, p ) == NULL ) {
00116         smr_setMessageError( smr, NULL, __FILE__, __LINE__, tpia_map_status_mapParsing, "No map file %s\n", mapFileName );
00117         
00118         return( (tpia_map*) tpia_map_free( NULL, map ) );
00119     }
00120 #endif
00121     n = strlen( p ) + 2;
00122     
00123     
00124     if( ( map->path = (char*) xData_malloc2( smr, 2 * n, 0, "map->path" ) ) == NULL ) return( (tpia_map*) tpia_map_free( NULL, map ) );
00125     map->mapFileName = &(map->path[n + 1]);
00126     strcpy( map->mapFileName, p );
00127     strcpy( map->path, p );
00128     if( ( p = strrchr( map->path, '/' ) ) != NULL ) {
00129         *p = 0; }
00130     else {
00131         strcpy( map->path, "." );
00132     }
00133 
00134     
00135     if( ( doc = xData_parseReadFile( smr, map->mapFileName, NULL, NULL ) ) == NULL ) return( (tpia_map*) tpia_map_free( NULL, map ) );
00136 
00137     element = xData_getDocumentsElement( doc );
00138     for( child = xData_getFirstElement( element ); child != NULL; child = xData_getNextElement( child ) ) {
00139         if( !strcmp( child->name, "path" ) ) {
00140             if( ( path = xData_getAttributesValueInElement( child , "path" ) ) == NULL ) {
00141                 smr_setMessageError( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_mapParsing, "path missing path attribute" );
00142                 break;
00143             }
00144             if( ( projectile = xData_getAttributesValueInElement( child , "projectile" ) ) == NULL ) {
00145                 smr_setMessageError( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_mapParsing, "path missing projectile attribute" );
00146                 break;
00147             }
00148             tpia_map_addPath( smr, map, path, projectile ); }
00149         else if( !strcmp( child->name, "target" ) ) {
00150             if( ( schema = xData_getAttributesValueInElement( child , "schema" ) ) == NULL ) {
00151                 smr_setMessageError( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_mapParsing, "target missing 'schema' attribute" );
00152                 break;
00153             }
00154             if( ( path = xData_getAttributesValueInElement( child , "path" ) ) == NULL ) {
00155                 smr_setMessageError( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_mapParsing, "target missing 'path' attribute" );
00156                 break;
00157             }
00158             if( ( evaluation = xData_getAttributesValueInElement( child , "evaluation" ) ) == NULL ) {
00159                 smr_setMessageError( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_mapParsing, "target missing 'evaluation' attribute" );
00160                 break;
00161             }
00162             if( ( projectile = xData_getAttributesValueInElement( child , "projectile" ) ) == NULL ) {
00163                 smr_setMessageError( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_mapParsing, "target missing 'projectile' attribute" );
00164                 break;
00165             }
00166             if( ( targetName = xData_getAttributesValueInElement( child , "target" ) ) == NULL ) {
00167                 smr_setMessageError( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_mapParsing, "target missing 'target' attribute" );
00168                 break;
00169             }
00170             tpia_map_addTarget( smr, map, schema, path, evaluation, projectile, targetName ); }
00171         else {
00172             smr_setMessageError( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_mapParsing, "invalid element = %s", child->name );
00173         }
00174         if( !smr_isOk( smr ) ) break;
00175     }
00176     xData_parseFree( smr, doc );
00177     
00178     if( !smr_isOk( smr ) ) map = (tpia_map*) tpia_map_free( NULL, map );
00179     return( map );
00180 }
00181 
00182 
00183 
00184 void *tpia_map_free( statusMessageReporting *smr, tpia_map *map ) {
00185 
00186     tpia_map_release( smr, map );
00187     xData_free( smr, map );
00188     return( NULL );
00189 }
00190 
00191 
00192 
00193 void tpia_map_release( statusMessageReporting *smr, tpia_map *map ) {
00194 
00195     tpia_mapEntry *entry, *next;
00196 
00197     if( map->path != NULL ) xData_free( NULL, map->path );
00198     for( entry = map->mapEntries; entry != NULL; entry = next ) {
00199         next = entry->next;
00200         if( entry->schema != NULL ) xData_free( NULL, entry->schema );
00201         if( entry->path != NULL ) xData_free( NULL, entry->path );
00202         if( entry->evaluation != NULL ) xData_free( NULL, entry->evaluation );
00203         if( entry->projectile != NULL ) xData_free( NULL, entry->projectile );
00204         if( entry->targetName != NULL ) xData_free( NULL, entry->targetName );
00205         if( entry->map != NULL ) tpia_map_free( smr, entry->map );
00206         xData_free( NULL, entry );
00207     }
00208     map->numberOfEntries = 0;
00209     map->mapEntries = NULL;
00210     map->status = tpia_map_status_Ok;
00211 }
00212 
00213 
00214 
00215 tpia_mapEntry *tpia_map_getFirstEntry( tpia_map *map ) {
00216 
00217     return( map->mapEntries );
00218 }
00219 
00220 
00221 
00222 tpia_mapEntry *tpia_map_getNextEntry( tpia_mapEntry *entry ) {
00223 
00224     return( entry->next );
00225 }
00226 
00227 
00228 
00229 int tpia_map_addTarget( statusMessageReporting *smr, tpia_map *map, const char *schema, const char *path, const char *evaluation, const char *projectile, const char *target ) {
00230 
00231     return( _tpia_map_addEntry( smr, map, tpia_mapEntry_type_target, schema, path, evaluation, projectile, target ) != NULL );
00232 }
00233 
00234 
00235 
00236 int tpia_map_addPath( statusMessageReporting *smr, tpia_map *map, const char *path, const char *projectile ) {
00237 
00238     tpia_mapEntry *entry = _tpia_map_addEntry( smr, map, tpia_mapEntry_type_path, NULL, path, NULL, projectile, NULL );
00239 
00240     if( entry != NULL ) {
00241         if( ( entry->map = tpia_map_readFile( smr, map->path, entry->path ) ) == NULL ) entry = NULL;
00242     }
00243     return( entry != NULL );
00244 }
00245 
00246 
00247 
00248 static tpia_mapEntry *_tpia_map_addEntry( statusMessageReporting *smr, tpia_map *map, enum tpia_mapEntry_type type, const char *schema, const char *path, 
00249     const char *evaluation, const char *projectile, const char *targetName ) {
00250 
00251     tpia_mapEntry *p;
00252     tpia_mapEntry *entry;
00253 
00254     
00255     if( ( entry = (tpia_mapEntry*) xData_malloc2( smr, sizeof( tpia_mapEntry ), 1, "entry" ) ) == NULL ) return( NULL );
00256     entry->next = NULL;
00257     entry->type = type;
00258     entry->path = NULL;
00259     entry->map = NULL;
00260     if( path != NULL ) {
00261         
00262         if( ( entry->path = (char*) xData_malloc2( smr, strlen( path ) + 1, 0, "path" ) ) == NULL ) {
00263             xData_free( smr, entry );
00264             return( NULL );
00265         }
00266         strcpy( entry->path, path );
00267     }
00268     entry->evaluation = NULL;
00269     if( evaluation != NULL ) {
00270         
00271         if( ( entry->evaluation = (char*) xData_malloc2( smr, strlen( evaluation ) + 1, 0, "evaluation" ) ) == NULL ) {
00272             xData_free( smr, entry->path );
00273             xData_free( smr, entry );
00274             return( NULL );
00275         }
00276         strcpy( entry->evaluation, evaluation );
00277     }
00278     entry->projectile = NULL;
00279     if( projectile != NULL ) {
00280         
00281         if( ( entry->projectile = (char*) xData_malloc2( smr, strlen( projectile ) + 1, 0, "projectile" ) ) == NULL ) {
00282             xData_free( smr, entry->evaluation );
00283             xData_free( smr, entry->path );
00284             xData_free( smr, entry );
00285             return( NULL );
00286         }
00287         strcpy( entry->projectile, projectile );
00288     }
00289     entry->targetName = NULL;
00290     if( targetName != NULL ) {
00291         
00292         if( ( entry->targetName = (char*) xData_malloc2( smr, strlen( targetName ) + 1, 0, "target" ) ) == NULL ) {
00293             xData_free( smr, entry->path );
00294             xData_free( smr, entry->evaluation );
00295             xData_free( smr, entry->projectile );
00296             xData_free( smr, entry );
00297             return( NULL );
00298         }
00299         strcpy( entry->targetName, targetName );
00300     }
00301     entry->schema = NULL;
00302     if( schema != NULL ) {
00303         
00304         if( ( entry->schema = (char*) xData_malloc2( smr, strlen( schema ) + 1, 0, "schema" ) ) == NULL ) {
00305             xData_free( smr, entry->path );
00306             xData_free( smr, entry->evaluation );
00307             xData_free( smr, entry->projectile );
00308             xData_free( smr, entry->targetName );
00309             xData_free( smr, entry );
00310             return( NULL );
00311         }
00312         strcpy( entry->schema, schema );
00313     }
00314 
00315     if( map->mapEntries == NULL ) {
00316         map->mapEntries = entry; }
00317     else {
00318         for( p = map->mapEntries; p->next != NULL; p = p->next ){;}
00319         p->next = entry;
00320     }
00321     map->numberOfEntries++;
00322     return( entry );
00323 }
00324 
00325 
00326 
00327 char *tpia_map_findTarget( statusMessageReporting *smr, tpia_map *map, const char *evaluation, const char *projectile, const char *targetName ) {
00328 
00329 
00330 
00331     char *path;
00332 
00333     if( map->status != tpia_map_status_Ok ) return( NULL );
00334 
00335     path = _tpia_map_findTarget2( smr, map, evaluation, projectile, targetName );
00336     if( ( path == NULL ) && smr_isOk( smr ) ) {
00337         if( evaluation == NULL ) {
00338             smr_setMessageInfo( smr, &(map->smrUserInterface), __FILE__, __LINE__, 1, "target %s for projectile %s not found", targetName, projectile ); }
00339         else {
00340             smr_setMessageInfo( smr, &(map->smrUserInterface), __FILE__, __LINE__, 1, "target %s for projectile %s and evaluation %s not found", targetName, projectile, evaluation );
00341         }
00342     }
00343     return( path );
00344 }
00345 
00346 
00347 
00348 static char *_tpia_map_findTarget2( statusMessageReporting *smr, tpia_map *map, const char *evaluation, const char *projectile, const char *targetName ) {
00349 
00350     tpia_mapEntry *entry;
00351     char *path = NULL;
00352     int n, status;
00353 
00354     for( entry = map->mapEntries; entry != NULL; entry = entry->next ) {
00355         switch( entry->type ) {
00356         case tpia_mapEntry_type_target :
00357             if( !strcmp( projectile, entry->projectile ) && ( !strcmp( targetName, entry->targetName ) ) ) {
00358                 if( evaluation == NULL ) {
00359                     status = 1; }
00360                 else {
00361                     status = !strcmp( evaluation,  entry->evaluation );
00362                 }
00363                 if( status ) {
00364                     n = strlen( map->path ) + 1 + strlen( entry->path ) + 1;
00365                     
00366                     if( ( path = (char*) xData_malloc2( smr, n, 0, "path" ) ) == NULL ) return( NULL );
00367                     strcpy( path, map->path );
00368                     strcat( path, "/" );
00369                     if( entry->path[0] == '/' ) {
00370                         strcpy( path, entry->path ); }
00371                     else {
00372                         strcat( path, entry->path );
00373                     }
00374                     return( path );
00375                 }
00376             }
00377             break;
00378         case tpia_mapEntry_type_path :
00379             if( !strcmp( projectile, entry->projectile ) ) {
00380                 if( ( path = _tpia_map_findTarget2( smr, entry->map, evaluation, projectile, targetName ) ) != NULL ) return( path );
00381             }
00382             break;
00383         default :
00384             smr_setMessageInfo( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_UnknownType, "unknown type = %d", entry->type );
00385             return( NULL );
00386         }
00387     }
00388     return( NULL );
00389 }
00390 
00391 
00392 
00393 tpia_map *tpia_map_findAllOfTarget( statusMessageReporting *smr, tpia_map *map, const char *projectile, const char *targetName ) {
00394 
00395 
00396 
00397     int status;
00398     tpia_map *mapAllOfTarget;
00399     
00400     if( map->status != tpia_map_status_Ok ) return( NULL );
00401     if( ( mapAllOfTarget = tpia_map_create( smr ) ) == NULL ) return( NULL );
00402     status = _tpia_map_findAllOfTarget2( smr, mapAllOfTarget, map, projectile, targetName );
00403     
00404     if( ( status != 0 ) ) mapAllOfTarget = (tpia_map*) tpia_map_free( smr, mapAllOfTarget );
00405     return( mapAllOfTarget );
00406 }
00407 
00408 
00409 
00410 static int _tpia_map_findAllOfTarget2( statusMessageReporting *smr, tpia_map *mapAllOfTarget, tpia_map *map, const char *projectile, const char *targetName ) {
00411 
00412     tpia_mapEntry *entry;
00413 
00414     for( entry = map->mapEntries; entry != NULL; entry = entry->next ) {
00415         switch( entry->type ) {
00416         case tpia_mapEntry_type_target :
00417             if( !strcmp( projectile, entry->projectile ) && ( !strcmp( targetName, entry->targetName ) ) ) {
00418                 if( _tpia_map_addEntry( smr, mapAllOfTarget, entry->type, entry->schema, entry->path, entry->evaluation, entry->projectile, 
00419                     entry->targetName ) == NULL ) return( 1 );
00420             }
00421             break;
00422         case tpia_mapEntry_type_path :
00423             if( !strcmp( projectile, entry->projectile ) ) {
00424                 if( _tpia_map_findAllOfTarget2( smr, mapAllOfTarget, entry->map, projectile, targetName ) != 0 ) return( 1 );
00425             }
00426             break;
00427         default :
00428             smr_setMessageInfo( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_UnknownType, "unknown type = %d", entry->type );
00429             return( 1 );
00430         }
00431     }
00432     return( 0 );
00433 }
00434 
00435 
00436 
00437 char *tpia_map_getFullPath( statusMessageReporting *smr, tpia_map *map, const char *endPath ) {
00438 
00439     char *path;
00440 
00441     if( endPath[0] == '/' ) {
00442         
00443         if( ( path = (char*) xData_malloc2( smr, strlen( endPath ) + 1, 0, "path" ) ) == NULL ) return( NULL );
00444         path[0] = 0; }
00445     else {
00446         
00447         if( ( path = (char*) xData_malloc2( smr, strlen( map->path ) + strlen( endPath ) + 2, 0, "path" ) ) == NULL ) return( NULL );
00448         strcpy( path, map->path );
00449         strcat( path, "/" );
00450     }
00451     strcat( path, endPath );
00452     return( path );
00453 }
00454 
00455 
00456 
00457 int tpia_map_walkTree( statusMessageReporting *smr, tpia_map *map, int (*handler)( tpia_mapEntry *entry, int level, void *userData), void *userData ) {
00458 
00459     return( _tpia_map_walkTree2( smr, map, 0, handler, userData ) );
00460 }
00461 
00462 
00463 
00464 static int _tpia_map_walkTree2( statusMessageReporting *smr, tpia_map *map, int level, int (*handler)( tpia_mapEntry *entry, int level, void *userData), 
00465     void *userData ) {
00466     
00467     tpia_mapEntry *entry;
00468 
00469     for( entry = map->mapEntries; entry != NULL; entry = entry->next ) {
00470         if( handler( entry, level, userData ) != 0 ) return( 1 );
00471         if( entry->type == tpia_mapEntry_type_path ) if( _tpia_map_walkTree2( smr, entry->map, level + 1, handler, userData ) != 0 ) return( 1 );
00472     }
00473     return( 0 );
00474 }
00475 
00476 
00477 
00478 char *tpia_map_toXMLString( statusMessageReporting *smr, tpia_map *map ) {
00479 
00480     tpia_mapEntry *entry;
00481     char *s, *p;
00482     char targetFormat[] = "<target schema=\"%s\" evaluation=\"%s\" projectile=\"%s\" target=\"%s\" path=\"%s\"/>\n";
00483     char pathFormat[] = "<path projectile=\"%s\" path=\"%s\"/>\n";
00484     char start[] = "<map>\n";
00485     char end[] = "</map>";
00486     int n = 0, nStart = strlen( start ), nEnd = strlen( end );
00487     int nTarget = strlen( targetFormat ) - 10, nPath = strlen( pathFormat ) - 4;
00488 
00489     if( map->status != tpia_map_status_Ok ) return( NULL );
00490 
00491     n = nStart + nEnd + 1;
00492     for( entry = map->mapEntries; entry != NULL; entry = entry->next ) {
00493         switch( entry->type ) {
00494         case tpia_mapEntry_type_target :
00495             n += strlen( entry->schema ) + strlen( entry->path ) + strlen( entry->evaluation ) + strlen( entry->projectile ) + strlen( entry->targetName ) + nTarget;
00496             break;
00497         case tpia_mapEntry_type_path :
00498             n += strlen( entry->path ) + strlen( entry->projectile ) + nPath;
00499             break;
00500         default :
00501             smr_setMessageInfo( smr, &(map->smrUserInterface), __FILE__, __LINE__, tpia_map_status_UnknownType, "unknown type = %d", entry->type );
00502             return( NULL );
00503         }
00504     }
00505 
00506     if( ( s = (char *) xData_malloc2( smr, n, 0, "xml string" ) ) == NULL ) return( NULL );
00507     p = s;
00508     strcpy( p, start );
00509     while( *p ) p++;
00510     for( entry = map->mapEntries; entry != NULL; entry = entry->next ) {
00511         switch( entry->type ) {
00512         case tpia_mapEntry_type_target :
00513             sprintf( p, targetFormat, entry->schema, entry->evaluation, entry->projectile, entry->targetName, entry->path );
00514             break;
00515         case tpia_mapEntry_type_path :
00516             sprintf( p, pathFormat, entry->projectile, entry->path );
00517             break;
00518         }
00519         while( *p ) p++;
00520     }
00521     strcpy( p, end );
00522     return( s );
00523 }
00524 
00525 
00526 
00527 void tpia_map_simpleWrite( FILE *f, tpia_map *map ) { _tpia_map_simpleWrite2( f, map, 0 ); }
00528 
00529 
00530 
00531 static void _tpia_map_simpleWrite2( FILE *f, tpia_map *map, int level ) {
00532 
00533     tpia_mapEntry *entry;
00534     char sLevel[] = "                ";
00535     int n = strlen( sLevel ) / 4;
00536 
00537     if( map->status != tpia_map_status_Ok ) {
00538         fprintf( f, "Bad map status = %d\n", map->status );
00539         return;
00540     }
00541     if( level < n ) sLevel[4 * level] = 0;
00542     fprintf( f, "%smap->path = %s\n", sLevel, map->path );
00543     fprintf( f, "%smap->mapFileName = %s\n", sLevel, map->mapFileName );
00544     for( entry = map->mapEntries; entry != NULL; entry = entry->next ) {
00545         switch( entry->type ) {
00546         case tpia_mapEntry_type_target :
00547             fprintf( f, "%sType = target: schema = %s: evaluation = %s: projectile = %s: target = %s: path = %s\n", sLevel, entry->schema, 
00548                 entry->evaluation, entry->projectile, entry->targetName, entry->path );
00549             break;
00550         case tpia_mapEntry_type_path :
00551             fprintf( f, "%sType =   path: projectile = %s: path = %s\n", sLevel, entry->projectile, entry->path );
00552             _tpia_map_simpleWrite2( f, entry->map, level + 1 );
00553             break;
00554         default :
00555             fprintf( f, "%sUnknown type = %d\n", sLevel, entry->type );
00556         }
00557     }
00558 }
00559 
00560 
00561 
00562 static int _tpia_map_smrUserInterface( void *userData, char **str ) {
00563 
00564     tpia_map_smr *smrUserInterface = (tpia_map_smr *) userData;
00565     char fnl[] = "map file = ";
00566     int size = strlen( fnl ) + strlen( smrUserInterface->map->mapFileName ) + 1;
00567 
00568     if( str != NULL ) {
00569         
00570         if( ( *str = (char*) xData_malloc2( NULL, size, 0, "mapFileName" ) ) == NULL ) return( -1 );
00571         strcpy( *str, fnl );
00572         strcat( *str, smrUserInterface->map->mapFileName );
00573     }
00574     return( size );
00575 }
00576 
00577 #if defined __cplusplus
00578 }
00579 #endif