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 // |
---|