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