/* ----------------------------------------------------------------------------
@COPYRIGHT :
Copyright 1993,1994,1995 David MacDonald,
McConnell Brain Imaging Centre,
Montreal Neurological Institute, McGill University.
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies. The author and McGill University
make no representations about the suitability of this
software for any purpose. It is provided "as is" without
express or implied warranty.
---------------------------------------------------------------------------- */
#include <internal_volume_io.h>
#if HAVE_PWD_H
#include <pwd.h>
#endif /* HAVE_PWD_H */
#include <stdlib.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <errno.h>
#ifndef lint
static char rcsid[] = "$Header: /software/source/minc/volume_io/Prog_utils/files.c,v 1.42 2005/05/19 21:19:28 bert Exp $";
#endif
static BOOLEAN has_no_extension( STRING );
static STRING compressed_endings[] = { ".z", ".Z", ".gz" };
#if !HAVE_STRERROR
static char *strerror(int errnum)
{
extern int sys_nerr;
extern char *sys_errlist[];
if( errnum < 0 || errnum >= sys_nerr )
{
return( "" );
}
return( sys_errlist[errnum] );
}
#endif /* !HAVE_STRERROR */
/* ----------------------------- MNI Header -----------------------------------
@NAME : print_system_error
@INPUT :
@OUTPUT :
@RETURNS :
@DESCRIPTION: Prints the most recent system error.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : , 1996 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
static void print_system_error( void )
{
char *error;
error = strerror( errno );
print_error( "\nSystem message: %s\n", error );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : real_is_double
@INPUT :
@OUTPUT :
@RETURNS : TRUE if real is defined to be type double
@DESCRIPTION:
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI BOOLEAN real_is_double( void )
{
static const size_t constant_8 = sizeof(double);
return( sizeof(Real) == constant_8 );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : file_exists
@INPUT : filename
@OUTPUT :
@RETURNS : TRUE or FALSE if file exists
@DESCRIPTION: Checks if the file of the given name exists
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI BOOLEAN file_exists(
STRING filename )
{
BOOLEAN exists;
FILE *file;
STRING expanded;
expanded = expand_filename( filename );
file = fopen( expanded, "r" );
if( file != NULL )
{
(void) fclose( file );
exists = TRUE;
}
else
exists = FALSE;
delete_string( expanded );
return( exists );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : file_directory_exists
@INPUT : filename
@OUTPUT :
@RETURNS : TRUE if directory containing file exists.
@DESCRIPTION: Checks if the directory contained in the path name exists.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : Nov. 2, 1995 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI BOOLEAN file_directory_exists(
STRING filename )
{
BOOLEAN exists;
STRING dir;
dir = extract_directory( filename );
if( string_length( dir ) != 0 )
exists = file_exists( dir );
else
exists = TRUE;
delete_string( dir );
return( exists );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : check_clobber_file
@INPUT : filename
@OUTPUT :
@RETURNS : TRUE if can write file
@DESCRIPTION: Checks if the file exists. If so, asks the user for permission
to overwrite the file.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : Sep. 1, 1995 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI BOOLEAN check_clobber_file(
STRING filename )
{
char ch;
BOOLEAN okay;
STRING expanded;
okay = TRUE;
if( file_exists( filename ) )
{
expanded = expand_filename( filename );
print( "File <%s> exists, do you wish to overwrite (y or n): ",
expanded );
delete_string( expanded );
while( input_character( stdin, &ch ) == OK && ch != 'y' && ch != 'n' &&
ch != 'N' && ch != 'Y' )
{
if( ch == '\n' )
print( " Please type y or n: " );
}
(void) input_newline( stdin );
okay = (ch == 'y' || ch == 'Y');
}
return( okay );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : check_clobber_file_default_suffix
@INPUT : filename
default_suffix
@OUTPUT :
@RETURNS : TRUE if can write file
@DESCRIPTION: Checks if the file exists (adding the default suffix if
necessary). If the file exists, asks the user for permission
to overwrite the file.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : Sep. 1, 1995 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI BOOLEAN check_clobber_file_default_suffix(
STRING filename,
STRING default_suffix )
{
STRING expanded;
BOOLEAN can_write;
expanded = expand_filename( filename );
if( has_no_extension( expanded ) )
{
concat_to_string( &expanded, "." );
concat_to_string( &expanded, default_suffix );
}
can_write = check_clobber_file( expanded );
delete_string( expanded );
return( can_write );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : create_backup_filename
@INPUT : filename
@OUTPUT :
@RETURNS : STRING - a backup filename
@DESCRIPTION: Creates a backup filename that is filename.{date}.bkp
If this already exists (not very likely), then it tries
appending _1, _2, ...
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : Feb. 3, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
static STRING create_backup_filename(
STRING filename )
{
int i, len, count;
STRING expanded, backup_filename, date;
expanded = expand_filename( filename );
date = get_date();
len = string_length( expanded ) + string_length( date ) + 100;
ALLOC( backup_filename, len );
count = 0;
do
{
if( count == 0 )
{
(void) sprintf( backup_filename, "%s.%s.bkp",
expanded, date );
}
else
{
(void) sprintf( backup_filename, "%s.%s.bkp_%d",
expanded, date, count );
}
len = string_length( backup_filename );
while( len > 0 &&
(backup_filename[len-1] == ' ' ||
backup_filename[len-1] == '\t' ||
backup_filename[len-1] == '\n') )
{
--len;
}
backup_filename[len] = (char) 0;
for_less( i, 0, len )
{
if( backup_filename[i] == ' ' || backup_filename[i] == '\t' ||
backup_filename[i] == '\n' )
backup_filename[i] = '_';
/* remove ':' for windows */
if( backup_filename[i] == ':'){
backup_filename[i] = '-';
}
}
++count;
}
while( file_exists( backup_filename ) );
delete_string( expanded );
delete_string( date );
return( backup_filename );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : make_backup_file
@INPUT : filename
@OUTPUT : backup_filename
@RETURNS : OK or ERROR
@DESCRIPTION: If the file exists, creates a backup of the file, and passes
back the name of the backup file, which must be passed to
cleanup_backup_file after the write of filename is performed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : Feb. 3, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status make_backup_file(
STRING filename,
STRING *backup_filename )
{
Status status;
status = OK;
if( file_exists( filename ) )
{
*backup_filename = create_backup_filename( filename );
status = copy_file( filename, *backup_filename );
if( status != OK )
{
print_error( "Error making backup file for: %s\n", filename );
*backup_filename = NULL;
}
}
else
*backup_filename = NULL;
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : cleanup_backup_file
@INPUT : filename
backup_filename
status_of_write
@OUTPUT :
@RETURNS :
@DESCRIPTION: This function is called after writing a file. If a backup file
was made before the write, then it is deleted, if the write was
successful, or copied to the original file, otherwise.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : Feb. 3, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void cleanup_backup_file(
STRING filename,
STRING backup_filename,
Status status_of_write )
{
BOOLEAN can_remove;
if( backup_filename != NULL )
{
can_remove = TRUE;
if( status_of_write != OK )
{
if( copy_file( backup_filename, filename ) != OK )
{
print_error( "File %s was corrupted during a failed write,\n",
filename );
print_error(
"File %s contains the state prior to the write attempt.\n",
backup_filename );
can_remove = FALSE;
}
}
if( can_remove )
remove_file( backup_filename );
}
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : remove_file
@INPUT : filename
@OUTPUT :
@RETURNS :
@DESCRIPTION: Deletes the given file.
@METHOD : Makes a system call to unlink().
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI void remove_file(
STRING filename )
{
STRING expanded;
expanded = expand_filename( filename );
if( unlink( expanded ) != 0 )
{
print_error( "Error removing %s. ", expanded );
print_system_error();
}
delete_string( expanded );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : copy_file
@INPUT : src
dest
@OUTPUT :
@RETURNS : OK or ERROR
@DESCRIPTION: Copies the src file to the dest file.
@METHOD : Makes a UNIX system call, using /bin/cp
@GLOBALS :
@CALLS :
@CREATED : Feb. 3, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status copy_file(
STRING src,
STRING dest )
{
Status status;
STRING src_expanded, dest_expanded, command;
src_expanded = expand_filename( src );
dest_expanded = expand_filename( dest );
command = concat_strings( "/bin/cp ", src_expanded );
concat_to_string( &command, " " );
concat_to_string( &command, dest_expanded );
if( system( command ) != 0 )
{
print_error( "Error copying file %s to %s: ",
src_expanded, dest_expanded );
print_system_error();
status = ERROR;
}
else
status = OK;
delete_string( src_expanded );
delete_string( dest_expanded );
delete_string( command );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : move_file
@INPUT : src
dest
@OUTPUT :
@RETURNS : OK or ERROR
@DESCRIPTION: Move the src file to the dest file.
@METHOD : Makes a UNIX system call, using /bin/mv
@GLOBALS :
@CALLS :
@CREATED : Feb. 3, 1997 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status move_file(
STRING src,
STRING dest )
{
Status status;
STRING src_expanded, dest_expanded, command;
src_expanded = expand_filename( src );
dest_expanded = expand_filename( dest );
command = concat_strings( "/bin/cp -f ", src_expanded );
concat_to_string( &command, " " );
concat_to_string( &command, dest_expanded );
if( system( command ) != 0 )
{
print_error( "Error moving file %s to %s: ",
src_expanded, dest_expanded );
print_system_error();
status = ERROR;
}
else
status = OK;
delete_string( src_expanded );
delete_string( dest_expanded );
delete_string( command );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : get_user_home_directory
@INPUT : user_name
@OUTPUT :
@RETURNS : Pointer to home directory string.
@DESCRIPTION: Returns the home directory of the specified user.
@METHOD : UNIX password file utilities
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
static STRING get_user_home_directory(
STRING user_name )
{
#if HAVE_GETPWNAM
struct passwd *p;
p = getpwnam( user_name );
if( p == NULL )
return( NULL );
else
return( p->pw_dir );
#else
return (".");
#endif /* HAVE_GETPWNAM */
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : expand_filename
@INPUT : filename
@OUTPUT : expanded_filename
@RETURNS :
@DESCRIPTION: Expands certain strings in the filename, if present:
environment variables, e.g. "$DATA_DIR/filename.txt"
~ e.g. "~david/filename.txt"
If a dollar sign or backslash is desired, it must be preceded
by a backslash.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI STRING expand_filename(
STRING filename )
{
int i, new_i, dest, len, env_index;
BOOLEAN tilde_found, prev_was_backslash;
char *expand_value;
int n_alloced, n_env_alloced;
STRING env, expanded;
/* --- copy from filename to expanded_filename, changing environment
variables and home directories */
len = string_length( filename );
prev_was_backslash = FALSE;
i = 0;
dest = 0;
n_alloced = 0;
n_env_alloced = 0;
env = NULL;
expanded = NULL;
while( i < len+1 )
{
/* --- if not escaped by backslash, and is either a '~' at the
beginning or a '$' anywhere, expand it */
if( !prev_was_backslash &&
((i == 0 && filename[i] == '~') || filename[i] == '$') )
{
/* --- pick up the environment variable name or user name, by
searching until the next '/' or a '.' or end of string */
new_i = i;
tilde_found = (filename[new_i] == '~');
++new_i;
env_index = 0;
while( filename[new_i] != '/' &&
filename[new_i] != '.' &&
filename[new_i] != END_OF_STRING )
{
ADD_ELEMENT_TO_ARRAY_WITH_SIZE( env, n_env_alloced, env_index,
filename[new_i],
DEFAULT_CHUNK_SIZE );
++new_i;
}
ADD_ELEMENT_TO_ARRAY_WITH_SIZE( env, n_env_alloced, env_index,
END_OF_STRING, DEFAULT_CHUNK_SIZE );
/* --- if expanding a '~', find the corresponding home directory */
if( tilde_found )
{
if( string_length( env ) == 0 )
expand_value = getenv( "HOME" );
else
expand_value = get_user_home_directory( env );
}
else /* --- get the environment variable value */
expand_value = getenv( env );
/* --- if an expansion is found, copy it, otherwise just copy char*/
if( expand_value != NULL )
{
SET_ARRAY_SIZE( expanded, n_alloced,
n_alloced + string_length(expand_value),
DEFAULT_CHUNK_SIZE );
n_alloced += string_length(expand_value);
(void) strcpy( &expanded[dest], expand_value );
dest += string_length( expand_value );
i = new_i;
}
else
{
SET_ARRAY_SIZE( expanded, n_alloced, n_alloced + 1,
DEFAULT_CHUNK_SIZE );
++n_alloced;
expanded[dest] = filename[i];
++dest;
++i;
}
prev_was_backslash = FALSE;
}
else
{
/* --- if not a backslash or if it is escaped, add character */
if( filename[i] != '\\' || prev_was_backslash )
{
SET_ARRAY_SIZE( expanded, n_alloced, n_alloced + 1,
DEFAULT_CHUNK_SIZE );
++n_alloced;
expanded[dest] = filename[i];
++dest;
prev_was_backslash = FALSE;
}
else
prev_was_backslash = TRUE;
++i;
}
}
if( n_env_alloced > 0 )
delete_string( env );
return( expanded );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : filename_extension_matches
@INPUT : filename
extension
@OUTPUT :
@RETURNS : TRUE if filename extension matches
@DESCRIPTION: Checks if the filename ends in a period, then the given
extension. Note that the filename first undergoes expansion
for home directories and environment variables, and any
ending of ".z", ".Z", or ".gz" is first removed.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI BOOLEAN filename_extension_matches(
STRING filename,
STRING extension )
{
int len, i;
STRING filename_no_z, ending;
BOOLEAN matches;
filename_no_z = expand_filename( filename );
len = string_length( filename_no_z );
for_less( i, 0, SIZEOF_STATIC_ARRAY(compressed_endings) )
{
if( string_ends_in( filename_no_z, compressed_endings[i] ) )
{
filename_no_z[len-string_length(compressed_endings[i])] =
END_OF_STRING;
}
}
ending = concat_strings( ".", extension );
matches = string_ends_in( filename_no_z, ending );
delete_string( filename_no_z );
delete_string( ending );
return( matches );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : remove_directories_from_filename
@INPUT : filename
@OUTPUT : filename_no_directories
@RETURNS :
@DESCRIPTION: Creates a new filename with no directories in it.
E.G. if filename equals "/usr/people/david/test.c"
filename_no_directories will be set to "test.c"
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : 1993 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI STRING remove_directories_from_filename(
STRING filename )
{
STRING expanded, no_directories;
int i;
expanded = expand_filename( filename );
i = string_length( expanded );
while( i >= 0 && expanded[i] != '/' )
--i;
++i;
no_directories = create_string( &expanded[i] );
delete_string( expanded );
return( no_directories );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : file_exists_as_compressed
@INPUT : filename
@OUTPUT : compressed_filename
@RETURNS : TRUE if a compressed file exists
@DESCRIPTION: Checks to see if a compressed version of the file exists. If so,
passes back the name of the compressed file.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : Jun 21, 1995 David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI BOOLEAN file_exists_as_compressed(
STRING filename,
STRING *compressed_filename )
{
int i;
STRING compressed, expanded;
BOOLEAN gzipped;
gzipped = FALSE;
expanded = expand_filename( filename );
/* --- check to see if file.z or file.Z, etc, exists */
for_less( i, 0, SIZEOF_STATIC_ARRAY( compressed_endings ) )
{
compressed = concat_strings( expanded, compressed_endings[i] );
if( file_exists( compressed ) )
{
if( *compressed_filename == filename )
delete_string( filename );
*compressed_filename = compressed;
gzipped = TRUE;
break;
}
delete_string( compressed );
}
delete_string( expanded );
return( gzipped );
}
VIOAPI STRING get_temporary_filename( void )
{
return micreate_tempfile();
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : open_file
@INPUT : filename
: io_type READ_FILE or WRITE_FILE
: file_format ASCII_FORMAT or BINARY_FORMAT
@OUTPUT : file
@RETURNS :
@DESCRIPTION: Opens the given filename for ascii or binary input or output.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status open_file(
STRING filename,
IO_types io_type,
File_formats file_format,
FILE **file )
{
Status status;
int i;
char *tmp_name;
char command[EXTREMELY_LARGE_STRING_SIZE];
STRING access_str, expanded;
BOOLEAN gzipped;
int command_status;
/* --- determine what mode of file access */
switch( io_type )
{
case APPEND_FILE: access_str = create_string( "a" ); break;
case WRITE_FILE: access_str = create_string( "w" ); break;
case READ_FILE:
default: access_str = create_string( "r" ); break;
}
/* --- check if ascii or binary */
if( file_format == BINARY_FORMAT )
concat_to_string( &access_str, "b" );
/* --- expand ~ and $ in filename */
expanded = expand_filename( filename );
gzipped = FALSE;
/* --- if reading the file, check if it is in compressed format */
if( io_type == READ_FILE )
{
/* --- check if the filename ends in one of the compressed suffixes */
for_less( i, 0, SIZEOF_STATIC_ARRAY( compressed_endings ) )
{
if( string_ends_in( expanded, compressed_endings[i] ) )
{
gzipped = TRUE;
break;
}
}
/* --- if the filename does not have a compressed suffix and
the file does not exist, check to see if file.z or file.Z, etc,
exists */
if( !gzipped && !file_exists( expanded ) )
gzipped = file_exists_as_compressed( expanded, &expanded );
}
/* --- if reading from a compressed file, decompress it to a temp file */
status = OK;
if( gzipped )
{
/* --- uncompress to a temporary file */
tmp_name = get_temporary_filename();
(void) sprintf( command, "gunzip -c %s > %s", expanded, tmp_name );
command_status = system( command );
/* Try again, using bzip2 */
if( command_status != 0 )
{
(void) sprintf( command, "bunzip2 -c %s > %s", expanded, tmp_name );
command_status = system( command );
}
/* Check for failure */
if( command_status != 0 )
{
print_error( "Error uncompressing %s into %s using gunzip and bunzip2\n",
expanded, tmp_name );
status = ERROR;
}
else
replace_string( &expanded, create_string(tmp_name) );
free(tmp_name);
}
/* --- finally, open the file */
if( status == OK )
{
*file = fopen( expanded, access_str );
if( *file == NULL ) /* --- print error message if needed */
{
print_error( "Error: could not open file \"%s\". ", expanded );
print_system_error();
status = ERROR;
}
else if( gzipped ) /* if reading a decompressed temp file, */
remove_file( expanded ); /* unlink it, so that when the program */
/* closes the file or dies, the file is */
/* removed */
}
delete_string( access_str );
delete_string( expanded );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : open_file_with_default_suffix
@INPUT : filename
: default_suffix - e.g. ".obj"
: io_type READ_FILE or WRITE_FILE
: file_format ASCII_FORMAT or BINARY_FORMAT
@OUTPUT : file
@RETURNS :
@DESCRIPTION: Opens the given filename for ascii or binary input or output.
: On output, if the file has no suffix, it adds the default suffix.
: On input, if the file does not exist as given, then it tries to
: find the file with the default_suffix.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status open_file_with_default_suffix(
STRING filename,
STRING default_suffix,
IO_types io_type,
File_formats file_format,
FILE **file )
{
Status status;
BOOLEAN suffix_added;
STRING used_filename, expanded;
expanded = expand_filename( filename );
if( io_type == READ_FILE )
{
suffix_added = FALSE;
if( !file_exists(expanded) && has_no_extension( expanded ) )
{
used_filename = concat_strings( expanded, "." );
concat_to_string( &used_filename, default_suffix );
if( file_exists( used_filename ) )
suffix_added = TRUE;
else
delete_string( used_filename );
}
if( !suffix_added )
used_filename = create_string( expanded );
}
else if( has_no_extension( expanded ) )
{
used_filename = concat_strings( expanded, "." );
concat_to_string( &used_filename, default_suffix );
}
else
{
used_filename = create_string( expanded );
}
status = open_file( used_filename, io_type, file_format, file );
delete_string( expanded );
delete_string( used_filename );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : has_no_extension
@INPUT : filename
@OUTPUT :
@RETURNS : TRUE if there is no . extension
@DESCRIPTION: Checks if there is an extension on the file.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
static BOOLEAN has_no_extension(
STRING filename )
{
STRING base_name;
BOOLEAN dot_found;
base_name = remove_directories_from_filename( filename );
dot_found = (find_character( base_name, '.' ) >= 0);
delete_string( base_name );
return( !dot_found );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : set_file_position
@INPUT : file
: byte_position
@OUTPUT :
@RETURNS :
@DESCRIPTION: Sets the file position to the given offset from the start.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status set_file_position(
FILE *file,
long byte_position )
{
Status status;
if( fseek( file, byte_position, 0 ) == 0 )
{
status = OK;
}
else
{
print_error( "Error setting the file position. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : close_file
@INPUT : file
@OUTPUT :
@RETURNS :
@DESCRIPTION: Closes the file.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status close_file(
FILE *file )
{
if( file != NULL )
{
(void) fclose( file );
return( OK );
}
else
return( ERROR );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : extract_directory
@INPUT : filename
@OUTPUT : directory
@RETURNS :
@DESCRIPTION: Extracts the directory from the filename by copying the string
: from the beginning up to the last '/'.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI STRING extract_directory(
STRING filename )
{
int i, slash_index;
STRING expanded, directory;
expanded = expand_filename( filename );
slash_index = string_length(expanded) - 1;
while( slash_index >= 0 && expanded[slash_index] != '/' )
--slash_index;
if( slash_index < 0 )
directory = create_string( "." );
else
{
++slash_index;
directory = alloc_string( slash_index );
for_less( i, 0, slash_index )
directory[i] = expanded[i];
directory[slash_index] = END_OF_STRING;
}
delete_string( expanded );
return( directory );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : get_absolute_filename
@INPUT : filename
: directory
@OUTPUT :
@RETURNS :
@DESCRIPTION: Given a filename and a default directory, determines the correct
: filename by checking if the filename is a relative or absolute
: pathname, and prepending the directory, if the former.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI STRING get_absolute_filename(
STRING filename,
STRING directory )
{
STRING abs_filename, expanded;
/* if the directory is non-null and the filename is not already
absolute (begins with '/'), then prefix the directory to the filename */
expanded = expand_filename( filename );
if( string_length( directory ) > 0 && expanded[0] != '/' )
{
if( directory[string_length(directory)-1] == '/' )
abs_filename = create_string( directory );
else
abs_filename = concat_strings( directory, "/" );
}
else
{
abs_filename = create_string( NULL );
}
concat_to_string( &abs_filename, expanded );
delete_string( expanded );
return( abs_filename );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : flush_file
@INPUT : file
@OUTPUT :
@RETURNS :
@DESCRIPTION: Flushes the output buffer for the given file.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status flush_file(
FILE *file )
{
Status status;
if( fflush( file ) == 0 )
{
status = OK;
}
else
{
print_error( "Error flushing file. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_character
@INPUT : file
@OUTPUT : ch
@RETURNS : Status
@DESCRIPTION: Inputs one character from the file, returning ERROR if eof.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_character(
FILE *file,
char *ch )
{
Status status;
int c;
c = fgetc( file );
if( c == EOF )
{
status = ERROR;
}
else
{
*ch = (char) c;
status = OK;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : unget_character
@INPUT : file
@OUTPUT : ch
@RETURNS : Status
@DESCRIPTION: Ungets one character back to the file, returning status.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status unget_character(
FILE *file,
char ch )
{
Status status;
int c;
c = ungetc( (int) ch, file );
if( c == EOF )
status = ERROR;
else
status = OK;
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_nonwhite_character
@INPUT : file
@OUTPUT : ch
@RETURNS : Status
@DESCRIPTION: Inputs the next nonwhite (tab, space, newline) character.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_nonwhite_character(
FILE *file,
char *ch )
{
Status status;
do
{
status = input_character( file, ch );
}
while( status == OK && (*ch == ' ' || *ch == '\t' || *ch == '\n') );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_character
@INPUT : file
: ch
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs the character to the file, returning the status.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_character(
FILE *file,
char ch )
{
Status status;
if( fputc( (int) ch, file ) != ch )
{
status = ERROR;
}
else
{
status = OK;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : skip_input_until
@INPUT : file
: search_char
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Skips characters in the file, up to and including the first match
: of the search_char;
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status skip_input_until(
FILE *file,
char search_char )
{
Status status;
char ch;
status = OK;
do
{
status = input_character( file, &ch );
}
while( status == OK && ch != search_char );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_string
@INPUT : file
: str
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs the string to the file.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_string(
FILE *file,
STRING str )
{
Status status;
if( fprintf( file, "%s", str ) == string_length(str) )
status = OK;
else
{
print_error( "Error outputting string. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_string
@INPUT : file
: termination_char
@OUTPUT : str
@RETURNS : Status
@DESCRIPTION: Inputs a string from the file. First it skips white space, then
: inputs all characters until the termination_char is found.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_string(
FILE *file,
STRING *str,
char termination_char )
{
char ch;
Status status;
status = input_nonwhite_character( file, &ch );
*str = create_string( NULL );
while( status == OK && ch != termination_char && ch != '\n' )
{
concat_char_to_string( str, ch );
status = input_character( file, &ch );
}
if( termination_char != '\n' && ch == '\n' )
(void) unget_character( file, ch );
if( status != OK )
{
delete_string( *str );
*str = NULL;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_quoted_string
@INPUT : file
@OUTPUT : str
@RETURNS : Status
@DESCRIPTION: Skips to the next nonwhitespace character, checks if it is a
: quotation mark ( ", ', or ` ), then reads characters into the
: string until the : next quotation mark.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_quoted_string(
FILE *file,
STRING *str )
{
char ch, quote;
Status status;
status = input_nonwhite_character( file, "e );
if( status == OK && quote != '"' && quote != '\'' && quote != '`' )
status = ERROR;
if( status == OK )
status = input_character( file, &ch );
*str = create_string( NULL );
while( status == OK && ch != quote )
{
concat_char_to_string( str, ch );
status = input_character( file, &ch );
}
if( status != OK )
{
delete_string( *str );
*str = NULL;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_possibly_quoted_string
@INPUT : file
: str
: str_length - size of string storage
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Skips to the next nonwhitespace character, checks if it is a
: quotation mark, then reads characters into the string until the
: next quotation mark. If it is not a quotation mark, reads to
: the next white space.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_possibly_quoted_string(
FILE *file,
STRING *str )
{
BOOLEAN quoted;
char ch, quote;
Status status;
status = input_nonwhite_character( file, "e );
if( status == OK )
{
if( quote == '"' || quote == '\'' || quote == '`' )
{
quoted = TRUE;
status = input_character( file, &ch );
}
else
{
quoted = FALSE;
ch = quote;
}
}
*str = create_string( NULL );
while( status == OK &&
(quoted && ch != quote ||
!quoted && ch != ' ' && ch != '\t' && ch != '\n') )
{
concat_char_to_string( str, ch );
status = input_character( file, &ch );
}
if( !quoted )
(void) unget_character( file, ch );
if( status != OK )
{
delete_string( *str );
*str = NULL;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_quoted_string
@INPUT : file
: str
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs the given string, with quotation marks around it.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_quoted_string(
FILE *file,
STRING str )
{
Status status;
if( fprintf( file, " \"%s\"", str ) > 0 )
status = OK;
else
status = ERROR;
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_binary_data
@INPUT : file
: element_size size of each element
: n number of elements
@OUTPUT : data array of elements to input
@RETURNS : Status
@DESCRIPTION: Inputs the data in binary format.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_binary_data(
FILE *file,
void *data,
size_t element_size,
int n )
{
Status status;
int n_done;
status = OK;
n_done = (int) fread( data, element_size, (size_t) n, file );
if( n_done != n )
{
print_error( "Error inputting binary data.\n" );
print_error( " (%d out of %d items of size %ld). ", n_done, n,
element_size );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_binary_data
@INPUT : file
: data array of elements to output
: element_size size of each element
: n number of elements
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs the data in binary format.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_binary_data(
FILE *file,
void *data,
size_t element_size,
int n )
{
Status status;
int n_done;
status = OK;
n_done = (int) fwrite( data, element_size, (size_t) n, file );
if( n_done != n )
{
print_error( "Error outputting binary data.\n" );
print_error( " (%d out of %d items of size %ld). ", n_done, n,
element_size );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_newline
@INPUT : file
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Skips to after the next newline in the file.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_newline(
FILE *file )
{
Status status;
status = skip_input_until( file, '\n' );
if( status != OK )
{
print_error( "Error inputting newline. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_newline
@INPUT : file
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs a newline to the file.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_newline(
FILE *file )
{
Status status;
if( fprintf( file, "\n" ) > 0 )
status = OK;
else
{
print_error( "Error outputting newline. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_line
@INPUT : line - string to input to
: str_length - storage allocated to the string
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs all characters upto the next newline.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_line(
FILE *file,
STRING *line )
{
Status status;
char ch;
*line = create_string( NULL );
status = input_character( file, &ch );
while( status == OK && ch != '\n' )
{
concat_char_to_string( line, ch );
status = input_character( file, &ch );
}
if( status != OK )
{
delete_string( *line );
*line = NULL;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_boolean
@INPUT : file
@OUTPUT : b
@RETURNS : Status
@DESCRIPTION: Inputs a BOOLEAN value from a file, by looking for an 'f' or 't'.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_boolean(
FILE *file,
BOOLEAN *b )
{
Status status;
char ch;
status = input_nonwhite_character( file, &ch );
if( status == OK )
{
if( ch == 'f' || ch == 'F' )
*b = FALSE;
else if( ch == 't' || ch == 'T' )
*b = TRUE;
else
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_boolean
@INPUT : file
: b
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs a T or F to the file.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_boolean(
FILE *file,
BOOLEAN b )
{
Status status;
STRING str;
status = OK;
if( b )
str = "T";
else
str = "F";
if( fprintf( file, " %s", str ) <= 0 )
{
print_error( "Error outputting BOOLEAN. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_short
@INPUT : file
@OUTPUT : s
@RETURNS : Status
@DESCRIPTION: Inputs an ascii short.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_short(
FILE *file,
short *s )
{
Status status;
if( fscanf( file, "%hd", s ) == 1 )
status = OK;
else
status = ERROR;
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_short
@INPUT : file
: s
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs an ascii short.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_short(
FILE *file,
short s )
{
Status status;
if( fprintf( file, " %d", s ) > 0 )
status = OK;
else
{
print_error( "Error outputting short. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_unsigned_short
@INPUT : file
@OUTPUT : s
@RETURNS : Status
@DESCRIPTION: Inputs an ascii unsigned short.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_unsigned_short(
FILE *file,
unsigned short *s )
{
int i;
Status status;
if( fscanf( file, "%d", &i ) == 1 )
{
*s = (unsigned short) i;
status = OK;
}
else
status = ERROR;
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_unsigned_short
@INPUT : file
: s
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs an ascii unsigned short.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_unsigned_short(
FILE *file,
unsigned short s )
{
Status status;
if( fprintf( file, " %d", (int) s ) > 0 )
status = OK;
else
{
print_error( "Error outputting unsigned short. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_int
@INPUT : file
@OUTPUT : i
@RETURNS : Status
@DESCRIPTION: Inputs an ascii integer.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_int(
FILE *file,
int *i )
{
Status status;
if( fscanf( file, "%d", i ) == 1 )
status = OK;
else
status = ERROR;
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_int
@INPUT : file
: i
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs an ascii integer.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_int(
FILE *file,
int i )
{
Status status;
if( fprintf( file, " %d", i ) > 0 )
status = OK;
else
{
print_error( "Error outputting int. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_real
@INPUT : file
@OUTPUT : r
@RETURNS : Status
@DESCRIPTION: Inputs an ascii real value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_real(
FILE *file,
Real *r )
{
Status status;
if( real_is_double() )
{
status = input_double( file, (double *) r );
}
else
{
status = input_float( file, (float *) r );
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_real
@INPUT : file
: i
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs an ascii real value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_real(
FILE *file,
Real r )
{
Status status;
if( real_is_double() )
{
status = output_double( file, (double) r );
}
else
{
status = output_float( file, (float) r );
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_float
@INPUT : file
@OUTPUT : f
@RETURNS : Status
@DESCRIPTION: Inputs an ascii float.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_float(
FILE *file,
float *f )
{
Status status;
if( fscanf( file, "%f", f ) == 1 )
status = OK;
else
{
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_float
@INPUT : file
: f
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs an ascii float value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_float(
FILE *file,
float f )
{
Status status;
if( fprintf( file, " %g", f ) > 0 )
status = OK;
else
{
print_error( "Error outputting float. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : input_double
@INPUT : file
@OUTPUT : d
@RETURNS : Status
@DESCRIPTION: Inputs an ascii double.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status input_double(
FILE *file,
double *d )
{
Status status;
if( fscanf( file, "%lf", d ) == 1 )
status = OK;
else
{
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : output_double
@INPUT : file
: d
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Outputs an ascii double value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status output_double(
FILE *file,
double d )
{
Status status;
if( fprintf( file, " %g", d ) > 0 )
status = OK;
else
{
print_error( "Error outputting double. " );
print_system_error();
status = ERROR;
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_binary_data
@INPUT : file
: io_flag
: data
: element_size
: n
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs binary data, depending on io_flag.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_binary_data(
FILE *file,
IO_types io_flag,
void *data,
size_t element_size,
int n )
{
Status status;
if( io_flag == READ_FILE )
status = input_binary_data( file, data, element_size, n );
else
status = output_binary_data( file, data, element_size, n );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_newline
@INPUT : file
: io_flag
: data
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs an ascii or binary newline char, as appropriate.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_newline(
FILE *file,
IO_types io_flag,
File_formats format )
{
Status status;
status = OK;
if( format == ASCII_FORMAT )
{
if( io_flag == READ_FILE )
status = OK;
else
status = output_newline( file );
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_quoted_string
@INPUT : file
: io_flag
: format
: str
: str_length
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs an ascii or binary quoted string.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_quoted_string(
FILE *file,
IO_types io_flag,
File_formats format,
STRING *str )
{
int length;
Status status;
status = OK;
if( format == ASCII_FORMAT )
{
if( io_flag == READ_FILE )
status = input_quoted_string( file, str );
else
status = output_quoted_string( file, *str );
}
else
{
if( io_flag == WRITE_FILE )
length = string_length( *str );
status = io_int( file, io_flag, format, &length );
if( io_flag == READ_FILE )
*str = alloc_string( length );
if( status == OK )
{
status = io_binary_data( file, io_flag, (void *) (*str),
sizeof((*str)[0]), length );
}
str[length] = END_OF_STRING;
}
if( status != OK )
print_error( "Error in quoted string in file.\n" );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_boolean
@INPUT : file
: io_flag
: format
: b boolean value
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs an ascii or binary boolean value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_boolean(
FILE *file,
IO_types io_flag,
File_formats format,
BOOLEAN *b )
{
Status status;
status = OK;
if( format == ASCII_FORMAT )
{
if( io_flag == READ_FILE )
status = input_boolean( file, b );
else
status = output_boolean( file, *b );
}
else
status = io_binary_data( file, io_flag, (void *) b, sizeof(*b), 1 );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_short
@INPUT : file
: io_flag
: format
: short_int short value
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs an ascii or binary short value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_short(
FILE *file,
IO_types io_flag,
File_formats format,
short *short_int )
{
Status status;
status = OK;
if( format == ASCII_FORMAT )
{
if( io_flag == READ_FILE )
status = input_short( file, short_int );
else
status = output_short( file, *short_int );
}
else
status = io_binary_data( file, io_flag, (void *) short_int,
sizeof(*short_int), 1 );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_unsigned_short
@INPUT : file
: io_flag
: format
: unsigned_short short value
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs an ascii or binary unsigned short value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_unsigned_short(
FILE *file,
IO_types io_flag,
File_formats format,
unsigned short *unsigned_short )
{
Status status;
status = OK;
if( format == ASCII_FORMAT )
{
if( io_flag == READ_FILE )
status = input_unsigned_short( file, unsigned_short );
else
status = output_unsigned_short( file, *unsigned_short );
}
else
status = io_binary_data( file, io_flag, (void *) unsigned_short,
sizeof(*unsigned_short), 1 );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_unsigned_char
@INPUT : file
: io_flag
: format
: c unsigned char value
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs an ascii or binary unsigned char.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_unsigned_char(
FILE *file,
IO_types io_flag,
File_formats format,
unsigned char *c )
{
int i;
Status status;
status = OK;
if( format == ASCII_FORMAT )
{
if( io_flag == READ_FILE )
{
if( fscanf( file, "%d", &i ) == 1 )
*c = (unsigned char) i;
else
{
print_error( "Error inputting unsigned char. " );
print_system_error();
status = ERROR;
}
}
else
{
if( fprintf( file, "%d", (int) *c ) != 1 )
{
print_error( "Error outputting unsigned char. " );
print_system_error();
status = ERROR;
}
}
}
else
status = io_binary_data( file, io_flag, (void *) c, sizeof(*c), 1 );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_int
@INPUT : file
: io_flag
: format
: i integer value
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs an ascii or binary integer value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_int(
FILE *file,
IO_types io_flag,
File_formats format,
int *i )
{
Status status;
status = OK;
if( format == ASCII_FORMAT )
{
if( io_flag == READ_FILE )
status = input_int( file, i );
else
status = output_int( file, *i );
}
else
status = io_binary_data( file, io_flag, (void *) i, sizeof(*i), 1 );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_real
@INPUT : file
: io_flag
: format
: r real value
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs an ascii or binary real value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_real(
FILE *file,
IO_types io_flag,
File_formats format,
Real *r )
{
Status status;
status = OK;
if( format == ASCII_FORMAT )
{
if( io_flag == READ_FILE )
status = input_real( file, r );
else
status = output_real( file, *r );
}
else
status = io_binary_data( file, io_flag, (void *) r, sizeof(*r), 1 );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_float
@INPUT : file
: io_flag
: format
: f float value
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs an ascii or binary double value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_float(
FILE *file,
IO_types io_flag,
File_formats format,
float *f )
{
Status status;
status = OK;
if( format == ASCII_FORMAT )
{
if( io_flag == READ_FILE )
status = input_float( file, f );
else
status = output_float( file, *f );
}
else
status = io_binary_data( file, io_flag, (void *) f, sizeof(*f), 1 );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_double
@INPUT : file
: io_flag
: format
: d double value
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs an ascii or binary double value.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_double(
FILE *file,
IO_types io_flag,
File_formats format,
double *d )
{
Status status;
status = OK;
if( format == ASCII_FORMAT )
{
if( io_flag == READ_FILE )
status = input_double( file, d );
else
status = output_double( file, *d );
}
else
status = io_binary_data( file, io_flag, (void *) d, sizeof(*d), 1 );
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_ints
@INPUT : file
: io_flag
: format
: n number of ints
: ints array of ints
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs a list of ascii or binary integers.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_ints(
FILE *file,
IO_types io_flag,
File_formats format,
int n,
int *ints[] )
{
Status status;
int i;
#define INTS_PER_LINE 8
status = OK;
if( io_flag == READ_FILE )
{
ALLOC( *ints, n );
}
if( format == ASCII_FORMAT )
{
for_less( i, 0, n )
{
status = io_int( file, io_flag, format, &(*ints)[i] );
if( status == OK )
{
if( i == n - 1 || (i+1) % INTS_PER_LINE == 0 )
status = io_newline( file, io_flag, format );
}
if( status == ERROR )
break;
}
}
else
{
status = io_binary_data( file, io_flag, (void *) *ints,
sizeof((*ints)[0]), n );
}
return( status );
}
/* ----------------------------- MNI Header -----------------------------------
@NAME : io_unsigned_chars
@INPUT : file
: io_flag
: format
: n number of unsigned chars
: unsigned_chars array of unsigned chars
@OUTPUT :
@RETURNS : Status
@DESCRIPTION: Inputs or outputs a list of ascii or binary unsigned chars.
@METHOD :
@GLOBALS :
@CALLS :
@CREATED : David MacDonald
@MODIFIED :
---------------------------------------------------------------------------- */
VIOAPI Status io_unsigned_chars(
FILE *file,
IO_types io_flag,
File_formats format,
int n,
unsigned char *unsigned_chars[] )
{
Status status;
int i;
status = OK;
if( io_flag == READ_FILE )
ALLOC( *unsigned_chars, n );
if( format == ASCII_FORMAT )
{
for_less( i, 0, n )
{
status = io_unsigned_char( file, io_flag, format,
&(*unsigned_chars)[i] );
if( status == OK )
{
if( i == n - 1 || (i+1) % INTS_PER_LINE == 0 )
status = io_newline( file, io_flag, format );
}
if( status == ERROR )
break;
}
}
else
{
status = io_binary_data( file, io_flag, (void *) (*unsigned_chars),
sizeof((*unsigned_chars)[0]), n );
}
return( status );
}
syntax highlighted by Code2HTML, v. 0.9.1