ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/io/basic_ifstrstream.hpp
Revision: 1582
Committed: Fri Oct 15 20:42:25 2004 UTC (19 years, 8 months ago) by tim
File size: 12944 byte(s)
Log Message:
change const_cast to statc_const

File Contents

# Content
1 /*
2 * Copyright (C) 2000-2004 Object Oriented Parallel Simulation Engine (OOPSE) project
3 *
4 * Contact: oopse@oopse.org
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
10 * All we ask is that proper credit is given for our work, which includes
11 * - but is not limited to - adding the above copyright notice to the beginning
12 * of your source code files, and to any copyright notice that you may distribute
13 * with programs based on this work.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 *
24 */
25
26 /**
27 * @file basic_ifstrstream.hpp
28 * @author Teng Lin
29 * @date 10/14/2004
30 * @version 1.0
31 */
32
33 #ifndef IO_IFSTRSTREAM_HPP
34 #define IO_IFSTRSTREAM_HPP
35
36 #include <cstring>
37 #include <fstream>
38 #include <sstream>
39
40 #ifdef IS_MPI
41 #include <mpi.h>
42 #endif
43
44 namespace oopse {
45 using namespace std;
46 /**
47 * @class basic_ifstrstream basic_ifstrstream.hpp "io/basic_ifstrstream.hpp"
48 * @brief class provides a stream interface to read data from files.
49 * <p>In single mode, it falls back to ifstream. Don't need to read the whole file into memory.
50 * In parallel mode, the master node will read the whole file and brocast it to other slave nodes.
51 * After brocasting, every node will fall back to stringstream.</p>
52 *
53 * @code
54 * const int MAXLEN = 1024;
55 * char buffer[MAXLEN];
56 * ifstrstream in;
57 * in.open("Shapes.frc");
58 * if (in.is_open()) {
59 * in.getline(buffer, MAXLEN);
60 * }
61 * in.close();
62 * @endcode
63 */
64 template <class _CharT, class _Traits, class _Alloc>
65 class basic_ifstrstream : public basic_istream<_CharT, _Traits> {
66 public:
67 //traits
68 typedef _CharT char_type;
69 typedef typename _Traits::int_type int_type;
70 typedef typename _Traits::pos_type pos_type;
71 typedef typename _Traits::off_type off_type;
72 typedef _Traits traits_type;
73
74 typedef basic_ios<_CharT, _Traits> _Basic_ios;
75 typedef basic_istream<_CharT, _Traits> _Base;
76
77 #ifdef IS_MPI
78 typedef basic_stringbuf<_CharT, _Traits, _Alloc> _Buf;
79 #else
80 typedef basic_filebuf<_CharT, _Traits> _Buf;
81 #endif
82
83 static const int FileNoExists = -1;
84 static const int FileIOError = -2;
85
86 public:
87
88 /** Constructs an object of class ifstream. */
89 basic_ifstrstream()
90 : basic_ios<_CharT, _Traits>(), basic_istream<_CharT, _Traits>(0),
91 internalBuf_(NULL), isRead(false) {
92
93 #ifdef IS_MPI
94 //in parallel mode, fall back to istringstream
95 basic_stringbuf<_CharT, _Traits, _Alloc>* stringBuffer = new basic_stringbuf<_CharT, _Traits, _Alloc>();
96 internalBuf_ = stringBuffer;
97 #else
98 //in single version, fall back to ifstream
99 basic_filebuf<_CharT, _Traits>* fileBuffer = new basic_filebuf<_CharT, _Traits>();
100 internalBuf_ = fileBuffer;
101 #endif
102
103 this->init(internalBuf_);
104 isRead = false;
105 }
106
107 /**
108 * Explicit constructor
109 * @filename String containing the name of the file to be opened
110 * @mode Flags describing the requested i/o mode for the file, default value is ios_base::in
111 * @checkFilename Flags indicating checking the file name in parallel
112 */
113 explicit basic_ifstrstream(const char* filename, ios_base::openmode mode = ios_base::in, bool checkFilename = false)
114 : basic_ios<_CharT, _Traits>(), basic_istream<_CharT, _Traits>(0),
115 internalBuf_(NULL), isRead(false) {
116
117 isRead = internalOpen(filename, mode | ios_base::in, checkFilename);
118 }
119
120 /**
121 * virtual destructor will close the file(in single mode) and clear the stream buffer
122 */
123 ~basic_ifstrstream(){
124 close();
125 delete internalBuf_;
126 internalBuf_ = NULL;
127 }
128
129 /**
130 * Opens a file and associats a buffer with the specified file to perform the i/o operations
131 * (single mode). Master reads a file and brocasts its content to the other slave nodes. After
132 * brocasting, every nodes fall back to stringstream (parallel mode).
133 * @filename String containing the name of the file to be opened
134 * @mode Flags describing the requested i/o mode for the file
135 * @checkFilename Flags indicating checking the file name in parallel
136 */
137 void open(const char* filename, ios_base::openmode mode = ios_base::in, bool checkFilename = false){
138
139 if (!isRead ) {
140 isRead = internalOpen(filename, mode, checkFilename);
141 }
142 }
143
144 /**
145 * Tests if the stream is currently associated with a valid buffer.
146 * @return true if a file has successfully been opened (single mode) or the whole file is read
147 * and spreaded among all of the processors (parallel mode), otherwise false is returned
148 */
149 bool is_open ( ) {
150 #ifdef IS_MPI
151 return isRead;
152 #else
153 //single version fall back to ifstream
154 return this->rdbuf()->is_open();
155 #endif
156 }
157
158 /**
159 * In single mode, closes a file. The stream's file buffer is released from its association with
160 * the currently open file. In parallel mode, clean the
161 */
162 void close() {
163 #ifndef IS_MPI
164 //single version fall back to ifstream
165 if (!this->rdbuf()->close())
166 this->setstate(ios_base::failbit);
167 #endif
168
169 isRead = false;
170 }
171
172 /**
173 * Gets the stream buffer object associated with the stream
174 * @return A pointer to the stream buffe object(filebuf in single mode, stringbuf in
175 * parallel mode) associated with the stream.
176 */
177 _Buf* rdbuf() const{
178 return static_cast<_Buf*>(internalBuf_);
179 }
180
181 private:
182
183 /**
184 * Internal function used to open the file
185 * @return true if succesfully opens a file (single mode) or gets the file content (parallel mode)
186 * otherwise return false
187 * @filename String containing the name of the file to be opened
188 * @mode Flags describing the requested i/o mode for the file
189 * @todo use try - catch syntax to make the program more readable
190 */
191 bool internalOpen(const char* filename, ios_base::openmode mode, bool checkFilename){
192
193 #ifdef IS_MPI
194 int commStatus;
195 long fileSize;
196 char* fbuf;
197 int filenameLen;
198 int diffFilename;
199 int error;
200 int myRank;
201 int masterNode;
202
203 commStatus = MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
204 masterNode = 0;
205
206 if (myRank == masterNode) {
207
208 if (checkFilename) {
209
210 //check the filename is the same
211 filenameLen = strlen(filename);
212 commStatus = MPI_Bcast(filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
213 commStatus = MPI_Bcast(filename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
214
215 diffFilename = 0;
216 commStatus = MPI_Allreduce(diffFilename, error, 1, MPI_INT, MPI_COMM_WORLD);
217
218 //if file names are different just return false
219 if (error > 0)
220 return false;
221 }
222
223 ifstream fin(filename, mode);
224 basic_stringbuf<_CharT, _Traits, _Alloc>* sbuf;
225
226 if (fin.is_open()) {
227
228 fin.in.seekg(0, ios::end);
229 fileSize = fin.tellg();
230
231 // '\0' need one more char
232 fbuf = new char[fileSize+1];
233
234 assert(fbuf != 0);
235
236 fin.read(fbuf, fileSize);
237
238 if (fin.fail())
239 fileSize = FileIOError;
240
241 //brocasting the file size
242 commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
243
244 if (fileSize < 0) {
245 fin.close();
246 delete fbuf;
247
248 return false;
249 }
250
251 // make a c-style string and brocasting it
252 fbuf[fileSize] = '\0';
253 commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
254
255 //it is safe to delete null pointer
256 delete internalBuf_;
257
258 //initilaize istream
259 internalBuf_ = new basic_stringbuf<_CharT, _Traits, _Alloc>(fbuf, mode);
260 assert(internalBuf_);
261 this->init(internalBuf_);
262
263 //close the file and delete the buffer
264 fin.close();
265 delete fbuf;
266 }else{
267 fileSize = FileNoExists;
268 commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
269 return false;
270 }
271
272 } else{
273 //check file name
274 if (checkFilename) {
275 commStatus = MPI_Bcast(filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
276
277 char * masterFilename = new char[filenameLen];
278 commStatus = MPI_Bcast(masterFilename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
279
280 if( strcmp(masterFilename, filename) == 0)
281 diffFilename = 0;
282 else
283 diffFilename = 1;
284
285 delete masterFilename;
286
287 commStatus = MPI_Allreduce(diffFilename, error, 1, MPI_INT, MPI_COMM_WORLD);
288
289 if (error > 0)
290 return false;
291 }
292 //get file size
293 commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
294
295 if (fileSize >= 0 ) {
296 fbuf = new char[fileSize+1];
297 assert(fbuf);
298
299 //receive file content
300 commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
301
302 //it is safe to delete null pointer
303 delete internalBuf_;
304
305 //initilaize istream
306 internalBuf_ = new basic_stringbuf<_CharT, _Traits, _Alloc>(fbuf, mode);
307 assert(internalBuf_);
308 this->init(internalBuf_);
309
310 delete fbuf;
311
312 } else if (fileSize == FileNoExists ) {
313 return false;
314
315 } else if (fileSize == FileIOError ) {
316 return false;
317 }
318 }
319
320 #else
321 //in single version, fall back to ifstream
322 basic_filebuf<_CharT, _Traits>* fileBuffer = new basic_filebuf<_CharT, _Traits>();
323
324 this->init(fileBuffer);
325 if (!fileBuffer->open(filename, mode))
326 this->setstate(ios_base::failbit);
327
328 //it is safe to delete null pointer
329 delete internalBuf_;
330
331 internalBuf_ = fileBuffer;
332 #endif
333
334 return true;
335 }
336
337 basic_streambuf<_CharT, _Traits>* internalBuf_; /** internal stream buffer */
338 bool isRead; /** file opened flag */
339 };
340
341 typedef basic_ifstrstream<char, char_traits<char>, allocator<char> > ifstrstream;
342 }//namespace oopse
343 #endif //IO_IFSTRSTREAM_HPP