1 /**
2  * \file sgstream.hxx
3  * zlib input file stream wrapper.
4  */
5 
6 // Written by Bernie Bright, 1998
7 //
8 // Copyright (C) 1998  Bernie Bright - bbright@c031.aone.net.au
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Library General Public
12 // License as published by the Free Software Foundation; either
13 // version 2 of the License, or (at your option) any later version.
14 //
15 // This library 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 GNU
18 // Library General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23 //
24 // $Id$
25 
26 
27 #ifndef _SGSTREAM_HXX
28 #define _SGSTREAM_HXX
29 
30 #ifndef __cplusplus
31 # error This library requires C++
32 #endif
33 
34 #include <simgear/compiler.h>
35 
36 #include <istream>
37 #include <ostream>
38 #include <fstream>
39 
40 #include <string>
41 
42 #include <zlib.h>
43 #include <simgear/io/iostreams/gzfstream.hxx>
44 
45 class SGPath;
46 
47 /**
48  * An envelope class for gzifstream.
49  */
50 class sg_gzifstream : private gzifstream_base, public std::istream
51 {
52 public:
53     /** Default constructor */
54     sg_gzifstream();
55 
56     /**
57      * Constructor that attempts to open a file.
58      * @param name name of file
59      * @param io_mode file open mode(s) "or'd" together
60      * @param use_exact_name if false, try to add or remove a ".gz" extension
61      *                       in case the indicated file can't be opened
62      */
63     sg_gzifstream( const SGPath& name,
64 		   ios_openmode io_mode = ios_in | ios_binary,
65                    bool use_exact_name = false );
66 
67     /**
68      * Constructor that attaches itself to an existing file descriptor.
69      * @param fd file descriptor
70      * @param io_mode file open mode(s) "or'd" together
71      */
72     sg_gzifstream( int fd, ios_openmode io_mode = ios_in|ios_binary );
73 
74     /**
75      * Attempt to open a file.
76      * @param name name of file
77      * @param io_mode file open mode(s) "or'd" together
78      * @param use_exact_name if false, try to add or remove a ".gz" extension
79      *                       in case the indicated file can't be opened
80      */
81     void open( const SGPath& name,
82 	       ios_openmode io_mode = ios_in|ios_binary,
83                bool use_exact_name = false );
84 
85     /**
86      * Attach to an existing file descriptor.
87      * @param fd file descriptor
88      * @param io_mode file open mode(s) "or'd" together
89      */
90     void attach( int fd, ios_openmode io_mode = ios_in|ios_binary );
91 
92     /**
93      * Close the stream.
94      */
close()95     void close() { gzbuf.close(); }
96 
97     /** @return true if the file is successfully opened, false otherwise. */
is_open()98     bool is_open() { return gzbuf.is_open(); }
99 
100     /**
101      * @return the current offset in the file being read or written.
102      * The offset corresponds to compressed data if the file is compressed,
103      * and is influenced by buffering performed in zlib, hence the "approx"
104      * qualifier. It should be suitable for progress indicators and such,
105      * though.
106      */
107     z_off_t approxOffset();
108 
109 private:
110     // Not defined!
111     sg_gzifstream( const sg_gzifstream& );
112     void operator= ( const sg_gzifstream& );
113 };
114 
115 /**
116  * \relates sg_gzifstream
117  * An istream manipulator that skips to end of line.
118  * @param in input stream
119  */
120 std::istream& skipeol( std::istream& in );
121 
122 /**
123  * \relates sg_gzifstream
124  * An istream manipulator that skips over white space.
125  * @param in input stream
126  */
127 std::istream& skipws( std::istream& in );
128 
129 /**
130  * \relates sg_gzifstream
131  * An istream manipulator that skips comments and white space.
132  * Ignores comments that start with '#'.
133  * @param in input stream
134  */
135 std::istream& skipcomment( std::istream& in );
136 
137 /**
138  * An envelope class for gzofstream.
139  */
140 class sg_gzofstream : private gzofstream_base, public std::ostream
141 {
142 public:
143     /** Default constructor */
144     sg_gzofstream();
145 
146     /**
147      * Constructor to open a file for writing.
148      * @param name name of file
149      * @param io_mode file open mode(s) "or'd" together
150      */
151     sg_gzofstream( const SGPath& name,
152            ios_openmode io_mode = ios_out | ios_binary );
153 
154     /**
155      * Constructor that attaches itself to an existing file descriptor.
156      * @param fd file descriptor
157      * @param io_mode file open mode(s) "or'd" together
158      */
159     sg_gzofstream( int fd, ios_openmode io_mode = ios_out|ios_binary );
160 
161     /**
162      * Attempt to open a file for writing.
163      * @param name name of file
164      * @param io_mode file open mode(s) "or'd" together
165      */
166     void open( const SGPath& name,
167            ios_openmode io_mode = ios_out|ios_binary );
168 
169     /**
170      * Attach to an existing file descriptor.
171      * @param fd file descriptor
172      * @param io_mode file open mode(s) "or'd" together
173      */
174     void attach( int fd, ios_openmode io_mode = ios_out|ios_binary );
175 
176     /**
177      * Close the stream.
178      */
close()179     void close() { gzbuf.close(); }
180 
181     /** @return true if the file is successfully opened, false otherwise. */
is_open()182     bool is_open() { return gzbuf.is_open(); }
183 
184 private:
185     // Not defined!
186     sg_gzofstream( const sg_gzofstream& );
187     void operator= ( const sg_gzofstream& );
188 };
189 
190 class sg_ifstream : public std::ifstream
191 {
192 public:
sg_ifstream()193     sg_ifstream() {}
194 
195     sg_ifstream(const SGPath& path, ios_openmode io_mode = ios_in | ios_binary);
196 
197     void open( const SGPath& name,
198 	       ios_openmode io_mode = ios_in|ios_binary );
199 
200     /// read the entire stream into a buffer. Use on files, etc - not recommended on streams
201     /// which never EOF, will bvlock forever.
202     std::string read_all();
203 };
204 
205 class sg_ofstream : public std::ofstream
206 {
207 public:
sg_ofstream()208     sg_ofstream() { }
209     sg_ofstream(const SGPath& path, ios_openmode io_mode = ios_out | ios_binary);
210 
211     void open( const SGPath& name,
212 	       ios_openmode io_mode = ios_out|ios_binary );
213 };
214 
215 #endif /* _SGSTREAM_HXX */
216