ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/io/basic_ifstrstream.hpp
Revision: 1570
Committed: Fri Oct 15 07:52:47 2004 UTC (19 years, 8 months ago) by tim
File size: 12174 byte(s)
Log Message:
adding basic_ifstrstream

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 <fstream>
37 #include <sstream>
38
39 namespace oopse {
40 using namespace std;
41 /**
42 * @class basic_ifstrstream basic_ifstrstream.hpp "io/basic_ifstrstream.hpp"
43 * @brief class provides a stream interface to read data from files.
44 * <p>In single mode, it falls back to ifstream. Don't need to read the whole file into memory.
45 * In parallel mode, the master node will read the whole file and brocast it to other slave nodes.
46 * After brocasting, every node will fall back to stringstream.</p>
47 *
48 * @code
49 * const int MAXLEN = 1024;
50 * char buffer[MAXLEN];
51 * ifstrstream in;
52 * in.open("Shapes.frc");
53 * if (in.is_open) {
54 * in.getline(buffer, MAXLEN);
55 * }
56 * in.close();
57 * @endcode
58 */
59 template <class _CharT, class _Traits, class _Alloc>
60 class basic_ifstrstream : public basic_istream<_CharT, _Traits> {
61 public:
62 //traits
63 typedef _CharT char_type;
64 typedef typename _Traits::int_type int_type;
65 typedef typename _Traits::pos_type pos_type;
66 typedef typename _Traits::off_type off_type;
67 typedef _Traits traits_type;
68
69 typedef basic_ios<_CharT, _Traits> _Basic_ios;
70 typedef basic_istream<_CharT, _Traits> _Base;
71
72 #ifdef IS_MPI
73 typedef basic_stringbuf<_CharT, _Traits, _Alloc> _Buf;
74 #else
75 typedef basic_filebuf<_CharT, _Traits> _Buf;
76 #endif
77
78 static const int FileNoExists = -1;
79 static const int FileIOError = -2;
80
81 public:
82
83 /** Constructs an object of class ifstream. */
84 basic_ifstrstream()
85 : basic_ios<_CharT, _Traits>(), basic_istream<_CharT, _Traits>(0),
86 internalBuf_(NULL), isRead(false) {
87
88 #ifdef IS_MPI
89 //in parallel mode, fall back to istringstream
90 basic_stringbuf<_CharT, _Traits, _Alloc>* stringBuffer = new basic_stringbuf<_CharT, _Traits, _Alloc>();
91 internalBuf_ = stringBuffer;
92 #else
93 //in single version, fall back to ifstream
94 basic_filebuf<_CharT, _Traits>* fileBuffer = new basic_filebuf<_CharT, _Traits>();
95 internalBuf_ = fileBuffer;
96 #endif
97
98 this->init(internalBuf_);
99 isRead = false;
100 }
101
102 /**
103 * Explicit constructor
104 * @filename String containing the name of the file to be opened
105 * @mode Flags describing the requested i/o mode for the file, default value is ios_base::in
106 */
107 explicit basic_ifstrstream(const char* filename, ios_base::openmode mode = ios_base::in)
108 : basic_ios<_CharT, _Traits>(), basic_istream<_CharT, _Traits>(0),
109 internalBuf_(NULL), isRead(false) {
110
111 isRead = internalOpen(filename, mode | ios_base::in);
112 }
113
114 /**
115 *
116 */
117 ~basic_ifstrstream(){
118 close();
119 delete internalBuf_;
120 internalBuf_ = NULL;
121 }
122
123 /**
124 * Opens a file and associats a buffer with the specified file to perform the i/o operations
125 * (single mode). Master reads a file and brocasts its content to the other slave nodes. After
126 * brocasting, every nodes fall back to stringstream (parallel mode).
127 * @filename String containing the name of the file to be opened
128 * @mode Flags describing the requested i/o mode for the file
129 */
130 void open(const char* filename, ios_base::openmode mode = ios_base::in){
131
132 if (!isRead ) {
133 isRead = internalOpen();
134 }
135 }
136
137 /**
138 * Tests if the stream is currently associated with a valid buffer.
139 * @return true if a file has successfully been opened (single mode) or the whole file is read
140 * and spreaded among all of the processors (parallel mode), otherwise false is returned
141 */
142 bool is_open ( ) {
143 #ifdef IS_MPI
144 return isRead;
145 #else
146 //single version fall back to ifstream
147 return this->rdbuf()->is_open();
148 #endif
149 }
150
151 /**
152 * In single mode, closes a file. The stream's file buffer is released from its association with
153 * the currently open file. In parallel mode, clean the
154 */
155 void close() {
156 #ifndef IS_MPI
157 //single version fall back to ifstream
158 if (!this->rdbuf()->close())
159 this->setstate(ios_base::failbit);
160 #endif
161
162 isRead = false;
163 }
164
165 /**
166 * Gets the stream buffer object associated with the stream
167 * @return A pointer to the stream buffe object(filebuf in single mode, stringbuf in
168 * parallel mode) associated with the stream.
169 */
170 _Buf* rdbuf() const{
171 return const_cast<_Buf*>(internalBuf_);
172 }
173
174 private:
175
176 /**
177 * Internal function used to open the file
178 * @return true if succesfully opens a file (single mode) or gets the file content (parallel mode)
179 * otherwise return false
180 * @filename String containing the name of the file to be opened
181 * @mode Flags describing the requested i/o mode for the file
182 * @todo use try - catch syntax to make the program more readable
183 */
184 bool internalOpen(const char* filename, ios_base::openmode mode){
185
186 #ifdef IS_MPI
187 int commStatus;
188 long fileSize;
189 char* fbuf;
190 int filenameLen;
191 int diffFilename;
192 int error;
193
194 if (worldRank == masterNode) {
195
196 //check the filename is the same
197 filenameLen = strlen(filename);
198 commStatus = MPI_Bcast(filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
199 commStatus = MPI_Bcast(filename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
200
201 diffFilename = 0;
202 commStatus = MPI_Allreduce(sameFilename, error, 1, MPI_INT, MPI_COMM_WORLD);
203
204 //if file names are different just return false
205 if (error > 0)
206 return false;
207
208 ifstream fin(filename, mod);
209 basic_stringbuf<_CharT, _Traits, _Alloc>* sbuf;
210
211 if (fin.is_open()) {
212
213 fin.in.seekg(0, ios::end);
214 fileSize = fin.tellg();
215
216 // '\0' need one more char
217 fbuf = new char[fileSize+1];
218
219 assert(fbuf != 0);
220
221 fin.read(fbuf, fileSize);
222
223 if (fin.fail())
224 fileSize = FileIOError;
225
226 //brocasting the file size
227 commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
228
229 if (fileSize < 0) {
230 fin.close();
231 delete fbuf;
232
233 return false;
234 }
235
236 // make a c-style string and brocasting it
237 fbuf[fileSize] = '\0';
238 commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
239
240 //it is safe to delete null pointer
241 delete internalBuf_;
242
243 //initilaize istream
244 internalBuf_ = new basic_stringbuf<_CharT, _Traits, _Alloc>(fbuf, mode);
245 assert(internalBuf_);
246 this->init(internalBuf_);
247
248 //close the file and delete the buffer
249 fin.close();
250 delete fbuf;
251 }else{
252 fileSize = FileNoExists;
253 commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
254 return false;
255 }
256
257 } else{
258 //check file name
259 commStatus = MPI_Bcast(filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
260
261 char * masterFilename = new char[filenameLen];
262 commStatus = MPI_Bcast(masterFilename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
263
264 if( strcmp(masterFilename, filename) == 0)
265 diffFilename = 0;
266 else
267 diffFilename = 1;
268
269 delete masterFilename;
270
271 commStatus = MPI_Allreduce(sameFilename, error, 1, MPI_INT, MPI_COMM_WORLD);
272
273 if (error > 0)
274 return false;
275
276 //get file size
277 commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
278
279 if (fileSize >= 0 ) {
280 fbuf = new char[fileSize+1];
281 assert(fbuf);
282
283 //receive file content
284 commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
285
286 //it is safe to delete null pointer
287 delete internalBuf_;
288
289 //initilaize istream
290 internalBuf_ = new basic_stringbuf<_CharT, _Traits, _Alloc>(fbuf, mode);
291 assert(internalBuf_);
292 this->init(internalBuf_);
293
294 delete fbuf;
295
296 } else if (fileSize == FileNoExists ) {
297 return false;
298
299 } else if (fileSize == FileIOError ) {
300 return false;
301 }
302 }
303
304 #else
305 //in single version, fall back to ifstream
306 basic_filebuf<_CharT, _Traits>* fileBuffer = new basic_filebuf<_CharT, _Traits>();
307
308 this->init(fileBuffer);
309 if (!fileBuffer->open(filename, mode))
310 this->setstate(ios_base::failbit);
311
312 //it is safe to delete null pointer
313 delete internalBuf_;
314
315 internalBuf_ = fileBuffer;
316 #endif
317
318 return true;
319 }
320
321 basic_streambuf<_CharT, _Traits>* internalBuf_; /** internal stream buffer */
322 bool isRead; /** file opened flag */
323 };
324
325 typedef basic_istringstream<char, char_traits<char>, allocator<char> > ifstringstream;
326 }//namespace oopse
327 #endif //IO_IFSTRSTREAM_HPP