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

# User Rev Content
1 tim 1570 /*
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 tim 1572 #include <cstring>
37 tim 1570 #include <fstream>
38     #include <sstream>
39    
40 tim 1572 #ifdef IS_MPI
41 tim 1577 #include <mpi.h>
42 tim 1572 #endif
43    
44 tim 1570 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 tim 1572 * if (in.is_open()) {
59 tim 1570 * 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 tim 1572 * @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 tim 1570 */
113 tim 1572 explicit basic_ifstrstream(const char* filename, ios_base::openmode mode = ios_base::in, bool checkFilename = false)
114 tim 1570 : basic_ios<_CharT, _Traits>(), basic_istream<_CharT, _Traits>(0),
115     internalBuf_(NULL), isRead(false) {
116    
117 tim 1572 isRead = internalOpen(filename, mode | ios_base::in, checkFilename);
118 tim 1570 }
119    
120     /**
121 tim 1577 * virtual destructor will close the file(in single mode) and clear the stream buffer
122 tim 1570 */
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 tim 1572 * @checkFilename Flags indicating checking the file name in parallel
136 tim 1570 */
137 tim 1572 void open(const char* filename, ios_base::openmode mode = ios_base::in, bool checkFilename = false){
138 tim 1570
139     if (!isRead ) {
140 tim 1572 isRead = internalOpen(filename, mode, checkFilename);
141 tim 1570 }
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 tim 1582 return static_cast<_Buf*>(internalBuf_);
179 tim 1570 }
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 tim 1572 bool internalOpen(const char* filename, ios_base::openmode mode, bool checkFilename){
192 tim 1570
193     #ifdef IS_MPI
194     int commStatus;
195     long fileSize;
196     char* fbuf;
197     int filenameLen;
198     int diffFilename;
199     int error;
200 tim 1572 int myRank;
201     int masterNode;
202 tim 1570
203 tim 1572 commStatus = MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
204     masterNode = 0;
205    
206     if (myRank == masterNode) {
207 tim 1570
208 tim 1572 if (checkFilename) {
209 tim 1570
210 tim 1572 //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 tim 1570
215 tim 1572 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 tim 1570 return false;
221 tim 1572 }
222 tim 1570
223 tim 1572 ifstream fin(filename, mode);
224 tim 1570 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 tim 1572 if (checkFilename) {
275     commStatus = MPI_Bcast(filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
276 tim 1570
277 tim 1572 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 tim 1570
285 tim 1572 delete masterFilename;
286    
287     commStatus = MPI_Allreduce(diffFilename, error, 1, MPI_INT, MPI_COMM_WORLD);
288 tim 1570
289 tim 1572 if (error > 0)
290     return false;
291     }
292 tim 1570 //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 tim 1581 typedef basic_ifstrstream<char, char_traits<char>, allocator<char> > ifstrstream;
342 tim 1570 }//namespace oopse
343     #endif //IO_IFSTRSTREAM_HPP