/***********************************************************************
* star_catalog.c : Implementation of the star catalog. It is a linked
* list of stars. The links are generated as needed.
***********************************************************************/
/***********************************************************************
* This file is part of SpaceChart.
* Copyright (C) 2000 Miguel Coca <e970095@zipi.fi.upm.es>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
***********************************************************************/
#include <stdlib.h>
#include <libgen.h>
#include "../include/starmap.h"
#include "../include/star.h"
#include "../include/star_catalog.h"
struct star_node
{
star_t *star;
struct star_node *next;
};
struct st_star_catalog
{
struct star_node *star_list;
char *info;
char *filename;
};
/* Local Functions */
static int star_list_add( struct star_node **list, star_t *star );
static void star_list_destroy( struct star_node *list );
/* Public Functions */
star_catalog_t* star_catalog_new( void )
{
star_catalog_t* cat;
if( (cat = ( star_catalog_t* ) malloc( sizeof( star_catalog_t ) )) )
{
cat->star_list = NULL;
cat->info = NULL;
}
return cat;
}
char* star_catalog_info( star_catalog_t *catalog )
{
return catalog->info;
}
char* star_catalog_filename( star_catalog_t *catalog )
{
return catalog->filename;
}
int star_catalog_read( star_catalog_t* catalog, const char *file,
int (*report_progress)(float progress, void* data),
void *data )
{
star_t* star;
FILE* data_file = NULL;
int error = 0;
long pos = 0, size;
char tmp[256]; /* Arbitrary */
int length, old_length;
/* First we read the list of stars. */
if( !( data_file = fopen( file, "rt" ) ) )
/* File not Found */
error = 1;
else
{
/* Find out the size of the file */
fseek( data_file, 0, SEEK_END );
size = ftell( data_file );
fseek( data_file, 0, SEEK_SET );
/* Before reading the stars we read the header. It is supposed
* to contain data the user should know */
old_length = 0;
while( (fgets( tmp, 256, data_file )[0]) &&
tmp[0] != '%' )
{
length = strlen(tmp);
if( !catalog->info )
{
catalog->info = malloc(length+1);
strncpy( catalog->info, tmp, length );
}
else
{
catalog->info = realloc(catalog->info,
length+old_length+1);
strncpy( catalog->info+old_length, tmp,
length );
}
old_length += length;
catalog->info[old_length] = '\0';
}
catalog->filename = basename(file);
while( !error )
{
star = star_new();
if( star_read( star, data_file ) )
{
if(!star_list_add(&(catalog->star_list), star))
{
/* Not enough memory. Clean up and get
* out of here. */
star_list_destroy(catalog->star_list);
error = 3;
break;
}
}
else
{
/* Couldn't read the next star:
* EOF or Corrupt file */
star_destroy(star);
break;
}
pos = ftell( data_file );
if(!report_progress( (float)pos/(float)size, data ))
return 4;
}
/* If we got out of the loop for an EOF, all is well, else.. */
if( !feof( data_file ) )
{
if( ferror( data_file ) )
{
/* Unexpected error. Report and return as file
* Not found. */
error = 1;
perror( file );
star_list_destroy( catalog->star_list );
}
else
{
/* Format error in the file. */
error = 2;
star_list_destroy( catalog->star_list );
}
}
fclose( data_file );
}
return error;
}
star_t* star_catalog_get( star_catalog_t* catalog, star_id_t id )
{
struct star_node *list;
for( list = catalog->star_list; list; list = list->next )
{
if( star_get_id( list->star ) == id )
break;
}
return list->star;
}
void star_catalog_select_objs( star_catalog_t* catalog,
star_t *(*stars[]), link_t *(*links[]),
int (*star_sel)( star_t* star, void* data ),
int (*link_sel)( link_t* link, void* data ),
void *data )
{
star_t **star_list = NULL, **s_backup;
link_t **link_list = NULL, **l_backup;
int list_length = 0, i, j;
struct star_node *ref;
link_t *link;
if( !(star_list = (star_t**) malloc( sizeof(star_t*) )) )
{
*stars = NULL;
return;
}
else
star_list[0] = NULL;
for( ref = catalog->star_list; ref; ref = ref->next )
{
if( star_sel( ref->star, data ) )
{
s_backup = star_list;
if( !(star_list = (star_t**) realloc( star_list,
(2+list_length) *
sizeof(star_t*) )) )
{
free( s_backup );
*stars = NULL;
return;
}
star_list[list_length] = ref->star;
list_length++;
star_list[list_length] = NULL;
}
}
*stars = star_list;
if( !links )
return;
list_length = 0;
if( !(link_list = (link_t**) malloc( sizeof(link_t*) )) )
{
*links = NULL;
return;
}
else
link_list[0] = NULL;
for( i = 0; star_list[i]; i++ )
{
for( j = i+1; star_list[j]; j++ )
{
link = link_new( star_list[i], star_list[j] );
if( link_sel( link, data ) )
{
l_backup = link_list;
if( !(link_list = (link_t**)
realloc( link_list, (2+list_length) *
sizeof(link_t*) )) )
{
free( l_backup );
*links = NULL;
return;
}
link_list[list_length] = link;
list_length++;
link_list[list_length] = NULL;
}
else
{
link_destroy(link);
}
}
}
*links = link_list;
}
void star_catalog_destroy( star_catalog_t* catalog )
{
star_list_destroy( catalog->star_list );
free( catalog );
}
/* Local Functions */
static int star_list_add( struct star_node **list, star_t *star )
{
struct star_node *node;
if( !*list )
{
if( (node = (struct star_node*)
malloc( sizeof(struct star_node) )) )
{
node->star = star;
node->next = NULL;
*list = node;
return 1;
}
else
return 0;
}
else
return star_list_add( &((*list)->next), star );
}
static void star_list_destroy( struct star_node *list )
{
if( list )
{
star_destroy( list->star );
star_list_destroy( list->next );
free( list );
}
}
syntax highlighted by Code2HTML, v. 0.9.1