Mercurial > hg > minc-tools
view volume_io/Prog_utils/files.c @ 2674:b99d8f1c2402
fixed bug related to writing pixel data to obj file
author | Vladimir S. FONOV <vladimir.fonov@gmail.com> |
---|---|
date | Wed, 18 Apr 2012 19:03:13 -0400 |
parents | 9944c7923d5b |
children |
line wrap: on
line source
/* ---------------------------------------------------------------------------- @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_SYS_TYPES_H #include <sys/types.h> #endif /* HAVE_SYS_TYPES_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> 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 ) < 0 ) { 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 ); }