1 #include "soplex/spxdefines.h"
2 #ifdef SOPLEX_WITH_ZLIB
3
4 // ============================================================================
5 // gzstream, C++ iostream classes wrapping the zlib compression library.
6 // Copyright (C) 2001 Deepak Bandyopadhyay, Lutz Kettner
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 // ============================================================================
22 //
23 // File : gzstream.C
24 // Revision : $Revision: 1.8 $
25 // Revision_date : $Date: 2005/12/07 18:03:25 $
26 // Author(s) : Deepak Bandyopadhyay, Lutz Kettner
27 //
28 // Standard streambuf implementation following Nicolai Josuttis, "The
29 // Standard C++ Library".
30 // ============================================================================
31
32 #include "soplex/gzstream.h"
33 #include <iostream>
34 #include <string.h> // for memcpy
35
36 #ifdef SOPLEX_GZSTREAM_NAMESPACE
37 namespace SOPLEX_GZSTREAM_NAMESPACE
38 {
39 #endif
40
41 // ----------------------------------------------------------------------------
42 // Internal classes to implement gzstream. See header file for user classes.
43 // ----------------------------------------------------------------------------
44
45 // --------------------------------------
46 // class gzstreambuf:
47 // --------------------------------------
48
49 gzstreambuf* gzstreambuf::open(const char* _name, int _open_mode)
50 {
51 if(is_open())
52 return 0;
53
54 mode = static_cast<unsigned int>(_open_mode);
55
56 // no append nor read/write mode
57 if((mode & std::ios::ate) || (mode & std::ios::app)
58 || ((mode & std::ios::in) && (mode & std::ios::out)))
59 return 0;
60
61 char fmode[10];
62 char* fmodeptr = fmode;
63
64 if(mode & std::ios::in)
65 *fmodeptr++ = 'r';
66 else if(mode & std::ios::out)
67 *fmodeptr++ = 'w';
68
69 *fmodeptr++ = 'b';
70 *fmodeptr = '\0';
71 file = gzopen(_name, fmode);
72
73 if(file == 0)
74 return 0;
75
76 opened = 1;
77 return this;
78 }
79
80 gzstreambuf* gzstreambuf::close()
81 {
(1) Event cond_true: |
Condition "this->is_open()", taking true branch. |
82 if(is_open())
83 {
84 sync();
85 opened = 0;
86
(2) Event freed_arg: |
"gzclose" frees parameter "this->file". |
87 if(gzclose(file) == Z_OK)
88 return this;
89 }
90
91 return 0;
92 }
93
94 int gzstreambuf::underflow() // used for input buffer only
95 {
96 if(gptr() && (gptr() < egptr()))
97 return * reinterpret_cast<unsigned char*>(gptr());
98
99 if(!(mode & std::ios::in) || ! opened)
100 return EOF;
101
102 // Josuttis' implementation of inbuf
103 size_t n_putback = (size_t)(gptr() - eback());
104
105 if(n_putback > 4)
106 n_putback = 4;
107
108 memcpy(buffer + (4 - n_putback), gptr() - n_putback, n_putback);
109
110 int num = gzread(file, buffer + 4, bufferSize - 4);
111
112 if(num <= 0) // ERROR or EOF
113 return EOF;
114
115 // reset buffer pointers
116 setg(buffer + (4 - n_putback), // beginning of putback area
117 buffer + 4, // read position
118 buffer + 4 + num); // end of buffer
119
120 // return next character
121 return * reinterpret_cast<unsigned char*>(gptr());
122 }
123
124 int gzstreambuf::flush_buffer()
125 {
126 // Separate the writing of the buffer from overflow() and
127 // sync() operation.
128 int w = static_cast<int>(pptr() - pbase());
129
130 if(gzwrite(file, pbase(), (unsigned int) w) != w)
131 return EOF;
132
133 pbump(-w);
134 return w;
135 }
136
137 int gzstreambuf::overflow(int c) // used for output buffer only
138 {
139 if(!(mode & std::ios::out) || ! opened)
140 return EOF;
141
142 if(c != EOF)
143 {
144 *pptr() = static_cast<char>(c);
145 pbump(1);
146 }
147
148 if(flush_buffer() == EOF)
149 return EOF;
150
151 return c;
152 }
153
154 int gzstreambuf::sync()
155 {
156 // Changed to use flush_buffer() instead of overflow( EOF)
157 // which caused improper behavior with std::endl and flush(),
158 // bug reported by Vincent Ricard.
159 if(pptr() && pptr() > pbase())
160 {
161 if(flush_buffer() == EOF)
162 return -1;
163 }
164
165 return 0;
166 }
167
168 // --------------------------------------
169 // class gzstreambase:
170 // --------------------------------------
171
172 gzstreambase::gzstreambase(const char* name, int mode)
173 {
174 init(&buf);
175 open(name, mode);
176 }
177
178 gzstreambase::~gzstreambase()
179 {
180 buf.close();
181 }
182
183 void gzstreambase::open(const char* _name, int _open_mode)
184 {
185 if(! buf.open(_name, _open_mode))
186 setstate(std::ios::badbit);
187
188 // clear( rdstate() | std::ios::badbit);
189 }
190
191 void gzstreambase::close()
192 {
193 if(buf.is_open())
194 if(! buf.close())
195 setstate(std::ios::badbit);
196
197 // clear( rdstate() | std::ios::badbit);
198 }
199
200 #ifdef SOPLEX_GZSTREAM_NAMESPACE
201 } // namespace SOPLEX_GZSTREAM_NAMESPACE
202 #endif
203
204 // ============================================================================
205 // EOF //
206
207 #endif
208