1 /*
2  * Modification History
3  *
4  * 2001-February-11		Jason Rohrer
5  * Created.
6  *
7  * 2001-April-12   Jason Rohrer
8  * Changed so that File is not destroyed when this stream is destroyed.
9  *
10  * 2001-April-29   Jason Rohrer
11  * Fixed a bug in the use of fread
12  * (num elements and element size swapped).
13  * Fixed a memory leak in the error message handling.
14  *
15  * 2006-November-23   Jason Rohrer
16  * Fixed a memory leak in error message handling.
17  */
18 
19 #include "minorGems/common.h"
20 
21 
22 
23 #ifndef FILE_INPUT_STREAM_CLASS_INCLUDED
24 #define FILE_INPUT_STREAM_CLASS_INCLUDED
25 
26 #include "minorGems/io/InputStream.h"
27 #include "File.h"
28 
29 #include <stdio.h>
30 
31 /**
32  * File implementation of an InputStream.
33  *
34  * @author Jason Rohrer
35  */
36 class FileInputStream : public InputStream {
37 
38 	public:
39 
40 		/**
41 		 * Constructs an input stream.
42 		 *
43 		 * @param inFile the file to open for reading.
44 		 *   If the file does not exist, all calls to read will fail.
45 		 *   inFile is NOT destroyed when this class is destroyed.
46 		 */
47 		FileInputStream( File *inFile );
48 
49 
50 		/**
51 		 * Destroys this stream and closes the file.
52 		 */
53 		~FileInputStream();
54 
55 
56 		/**
57 		 * Gets the file attached to this stream.
58 		 *
59 		 * @return the file used by this stream.
60 		 *   Should not be modified or destroyed by caller until after
61 		 *   this class is destroyed.
62 		 */
63 		File *getFile();
64 
65 
66 		// implementst InputStream interface
67 		virtual long read( unsigned char *inBuffer, long inNumBytes );
68 
69 	private:
70 		File *mFile;
71 
72 		FILE *mUnderlyingFile;
73 	};
74 
75 
76 
77 
FileInputStream(File * inFile)78 inline FileInputStream::FileInputStream( File *inFile )
79 	: mFile( inFile ) {
80 
81 	int fileNameLength;
82 
83 	char *fileName = mFile->getFullFileName( &fileNameLength );
84 
85 	mUnderlyingFile = fopen( fileName, "rb" );
86 
87 	if( mUnderlyingFile == NULL ) {
88 		// file open failed.
89 
90 		char *stringBuffer = new char[ fileNameLength + 50 ];
91 		sprintf( stringBuffer, "Opening file %s failed.", fileName );
92 		setNewLastError( stringBuffer );
93 		}
94 
95 	delete [] fileName;
96 	}
97 
98 
99 
~FileInputStream()100 inline FileInputStream::~FileInputStream() {
101 	if( mUnderlyingFile != NULL ) {
102 		fclose( mUnderlyingFile );
103 		}
104 	}
105 
106 
107 
getFile()108 inline File *FileInputStream::getFile() {
109 	return mFile;
110 	}
111 
112 
113 
read(unsigned char * inBuffer,long inNumBytes)114 inline long FileInputStream::read(
115 	unsigned char *inBuffer, long inNumBytes ) {
116 
117 	if( mUnderlyingFile != NULL ) {
118 
119 		long numRead = fread( inBuffer, 1, inNumBytes, mUnderlyingFile );
120 
121 		if( numRead < inNumBytes ) {
122 
123 			int fileNameLength;
124 			char *fileName = mFile->getFullFileName( &fileNameLength );
125 
126 			if( feof( mUnderlyingFile ) ) {
127 				// we reached the end of the file.
128 				char *stringBuffer = new char[ fileNameLength + 50 ];
129 				sprintf( stringBuffer, "Reached end of file %s on read.",
130 					fileName );
131 				setNewLastError( stringBuffer );
132 
133 				delete [] fileName;
134 				}
135 			else {
136 				// some other kind of error occured
137 				char *stringBuffer = new char[ fileNameLength + 50 ];
138 				sprintf( stringBuffer, "Reading from file %s failed.",
139 					fileName );
140 				setNewLastError( stringBuffer );
141 
142 				delete [] fileName;
143 
144 				if( numRead == 0 ) {
145 					// a complete read failure
146 					return -1;
147 					}
148 				}
149 			}
150 
151 		return numRead;
152 		}
153 	else {
154 		// file was not opened properly
155 
156 		int fileNameLength;
157 		char *fileName = mFile->getFullFileName( &fileNameLength );
158 		char *stringBuffer = new char[ fileNameLength + 50 ];
159 		sprintf( stringBuffer,
160 			"File %s was not opened properly before reading.",
161 			fileName );
162         delete [] fileName;
163 
164 		setNewLastError( stringBuffer );
165 
166 		return -1;
167 		}
168 	}
169 
170 
171 
172 #endif
173