MFEM  v4.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
gzstream.cpp
Go to the documentation of this file.
1 // ============================================================================
2 // gzstream, C++ iostream classes wrapping the zlib compression library.
3 // Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // ============================================================================
19 //
20 // File : gzstream.C
21 // Revision : $Revision: 1.7 $
22 // Revision_date : $Date: 2003/01/08 14:41:27 $
23 // Author(s) : Deepak Bandyopadhyay, Lutz Kettner
24 //
25 // Standard streambuf implementation following Nicolai Josuttis, "The
26 // Standard C++ Library".
27 // ============================================================================
28 
29 #include "../config/config.hpp"
30 #include "gzstream.hpp"
31 #include <fstream>
32 #include <cstring>
33 
34 namespace mfem
35 {
36 
37 #ifdef MFEM_USE_GZSTREAM
38 // ----------------------------------------------------------------------------
39 // Internal classes to implement gzstream. See header file for user classes.
40 // ----------------------------------------------------------------------------
41 
42 // --------------------------------------
43 // class gzstreambuf:
44 // --------------------------------------
45 
46 gzstreambuf* gzstreambuf::open(char const *name, char const *_mode)
47 {
48  if (is_open())
49  {
50  return (gzstreambuf*)0;
51  }
52  file = gzopen(name, _mode);
53  if (file == 0)
54  {
55  return (gzstreambuf*)0;
56  }
57  strncpy(mode, _mode, sizeof(mode)-1);
58  opened = 1;
59  return this;
60 }
61 
63 {
64  if ( is_open())
65  {
66  sync();
67  opened = 0;
68  if ( gzclose( file) == Z_OK)
69  {
70  return this;
71  }
72  }
73  return (gzstreambuf*)0;
74 }
75 
76 int gzstreambuf::underflow() // used for input buffer only
77 {
78  if ( gptr() && ( gptr() < egptr()))
79  {
80  return * reinterpret_cast<unsigned char *>( gptr());
81  }
82 
83  if ( ! strchr(mode,'r') || ! opened)
84  {
85  return EOF;
86  }
87  // Josuttis' implementation of inbuf
88  int n_putback = gptr() - eback();
89  if ( n_putback > 4)
90  {
91  n_putback = 4;
92  }
93  memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
94 
95  int num = gzread( file, buffer+4, bufferSize-4);
96  if (num <= 0) // ERROR or EOF
97  {
98  return EOF;
99  }
100 
101  // reset buffer pointers
102  setg( buffer + (4 - n_putback), // beginning of putback area
103  buffer + 4, // read position
104  buffer + 4 + num); // end of buffer
105 
106  // return next character
107  return * reinterpret_cast<unsigned char *>( gptr());
108 }
109 
110 int gzstreambuf::flush_buffer()
111 {
112  // Separate the writing of the buffer from overflow() and
113  // sync() operation.
114  int w = pptr() - pbase();
115  if ( gzwrite( file, pbase(), w) != w)
116  {
117  return EOF;
118  }
119  pbump( -w);
120  return w;
121 }
122 
123 int gzstreambuf::overflow( int c) // used for output buffer only
124 {
125 
126  if ( ! (strchr(mode,'w') || strchr(mode,'a')) || ! opened)
127  {
128  return EOF;
129  }
130  if (c != EOF)
131  {
132  *pptr() = c;
133  pbump(1);
134  }
135  if ( flush_buffer() == EOF)
136  {
137  return EOF;
138  }
139  return c;
140 }
141 
143 {
144  // Changed to use flush_buffer() instead of overflow( EOF)
145  // which caused improper behavior with std::endl and flush(),
146  // bug reported by Vincent Ricard.
147  if ( pptr() && pptr() > pbase())
148  {
149  if ( flush_buffer() == EOF)
150  {
151  return -1;
152  }
153  }
154  return 0;
155 }
156 
157 // --------------------------------------
158 // class gzstreambase:
159 // --------------------------------------
160 
161 gzstreambase::gzstreambase(char const *name, char const *_mode)
162 {
163  init( &buf);
164  open(name, _mode);
165 }
166 
168 {
169  buf.close();
170 }
171 
172 void gzstreambase::open(char const *name, char const *_mode)
173 {
174  if ( ! buf.open( name, _mode))
175  {
176  clear( rdstate() | std::ios::badbit);
177  }
178 }
179 
181 {
182  if ( buf.is_open())
183  if ( ! buf.close())
184  {
185  clear( rdstate() | std::ios::badbit);
186  }
187 }
188 
189 #endif // MFEM_USE_GZSTREAM
190 
191 
192 // static method
193 bool ifgzstream::maybe_gz(const char *fn)
194 {
195  unsigned short byt = 0x0000;
196  std::ifstream strm(fn,std::ios_base::binary|std::ios_base::in);
197  strm.read(reinterpret_cast<char*>(&byt),2);
198  if (byt==0x1f8b||byt==0x8b1f) { return true; }
199  return false;
200 }
201 
202 ifgzstream::ifgzstream(char const *name, char const *mode)
203  : std::istream(0)
204 {
205  bool err;
206 #ifdef MFEM_USE_GZSTREAM
207  if (maybe_gz(name))
208  {
209  gzstreambuf *gzbuf = new gzstreambuf;
210  err = gzbuf != gzbuf->open(name, mode);
211  buf = gzbuf;
212  }
213  else
214 #endif
215  {
216  std::filebuf *fbuf = new std::filebuf;
217  err = fbuf != fbuf->open(name, std::ios_base::in); // 'mode' is ignored
218  buf = fbuf;
219  }
220  if (!err)
221  {
222  rdbuf(buf);
223  }
224  else
225  {
226  delete buf;
227  buf = NULL;
228  setstate(std::ios::failbit);
229  }
230 }
231 
232 
233 // static class member, ofgzstream::default_mode
234 #ifdef MFEM_USE_GZSTREAM
235 char const *ofgzstream::default_mode = "zwb6";
236 #else
237 char const *ofgzstream::default_mode = "w";
238 #endif
239 
240 ofgzstream::ofgzstream(char const *name, char const *mode)
241  : std::ostream(0)
242 {
243  bool err;
244 #ifdef MFEM_USE_GZSTREAM
245  if (strchr(mode,'z'))
246  {
247  gzstreambuf *gzbuf = new gzstreambuf;
248  err = gzbuf != gzbuf->open(name, mode);
249  buf = gzbuf;
250  }
251  else
252 #endif
253  {
254  std::filebuf *fbuf = new std::filebuf;
255  err = fbuf != fbuf->open(name, std::ios_base::out); // 'mode' is ignored
256  buf = fbuf;
257  }
258  if (!err)
259  {
260  rdbuf(buf);
261  }
262  else
263  {
264  delete buf;
265  buf = NULL;
266  setstate(std::ios::failbit);
267  }
268 }
269 
270 } // namespace mfem
gzstreambuf buf
Definition: gzstream.hpp:594
gzstreambuf * close()
Definition: gzstream.cpp:62
std::streambuf * buf
Definition: gzstream.hpp:700
virtual int overflow(int c=traits_type::eof())
Definition: gzstream.cpp:123
static bool maybe_gz(const char *fn)
Definition: gzstream.cpp:193
static char const * default_mode
Definition: gzstream.hpp:681
ifgzstream(char const *name, char const *mode="rb")
Definition: gzstream.cpp:202
ofgzstream(char const *name, char const *mode=default_mode)
Definition: gzstream.cpp:240
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
Definition: globals.hpp:69
std::streambuf * buf
Definition: gzstream.hpp:648
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:64
virtual int underflow()
Definition: gzstream.cpp:76
virtual int sync()
Definition: gzstream.cpp:142
gzstreambuf * open(char const *name, char const *mode)
Definition: gzstream.cpp:46
void open(char const *name, char const *mode)
Definition: gzstream.cpp:172