license changed to LGPL for libnxcl, libnxsnmp, libnxlp, libnxsl, and libnxmap
[public/netxms.git] / src / snmp / libnxsnmp / zfile.cpp
CommitLineData
5039dede
AK
1/*
2** NetXMS - Network Management System
3** SNMP support library
65d2c384 4** Copyright (C) 2003-2010 Victor Kirhenshtein
5039dede
AK
5**
6** This program is free software; you can redistribute it and/or modify
65d2c384
VK
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
5039dede
AK
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**
65d2c384 16** You should have received a copy of the GNU Lesser General Public License
5039dede
AK
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
38ZFile::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
71ZFile::~ZFile()
72{
73 safe_free(m_pDataBuffer);
74 safe_free(m_pCompBuffer);
75}
76
77
78//
79// Write block to compressed file
80//
81
82int 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
117int 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
130BOOL 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
83fb9214 140 nBytes = (int)fread(m_pCompBuffer, 1, DATA_BUFFER_SIZE, m_pFile);
5039dede
AK
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
166int 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
187int 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
199int 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}