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

# 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     #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