+/* Martin Asser Hansen (mail@maasha.dk) Copyright (C) 2008 - All right reserved */
+
#include "common.h"
+#include "mem.h"
#include "filesys.h"
{
/* Martin A. Hansen, November 2005 */
+ /* Unit test done. */
+
/* Given a file name, read-opens the file, */
/* and returns a file pointer. */
FILE *fp;
- char *msg;
if ( ( fp = fopen( file, "r" ) ) == NULL )
{
- sprintf( msg, "Could not read-open file '%s'.", file );
-
- die( msg );
+ fprintf( stderr, "ERROR: Could not read-open file '%s': %s\n", file, strerror( errno ) );
+ abort();
}
return fp;
{
/* Martin A. Hansen, November 2005 */
+ /* Unit test done. */
+
/* Given a file name, write-opens the file, */
/* and returns a file pointer. */
FILE *fp;
- char *msg;
if ( ( fp = fopen( file, "w" ) ) == NULL )
{
- sprintf( msg, "Could not write-open file '%s'.", file );
-
- die( msg );
+ fprintf( stderr, "ERROR: Could not write-open file '%s': %s\n", file, strerror( errno ) );
+ abort();
}
return fp;
{
/* Martin A. Hansen, November 2005 */
+ /* Unit test done. */
+
/* Given a file name, append-opens the file, */
/* and returns a file pointer. */
FILE *fp;
- char *msg;
if ( ( fp = fopen( file, "a" ) ) == NULL )
{
- sprintf( msg, "Could not append-open file '%s'.", file );
-
- die( msg );
+ fprintf( stderr, "ERROR: Could not append-open file '%s': %s\n", file, strerror( errno ) );
+ abort();
}
return fp;
{
/* Martin A. Hansen, May 2008 */
+ /* Unit test done. */
+
/* Closes a stream or file associated with a given file pointer. */
- if ( ( fclose( fp ) ) != 0 ) {
- die( "Could not close stream." );
+ if ( ( fclose( fp ) ) != 0 )
+ {
+ fprintf( stderr, "ERROR: Could not close stream: %s\n", strerror( errno ) );
+ abort();
}
}
-char *file_read( FILE *fp, size_t len )
+size_t file_read( FILE *fp, char **string_ppt, size_t len )
{
/* Martin A. Hansen, June 2008 */
/* Read in len number of bytes from the current position of a */
/* file pointer into a string that is allocated and null terminated. */
+ /* The number of read chars is returned. */
+
+ char *string = *string_ppt;
+ size_t num = 0;
- char *string;
+ assert( len > 0 );
string = mem_get( len + 1 );
- fread( string, len, 1, fp );
+ num = fread( string, 1, len, fp );
- if ( ferror( fp ) != 0 ) {
- die( "fread failed." );
+ if ( ferror( fp ) != 0 )
+ {
+ fprintf( stderr, "ERROR: file_read failed\n" );
+ abort();
}
- string[ len + 1 ] = '\0';
+ string[ num ] = '\0';
+
+ *string_ppt = string;
- return string;
+ return num;
}
{
/* Martin A. Hansen, June 2008 */
- /* Delete a file. */
+ /* Unit test done. */
- char *msg;
+ /* Delete a file. */
if ( unlink( file ) == -1 )
{
- sprintf( msg, "Could not delete file '%s'.", file );
-
- die( msg );
+ fprintf( stderr, "ERROR: Could not unlink file '%s': %s\n", file, strerror( errno ) );
+ abort();
}
}
{
/* Martin A. Hansen, June 2008 */
- /* Rename a file. */
+ /* Unit test done. */
- char *msg;
+ /* Rename a file. */
- if ( rename( old_name, new_name ) == -1 )
+ if ( rename( old_name, new_name ) != 0 )
{
- sprintf( msg, "Could not rename file '%s' -> '%s'.", old_name, new_name );
-
- die( msg );
+ fprintf( stderr, "ERROR: Could not rename file '%s' -> '%s': %s\n", old_name, new_name, strerror( errno ) );
+
+ abort();
}
}
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FILE BUFFER <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
-struct file_buffer *read_open_buffer( char *file )
+size_t buffer_new( char *file, file_buffer **buffer_ppt, size_t size )
{
/* Martin A. Hansen, June 2008 */
/* Opens a file for reading and loads a new buffer.*/
+ /* The number of read chars is returned. */
- struct file_buffer *buffer;
- FILE *fp;
- char *str;
- bool eof;
+ file_buffer *buffer = *buffer_ppt;
+ FILE *fp = NULL;
+ size_t num = 0;
- MEM_GET( buffer );
+ buffer = mem_get( sizeof( file_buffer ) );
- fp = read_open( file );
+ fp = read_open( file );
- str = file_read( fp, FILE_BUFFER_SIZE );
+ buffer->fp = fp;
+ buffer->str = NULL;
+ buffer->token_pos = 0;
+ buffer->token_len = 0;
+ buffer->buffer_pos = 0;
+ buffer->buffer_end = 0;
+ buffer->buffer_size = size;
+ buffer->eof = FALSE;
- feof( fp ) ? ( eof = TRUE ) : ( eof = FALSE );
+ num = buffer_read( &buffer );
- buffer->fp = fp;
- buffer->str = str;
- buffer->pos = 0;
- buffer->use = 0;
- buffer->end = strlen( str );
- buffer->size = FILE_BUFFER_SIZE;
- buffer->eof = eof;
+ *buffer_ppt = buffer;
- return buffer;
+ return num;
}
-char buffer_getc( struct file_buffer *buffer )
+size_t buffer_read( file_buffer **buffer_ppt )
+{
+ /* Martin A. Hansen, June 2008 */
+
+ /* Read in buffer->buffer_size bytes from file and appends to buffer string. */
+
+ file_buffer *buffer = *buffer_ppt;
+ char *str = NULL;
+ size_t str_len = 0;
+ size_t new_end = 0;
+ size_t num = 0;
+
+ num = file_read( buffer->fp, &str, buffer->buffer_size );
+
+ if ( num != 0 )
+ {
+ str_len = num;
+ new_end = buffer->buffer_end + str_len;
+
+ buffer->str = mem_resize( buffer->str, new_end );
+
+ memcpy( &buffer->str[ buffer->buffer_end ], str, str_len );
+
+ buffer->str[ new_end ] = '\0';
+ buffer->buffer_end = new_end;
+
+ mem_free( &str );
+ }
+
+ buffer->eof = feof( buffer->fp ) ? TRUE : FALSE;
+
+ *buffer_ppt = buffer;
+
+ return num;
+}
+
+
+char buffer_getc( file_buffer *buffer )
{
/* Martin A. Hansen, June 2008 */
while ( 1 )
{
- if ( buffer->use == buffer->end )
+ if ( buffer->buffer_pos == buffer->buffer_end )
{
if ( buffer->eof )
{
- return '\0';
+ return EOF;
}
else
{
- buffer->pos = buffer->use;
- buffer_new_size( buffer, buffer->use );
- buffer_resize( buffer );
+ buffer->token_pos = buffer->buffer_pos;
+ buffer_new_size( buffer, buffer->buffer_pos ); // MOVE THIS TO buffer_resize !!!!! ??????
+
+ if ( ( buffer_resize( buffer ) == FALSE ) ) {
+ return EOF;
+ }
}
}
- return buffer->str[ buffer->use++ ];
+ return buffer->str[ buffer->buffer_pos++ ];
}
}
-char *buffer_gets( struct file_buffer *buffer )
+void buffer_ungetc( file_buffer *buffer )
+{
+ /* Martin A. Hansen, August 2008. */
+
+ /* Rewinds the file buffer one char, */
+ /* i.e. put one char back on the buffer. */
+
+ assert( buffer->buffer_pos > 0 );
+
+ buffer->buffer_pos--;
+}
+
+
+char *buffer_gets( file_buffer *buffer )
{
/* Martin A. Hansen, June 2008 */
/* Get the next line that is terminated by \n or EOF from a file buffer. */
- char *pt;
- char *line;
- size_t line_size;
+ char *pt = NULL;
+ char *line = NULL;
+ size_t line_size = 0;
while ( 1 )
{
- if ( ( pt = memchr( &buffer->str[ buffer->use ], '\n', buffer->end - buffer->use ) ) != NULL )
+ if ( ( pt = memchr( &buffer->str[ buffer->buffer_pos ], '\n', buffer->buffer_end + 1 - buffer->buffer_pos ) ) != NULL )
{
- line_size = pt - &buffer->str[ buffer->use ] + 1;
+ line_size = pt - &buffer->str[ buffer->buffer_pos ] + 1;
- line = mem_get( line_size );
+ line = mem_get( line_size + 1 );
- memcpy( line, &buffer->str[ buffer->use ], line_size );
+ memcpy( line, &buffer->str[ buffer->buffer_pos ], line_size );
line[ line_size ] = '\0';
- buffer->use += line_size;
+ buffer->token_len = line_size;
+ buffer->buffer_pos += line_size;
buffer_new_size( buffer, line_size );
}
else
{
- if ( buffer->eof ) {
- return NULL;
- } else {
+ if ( buffer->eof )
+ {
+ if ( buffer->buffer_pos < buffer->buffer_end )
+ {
+ line_size = buffer->buffer_end - buffer->buffer_pos + 1;
+
+ line = mem_get( line_size + 1 );
+
+ memcpy( line, &buffer->str[ buffer->buffer_pos ], line_size );
+
+ line[ line_size ] = '\0';
+
+ buffer->token_len = line_size;
+ buffer->buffer_pos += line_size;
+
+ return line;
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ else
+ {
buffer_resize( buffer );
}
}
}
-void buffer_new_size( struct file_buffer *buffer, int len )
+void buffer_ungets( file_buffer *buffer )
+{
+ /* Martin A. Hansen, August 2008 */
+
+ /* Rewind the file buffer one line, */
+ /* i.e. put one line back on the buffer. */
+
+ assert( buffer->buffer_pos >= buffer->token_len );
+
+ buffer->buffer_pos -= buffer->token_len;
+}
+
+
+void buffer_new_size( file_buffer *buffer, long len )
{
/* Martin A. Hansen, June 2008 */
- /* Increases buffer size until it is larger than len. */
+ /* Doubles buffer size until it is larger than len. */
- while ( buffer->size < len )
+ while ( buffer->buffer_size <= len )
{
- buffer->size <<= 1;
+ buffer->buffer_size <<= 1;
- if ( buffer->size <= 0 ) {
- die( "buffer_new_size failed." );
+ if ( buffer->buffer_size <= 0 )
+ {
+ fprintf( stderr, "ERROR: buffer_new_size failed.\n" );
+ abort();
}
}
}
-void buffer_resize( struct file_buffer *buffer )
+bool buffer_resize( file_buffer *buffer )
{
/* Martin A. Hansen, June 2008 */
/* Resize file buffer. */
- char *str;
- size_t str_len;
- size_t new_end;
-
- str = file_read( buffer->fp, buffer->size );
+ size_t num = 0;
- str_len = strlen( str );
+ if ( buffer->token_pos != 0 ) {
+ buffer_move( buffer, buffer->buffer_pos, buffer->token_pos );
+ }
- feof( buffer->fp ) ? ( buffer->eof = TRUE ) : ( buffer->eof = FALSE );
+ num = buffer_read( &buffer );
- if ( buffer->pos != 0 )
- {
- memmove( buffer->str, &buffer->str[ buffer->pos ], buffer->use - buffer->pos );
-
- buffer->end -= buffer->pos;
- buffer->use = 0;
- buffer->pos = 0;
+ if ( num == 0 ) {
+ return FALSE;
+ } else {
+ return TRUE;
}
+}
- new_end = buffer->end + str_len;
- buffer->str = mem_resize( buffer->str, new_end + 1 );
+size_t buffer_move( file_buffer *buffer, size_t size, size_t num )
+{
+ /* Martin A. Hansen, August 2008 */
+
+ /* Moves file buffer of a given size num positions to the left. */
+ /* The size of the resulting string is returned. */
+
+ size_t len = 0;
- memcpy( &buffer->str[ buffer->end ], str, str_len );
+ assert( size > 0 );
+ assert( num > 0 );
+ assert( num <= size );
- buffer->str[ new_end + 1 ] = '\0';
+ memmove( buffer->str, &buffer->str[ num ], size );
- buffer->end = new_end;
+ len = size - num;
- mem_free( str );
+ buffer->buffer_end = len;
+ buffer->buffer_pos = 0;
+ buffer->token_pos = 0;
+
+ return len;
}
-void buffer_destroy( struct file_buffer *buffer )
+void buffer_destroy( file_buffer **buffer_ppt )
{
/* Martin A. Hansen, June 2008 */
/* Deallocates memory and close stream used by file buffer. */
+ file_buffer *buffer = *buffer_ppt;
+
+ assert( buffer != NULL );
+
close_stream( buffer->fp );
- mem_free( buffer->str );
- mem_free( buffer );
+ mem_free( &buffer->str );
+ mem_free( &buffer );
+
+ buffer = NULL;
}
-void buffer_print( struct file_buffer *buffer )
+void buffer_print( file_buffer *buffer )
{
/* Martin A. Hansen, June 2008 */
/* Debug function that prints the content of a file_buffer. */
- printf( "buffer: {\n" );
- printf( " pos : %lu\n", buffer->pos );
- printf( " use : %lu\n", buffer->use );
- printf( " end : %lu\n", buffer->end );
- printf( " eof : %d\n", buffer->eof );
- printf( " str : ->%s<-\n", buffer->str );
- printf( " str_len: %lu\n", strlen( buffer->str ) );
+ printf( "\nbuffer: {\n" );
+ printf( " token_pos : %zu\n", buffer->token_pos );
+ printf( " token_len : %zu\n", buffer->token_len );
+ printf( " buffer_pos : %zu\n", buffer->buffer_pos );
+ printf( " buffer_end : %zu\n", buffer->buffer_end );
+ printf( " buffer_size : %ld\n", buffer->buffer_size );
+ printf( " str : ->%s<-\n", buffer->str );
+ printf( " eof : %d\n", buffer->eof );
+
+ if ( buffer->str != NULL ) {
+ printf( " _str_len_ : %zu\n", strlen( buffer->str ) );
+ }
+
printf( "}\n" );
}