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