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