/* Name: stream.c Language: ANSI/ISO C Purpose: An attempt encapsulate an abstract data type (namely a stream) using C. Notes: To import the functions into a .c file: #include "stream.h" which will declare the abstract data type as extern File_t Stream; so the linker will resolve it to the object that is in this file. To call the functions from within that .c file: call the functions by their names in file.h for example to call open_file() you might write Stream.open("caller", "foo.txt", "r"); Author: James Blustein Created: 1 January 1996 Last Modified: 21 April 1996 by James Blustein Added PRE and POST comments for functions Using UWOCSD cpp symbol Changed `const string' to `const char *' References: 1] Programming on Purpose: essays on software design by P. J. Plauger published by Prentice-Hall, 1993 pp. 201-2 (part of Essay 22: Inherit It) 2] C Programming FAQs: frequently asked questions by Steve Summit published by Addison-Wesley, 1996 `Question 2.4: What's the best way of implementing opaque (abstract) data types in C?' (p. 32) and definition of opaque type (p. 367) */ #include #ifdef UWOCSD int fclose(FILE *stream); /* library doesn't declare fclose() lose, lose! */ #endif #include "types.h" #include "proto.h" #include "stream.h" /* Prototypes for local functions */ static FILE * open_file(const char * proc, const char * fname, const char * mode); static bool close_file(const char * proc, const char * fname, FILE * handle); /* Exported (program global) opaque type for using functions defined here */ File_t Stream = { &open_file, &close_file}; /* Module global variable */ static int open_files = 0; /* --- Functions using the opaque datatype --- open() : given a filename it returns a file handle close() : given a file handle it closes the associated stream */ /* ********** * open() * ********** PRE: `fname' holds the name of a file to be opened (e.g. "foo.tmp") with type `mode', e.g. "rb" for reading or "wb" for writing. POST: The file has been opened, a stream has been associated with it and a (non-NULL) pointer to the stream has been returned. OR The operation failed, the user has been notified of the error (by a call to swerr()) and NULL has been returned. */ FILE * open_file(const char * proc, /* name of calling function */ const char * fname, /* filename of file to open */ const char * mode) /* see def'n of `type' in fopen(3) */ { FILE * handle; if ((handle = fopen(fname, mode)) != NULL) { open_files++; } else { swerr(proc, 0, "cannot open file `%s'", fname); } return(handle); } /* open_file() */ /* *********** * close() * *********** PRE: `handle' points to an open stream which is associated with a file named by `fname'. POST: TRUE has been returned and the stream was succesfully closed OR FALSE was returned, an error occurred and was reported (by swerr()). */ bool close_file(const char * proc, /* name of calling function */ const char * fname, /* filename of file to open */ FILE * handle) /* stream to close */ { if (fclose(handle) != EOF) { open_files--; return(TRUE); } else { swerr(proc, 0, "cannot close file `%s'", fname); return(FALSE); } } /* close_file() */ /* end of stream.c */