license changed to LGPL for libnxcl, libnxsnmp, libnxlp, libnxsl, and libnxmap
[public/netxms.git] / src / snmp / libnxsnmp / zfile.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** SNMP support library
4 ** Copyright (C) 2003-2010 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published by
8 ** the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: zfile.cpp
21 **
22 **/
23
24 #include "libnxsnmp.h"
25
26
27 //
28 // Constants
29 //
30
31 #define DATA_BUFFER_SIZE 65536
32
33
34 //
35 // Constructor for ZFile
36 //
37
38 ZFile::ZFile(FILE *pFile, BOOL bCompress, BOOL bWrite)
39 {
40 m_bCompress = bCompress;
41 m_bWrite = bWrite;
42 m_pFile = pFile;
43 if (bCompress)
44 {
45 // Initialize compression stream
46 m_stream.zalloc = Z_NULL;
47 m_stream.zfree = Z_NULL;
48 m_stream.opaque = Z_NULL;
49 m_stream.avail_in = 0;
50 m_stream.next_in = Z_NULL;
51 if (bWrite)
52 m_nLastZLibError = deflateInit(&m_stream, 9);
53 else
54 m_nLastZLibError = inflateInit(&m_stream);
55 m_nBufferSize = 0;
56 m_pDataBuffer = (BYTE *)malloc(DATA_BUFFER_SIZE);
57 m_pCompBuffer = (BYTE *)malloc(DATA_BUFFER_SIZE);
58 }
59 else
60 {
61 m_pDataBuffer = NULL;
62 m_pCompBuffer = NULL;
63 }
64 }
65
66
67 //
68 // Destructor for ZFile
69 //
70
71 ZFile::~ZFile()
72 {
73 safe_free(m_pDataBuffer);
74 safe_free(m_pCompBuffer);
75 }
76
77
78 //
79 // Write block to compressed file
80 //
81
82 int ZFile::zwrite(void *pBuf, int nLen)
83 {
84 int nBytes, nSrcPos, nRet;
85
86 for(nSrcPos = 0, nRet = 0; nSrcPos < nLen; nSrcPos += nBytes)
87 {
88 nBytes = min(nLen - nSrcPos, DATA_BUFFER_SIZE - m_nBufferSize);
89 memcpy(&m_pDataBuffer[m_nBufferSize], (BYTE *)pBuf + nSrcPos, nBytes);
90 m_nBufferSize += nBytes;
91 if (m_nBufferSize == DATA_BUFFER_SIZE)
92 {
93 // Buffer is full, compress and write it to file
94 m_stream.next_in = m_pDataBuffer;
95 m_stream.avail_in = DATA_BUFFER_SIZE;
96 do
97 {
98 m_stream.next_out = m_pCompBuffer;
99 m_stream.avail_out = DATA_BUFFER_SIZE;
100 deflate(&m_stream, Z_NO_FLUSH);
101 if (fwrite(m_pCompBuffer, 1, DATA_BUFFER_SIZE - m_stream.avail_out, m_pFile) != DATA_BUFFER_SIZE - m_stream.avail_out)
102 nRet = -1;
103 } while(m_stream.avail_in > 0);
104 m_nBufferSize = 0;
105 }
106 if (nRet != -1)
107 nRet += nBytes;
108 }
109 return nRet;
110 }
111
112
113 //
114 // Write single character to compressed file
115 //
116
117 int ZFile::zputc(int ch)
118 {
119 BYTE bt;
120
121 bt = (BYTE)ch;
122 return (zwrite(&bt, 1) == 1) ? ch : -1;
123 }
124
125
126 //
127 // Fill data buffer with new data from file if buffer is empty
128 //
129
130 BOOL ZFile::FillDataBuffer(void)
131 {
132 int nBytes, nRet;
133
134 if (m_nBufferSize > 0)
135 return TRUE;
136
137 if (m_stream.avail_in == 0)
138 {
139 // Read more data from disk
140 nBytes = (int)fread(m_pCompBuffer, 1, DATA_BUFFER_SIZE, m_pFile);
141 if (nBytes <= 0)
142 return FALSE; // EOF or error
143
144 m_stream.next_in = m_pCompBuffer;
145 m_stream.avail_in = nBytes;
146 }
147
148 m_stream.next_out = m_pDataBuffer;
149 m_stream.avail_out = DATA_BUFFER_SIZE;
150 nRet = inflate(&m_stream, Z_NO_FLUSH);
151 if ((nRet == Z_OK) || (nRet == Z_STREAM_END))
152 {
153 m_nBufferSize = DATA_BUFFER_SIZE - m_stream.avail_out;
154 m_pBufferPos = m_pDataBuffer;
155 return TRUE;
156 }
157
158 return FALSE;
159 }
160
161
162 //
163 // Read block from compressed file
164 //
165
166 int ZFile::zread(void *pBuf, int nLen)
167 {
168 int nBytes, nDstPos;
169
170 for(nDstPos = 0; nDstPos < nLen; nDstPos += nBytes)
171 {
172 if (!FillDataBuffer())
173 return 0; // EOF or error
174 nBytes = min(nLen - nDstPos, m_nBufferSize);
175 memcpy((BYTE *)pBuf + nDstPos, m_pBufferPos, nBytes);
176 m_pBufferPos += nBytes;
177 m_nBufferSize -= nBytes;
178 }
179 return nLen;
180 }
181
182
183 //
184 // Read one character from compressed file
185 //
186
187 int ZFile::zgetc(void)
188 {
189 BYTE ch;
190
191 return (zread(&ch, 1) == 1) ? ch : -1;
192 }
193
194
195 //
196 // Close compressed file
197 //
198
199 int ZFile::zclose(void)
200 {
201 int nRet;
202
203 if (m_bWrite)
204 {
205 // Flush buffer
206 if (m_nBufferSize > 0)
207 {
208 m_stream.next_in = m_pDataBuffer;
209 m_stream.avail_in = m_nBufferSize;
210 do
211 {
212 m_stream.next_out = m_pCompBuffer;
213 m_stream.avail_out = DATA_BUFFER_SIZE;
214 nRet = deflate(&m_stream, Z_FINISH);
215 fwrite(m_pCompBuffer, 1, DATA_BUFFER_SIZE - m_stream.avail_out, m_pFile);
216 } while(nRet != Z_STREAM_END);
217 }
218
219 deflateEnd(&m_stream);
220 }
221 else
222 {
223 inflateEnd(&m_stream);
224 }
225 return fclose(m_pFile);
226 }