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.1 $
|
---|
22 | // Revision_date : $Date: 2004/02/16 14:46:00 $
|
---|
23 | // Author(s) : Deepak Bandyopadhyay, Lutz Kettner
|
---|
24 | //
|
---|
25 | // Standard streambuf implementation following Nicolai Josuttis, "The
|
---|
26 | // Standard C++ Library".
|
---|
27 | // ============================================================================
|
---|
28 |
|
---|
29 | #include "gzstream.h"
|
---|
30 | #include <string.h> // for memcpy
|
---|
31 |
|
---|
32 | #ifdef GZSTREAM_NAMESPACE
|
---|
33 | namespace GZSTREAM_NAMESPACE {
|
---|
34 | #endif
|
---|
35 |
|
---|
36 | // ----------------------------------------------------------------------------
|
---|
37 | // Internal classes to implement gzstream. See header file for user classes.
|
---|
38 | // ----------------------------------------------------------------------------
|
---|
39 |
|
---|
40 | // --------------------------------------
|
---|
41 | // class gzstreambuf:
|
---|
42 | // --------------------------------------
|
---|
43 |
|
---|
44 | gzstreambuf*
|
---|
45 | gzstreambuf::open( const char* name, int open_mode) {
|
---|
46 | if ( is_open() )
|
---|
47 | return (gzstreambuf*)0;
|
---|
48 | mode = open_mode;
|
---|
49 | // no append nor read/write mode
|
---|
50 | if ((mode & std::ios::ate) || (mode & std::ios::app)
|
---|
51 | || ((mode & std::ios::in) && (mode & std::ios::out)))
|
---|
52 | return (gzstreambuf*)0;
|
---|
53 | char fmode[10];
|
---|
54 | char* fmodeptr = fmode;
|
---|
55 | if ( mode & std::ios::in)
|
---|
56 | *fmodeptr++ = 'r';
|
---|
57 | else
|
---|
58 | if ( mode & std::ios::out)
|
---|
59 | *fmodeptr++ = 'w';
|
---|
60 | *fmodeptr++ = 'b';
|
---|
61 | *fmodeptr = '\0';
|
---|
62 | file = gzopen( name, fmode);
|
---|
63 | if (file == 0)
|
---|
64 | return (gzstreambuf*)0;
|
---|
65 | opened = 1;
|
---|
66 | return this;
|
---|
67 | }
|
---|
68 |
|
---|
69 | gzstreambuf *
|
---|
70 | gzstreambuf::close() {
|
---|
71 | if ( is_open()) {
|
---|
72 | sync();
|
---|
73 | opened = 0;
|
---|
74 | if ( gzclose( file) == Z_OK)
|
---|
75 | return this;
|
---|
76 | }
|
---|
77 | return (gzstreambuf*)0;
|
---|
78 | }
|
---|
79 |
|
---|
80 | int
|
---|
81 | gzstreambuf::underflow() { // used for input buffer only
|
---|
82 | if ( gptr() && ( gptr() < egptr()))
|
---|
83 | return * reinterpret_cast<unsigned char *>( gptr());
|
---|
84 |
|
---|
85 | if ( ! (mode & std::ios::in) || ! opened)
|
---|
86 | return EOF;
|
---|
87 | // Josuttis' implementation of inbuf
|
---|
88 | int n_putback = gptr() - eback();
|
---|
89 | if ( n_putback > 4)
|
---|
90 | n_putback = 4;
|
---|
91 | memcpy( buffer + (4 - n_putback), gptr() - n_putback, n_putback);
|
---|
92 |
|
---|
93 | int num = gzread( file, buffer+4, gzbufferSize-4);
|
---|
94 | if (num <= 0) // ERROR or EOF
|
---|
95 | return EOF;
|
---|
96 |
|
---|
97 | // reset buffer pointers
|
---|
98 | setg( buffer + (4 - n_putback), // beginning of putback area
|
---|
99 | buffer + 4, // read position
|
---|
100 | buffer + 4 + num); // end of buffer
|
---|
101 |
|
---|
102 | // return next character
|
---|
103 | return * reinterpret_cast<unsigned char *>( gptr());
|
---|
104 | }
|
---|
105 |
|
---|
106 | int
|
---|
107 | gzstreambuf::flush_buffer() {
|
---|
108 | // Separate the writing of the buffer from overflow() and
|
---|
109 | // sync() operation.
|
---|
110 | int w = pptr() - pbase();
|
---|
111 | if ( gzwrite( file, pbase(), w) != w)
|
---|
112 | return EOF;
|
---|
113 | pbump( -w);
|
---|
114 | return w;
|
---|
115 | }
|
---|
116 |
|
---|
117 | int
|
---|
118 | gzstreambuf::overflow( int c) { // used for output buffer only
|
---|
119 | if ( ! ( mode & std::ios::out) || ! opened)
|
---|
120 | return EOF;
|
---|
121 | if (c != EOF) {
|
---|
122 | *pptr() = c;
|
---|
123 | pbump(1);
|
---|
124 | }
|
---|
125 | if ( flush_buffer() == EOF)
|
---|
126 | return EOF;
|
---|
127 | return c;
|
---|
128 | }
|
---|
129 |
|
---|
130 | int
|
---|
131 | gzstreambuf::sync() {
|
---|
132 | // Changed to use flush_buffer() instead of overflow( EOF)
|
---|
133 | // which caused improper behavior with std::endl and flush(),
|
---|
134 | // bug reported by Vincent Ricard.
|
---|
135 | if ( pptr() && pptr() > pbase()) {
|
---|
136 | if ( flush_buffer() == EOF)
|
---|
137 | return -1;
|
---|
138 | }
|
---|
139 | return 0;
|
---|
140 | }
|
---|
141 |
|
---|
142 |
|
---|
143 | // --------------------------------------
|
---|
144 | // class gzstreambase:
|
---|
145 | // --------------------------------------
|
---|
146 |
|
---|
147 | gzstreambase::gzstreambase( const char* name, int mode)
|
---|
148 | {
|
---|
149 | init( &buf);
|
---|
150 | open( name, mode);
|
---|
151 | }
|
---|
152 |
|
---|
153 | gzstreambase::~gzstreambase()
|
---|
154 | {
|
---|
155 | buf.close();
|
---|
156 | }
|
---|
157 |
|
---|
158 | void
|
---|
159 | gzstreambase::open( const char* name, int open_mode) {
|
---|
160 | if ( ! buf.open( name, open_mode))
|
---|
161 | clear( rdstate() | std::ios::badbit);
|
---|
162 | }
|
---|
163 |
|
---|
164 | void gzstreambase::close() {
|
---|
165 | if ( buf.is_open())
|
---|
166 | if ( ! buf.close())
|
---|
167 | clear( rdstate() | std::ios::badbit);
|
---|
168 | }
|
---|
169 |
|
---|
170 | #ifdef GZSTREAM_NAMESPACE
|
---|
171 | } // namespace GZSTREAM_NAMESPACE
|
---|
172 | #endif
|
---|
173 |
|
---|
174 | // ============================================================================
|
---|
175 | // EOF //
|
---|