MRPT  1.9.9
zip.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "io-precomp.h" // Precompiled headers
11 
12 #include "zlib.h"
13 
14 // For named pipes:
15 #ifdef _WIN32
16 #define WIN32_LEAN_AND_MEAN
17 #include <windows.h>
18 #endif
19 
20 #include <mrpt/io/zip.h>
21 #include <mrpt/core/exceptions.h>
23 
27 #include <mrpt/system/filesystem.h>
28 #include <chrono>
29 #include <iostream>
30 
31 using namespace mrpt;
32 using namespace mrpt::io;
33 using namespace mrpt::io::zip;
34 
36  void* inData, size_t inDataSize, std::vector<unsigned char>& outData)
37 {
38  int ret = 0;
40 
41  unsigned long resSize;
42 
43  outData.resize(inDataSize + inDataSize / 1000 + 50);
44  resSize = (unsigned long)outData.size();
45  ret = ::compress(
46  &outData[0], &resSize, (unsigned char*)inData,
47  (unsigned long)inDataSize);
48  ASSERT_(ret == Z_OK);
49 
50  outData.resize(resSize);
51 
52  MRPT_END_WITH_CLEAN_UP(printf("[zlib] Error code=%i\n", ret););
53 }
54 
55 /*---------------------------------------------------------------
56  compress
57 ---------------------------------------------------------------*/
59  const std::vector<unsigned char>& inData,
60  std::vector<unsigned char>& outData)
61 {
62  int ret = 0;
64 
65  unsigned long resSize;
66 
67  outData.resize(inData.size() + inData.size() / 1000 + 50);
68  resSize = (unsigned long)outData.size();
69  ret = ::compress(
70  &outData[0], &resSize, &inData[0], (unsigned long)inData.size());
71  ASSERT_(ret == Z_OK);
72 
73  outData.resize(resSize);
74 
75  MRPT_END_WITH_CLEAN_UP(printf("[zlib] Error code=%i\n", ret););
76 }
77 
78 /*---------------------------------------------------------------
79  compress
80 ---------------------------------------------------------------*/
81 void mrpt::io::zip::compress(void* inData, size_t inDataSize, CStream& out)
82 {
83  int ret = 0;
85 
86  unsigned long resSize;
87  std::vector<unsigned char> outData;
88 
89  outData.resize(inDataSize + inDataSize / 1000 + 50);
90  resSize = (unsigned long)outData.size();
91 
92  ret = ::compress(
93  &outData[0], &resSize, (unsigned char*)inData,
94  (unsigned long)inDataSize);
95  ASSERT_(ret == Z_OK);
96 
97  outData.resize(resSize);
98 
99  // Write to stream:
100  out.Write(&outData[0], resSize);
101 
102  MRPT_END_WITH_CLEAN_UP(printf("[zlib] Error code=%i\n", ret););
103 }
104 
105 /*---------------------------------------------------------------
106  compress
107 ---------------------------------------------------------------*/
109  const std::vector<unsigned char>& inData, CStream& out)
110 {
111  int ret = 0;
112  MRPT_START
113 
114  unsigned long resSize;
115  std::vector<unsigned char> outData;
116  outData.resize(inData.size() + inData.size() / 1000 + 50);
117  resSize = (unsigned long)outData.size();
118 
119  ret = ::compress(
120  &outData[0], &resSize, &inData[0], (unsigned long)inData.size());
121 
122  ASSERT_(ret == Z_OK);
123 
124  outData.resize(resSize);
125 
126  // Write to stream:
127  out.Write(&outData[0], resSize);
128 
129  MRPT_END_WITH_CLEAN_UP(printf("[zlib] Error code=%i\n", ret););
130 }
131 
132 /*---------------------------------------------------------------
133  decompress
134 ---------------------------------------------------------------*/
136  void* inData, size_t inDataSize, std::vector<unsigned char>& outData,
137  size_t outDataEstimatedSize)
138 {
139  int ret = 0;
140  MRPT_START
141 
142  outData.resize(outDataEstimatedSize);
143  unsigned long actualOutSize;
144 
145  ret = ::uncompress(
146  &outData[0], &actualOutSize, (unsigned char*)inData,
147  (unsigned long)inDataSize);
148 
149  ASSERT_(ret == Z_OK);
150 
151  outData.resize(actualOutSize);
152 
153  MRPT_END_WITH_CLEAN_UP(printf("[zlib] Error code=%i\n", ret););
154 }
155 
156 /*---------------------------------------------------------------
157  decompress
158 ---------------------------------------------------------------*/
160  void* inData, size_t inDataSize, void* outData, size_t outDataBufferSize,
161  size_t& outDataActualSize)
162 {
163  int ret = 0;
164  MRPT_START
165 
166  unsigned long actualOutSize = (unsigned long)outDataBufferSize;
167 
168  ret = ::uncompress(
169  (unsigned char*)outData, &actualOutSize, (unsigned char*)inData,
170  (unsigned long)inDataSize);
171 
172  ASSERT_(ret == Z_OK);
173 
174  outDataActualSize = actualOutSize;
175 
176  MRPT_END_WITH_CLEAN_UP(printf("[zlib] Error code=%i\n", ret););
177 }
178 
179 /*---------------------------------------------------------------
180  decompress
181 ---------------------------------------------------------------*/
183  CStream& inStream, size_t inDataSize, void* outData,
184  size_t outDataBufferSize, size_t& outDataActualSize)
185 {
186  int ret = 0;
187  MRPT_START
188 
189  unsigned long actualOutSize = (unsigned long)outDataBufferSize;
190  std::vector<unsigned char> inData;
191 
192  inData.resize(inDataSize);
193  inStream.Read(&inData[0], inDataSize);
194 
195  ret = ::uncompress(
196  (unsigned char*)outData, &actualOutSize, &inData[0],
197  (unsigned long)inDataSize);
198 
199  ASSERT_(ret == Z_OK);
200 
201  outDataActualSize = actualOutSize;
202 
203  MRPT_END_WITH_CLEAN_UP(printf("[zlib] Error code=%i\n", ret););
204 }
205 
206 /*---------------------------------------------------------------
207  decompress_gz_file
208 ---------------------------------------------------------------*/
210  const std::string& file_path, std::vector<uint8_t>& buffer)
211 {
212  CFileGZInputStream iss(file_path);
213  if (!iss.fileOpenCorrectly()) return false;
214 
215  buffer.clear();
216 
217  const int bytes2read = 1 << 20;
218  int act_read;
219  size_t total_bytes = 0;
220 
221  buffer.reserve(iss.getTotalBytesCount());
222 
223  do
224  {
225  buffer.resize(1000 + bytes2read + buffer.size());
226  act_read = iss.Read(&buffer[total_bytes], bytes2read);
227  total_bytes += act_read;
228  } while (act_read == bytes2read);
229 
230  buffer.resize(total_bytes);
231  return true;
232 }
233 
235  const std::string& file_path, const std::vector<uint8_t>& buffer,
236  const int compress_level)
237 {
239  oss.open(file_path, compress_level);
240  if (!oss.fileOpenCorrectly()) return false;
241 
242  if (!buffer.empty())
243  {
244  try
245  {
246  oss.Write(&buffer[0], buffer.size());
247  return true;
248  }
249  catch (...)
250  {
251  return false;
252  }
253  }
254  else
255  {
256  return true;
257  }
258 }
259 
261  const std::vector<uint8_t>& in_data, std::vector<uint8_t>& out_gz_data,
262  const int compress_level)
263 {
264  out_gz_data.clear();
265  if (in_data.empty()) return true;
266 
267  const unsigned int nPipeName =
268  std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
269  std::string pipe_file_name;
270 
271 // Create an anonymous pipe for writing the data to:
272 #ifdef _WIN32
273  // Windows:
274  pipe_file_name =
275  format("\\\\.\\pipe\\mrpt_compress_gz_data_block_%u", nPipeName);
276 
277  HANDLE hPipe = CreateNamedPipeA(
278  pipe_file_name.c_str(),
279  PIPE_ACCESS_DUPLEX | 0x00080000 /* FILE_FLAG_FIRST_PIPE_INSTANCE */,
280  PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES, in_data.size() + 1000,
281  in_data.size() + 1000, 0, nullptr);
282  if (hPipe == INVALID_HANDLE_VALUE)
283  THROW_EXCEPTION("Error creating named pipe for gz-file compression");
284 #else
285  // Unix:
286  pipe_file_name = format("/tmp/mrpt_compress_gz_data_block_%u", nPipeName);
287 #endif
288 
289  bool retVal = false;
290  try
291  {
292  // Write as gz
293  {
294  gzFile f = gzopen(
295  pipe_file_name.c_str(), format("wb%i", compress_level).c_str());
296  if (f)
297  {
298  retVal = (int)in_data.size() ==
299  gzwrite(f, &in_data[0], in_data.size());
300  gzclose(f);
301  }
302  else
303  {
304  std::cerr << "[compress_gz_data_block] Error writing to pipe: "
305  << pipe_file_name << std::endl;
306  }
307  }
308  // Read it all:
309  if (retVal)
310  {
311 #ifdef _WIN32
312  // Read (windows)
313  const size_t N = GetFileSize(hPipe, nullptr);
314  if (N)
315  {
316  out_gz_data.resize(N);
317  DWORD nRead;
318  SetFilePointer(hPipe, 0, nullptr, FILE_BEGIN);
319  if (N)
320  {
321  ReadFile(hPipe, &out_gz_data[0], N, &nRead, nullptr);
322  retVal = nRead == N;
323  }
324  }
325  else
326  {
327  retVal = false;
328  }
329 #else
330  // Read (Unix)
331  {
332  CFileInputStream iss;
333  if (iss.open(pipe_file_name))
334  {
335  const size_t M = iss.getTotalBytesCount();
336  out_gz_data.resize(M);
337  if (M) retVal = M == iss.Read(&out_gz_data[0], M);
338  }
339  }
340 #endif
341  }
342  }
343  catch (...)
344  {
345  retVal = false;
346  }
347 
348 // Close the pipe:
349 #ifdef _WIN32
350  CloseHandle(hPipe);
351 #else
352  remove(pipe_file_name.c_str());
353 #endif
354 
355  return retVal;
356 }
357 
359  const std::vector<uint8_t>& in_gz_data, std::vector<uint8_t>& out_data)
360 {
361  out_data.clear();
362  if (in_gz_data.empty()) return true;
363 
364  // JL: I tried to do this with pipes but had no luck... :-(
365  const std::string tmp_file_name = mrpt::system::getTempFileName();
366  if (!mrpt::io::vectorToBinaryFile(in_gz_data, tmp_file_name)) return false;
367  bool retVal = mrpt::io::zip::decompress_gz_file(tmp_file_name, out_data);
368 
369  remove(tmp_file_name.c_str()); // Delete tmp file
370 
371  return retVal;
372 }
Transparently opens a compressed "gz" file and reads uncompressed data from it.
uint64_t getTotalBytesCount() const override
Method for getting the total number of compressed bytes of in the file (the physical size of the comp...
bool fileOpenCorrectly() const
Returns true if the file was open without errors.
size_t Read(void *Buffer, size_t Count) override
Introduces a pure virtual method responsible for reading from the stream.
Saves data to a file and transparently compress the data using the given compression level.
size_t Write(const void *Buffer, size_t Count) override
Introduces a pure virtual method responsible for writing to the stream.
bool open(const std::string &fileName, int compress_level=1)
Open a file for write, choosing the compression level.
bool fileOpenCorrectly() const
Returns true if the file was open without errors.
This CStream derived class allow using a file as a read-only, binary stream.
size_t Read(void *Buffer, size_t Count) override
Introduces a pure virtual method responsible for reading from the stream.
uint64_t getTotalBytesCount() const override
Returns the total amount of bytes in the stream.
bool open(const std::string &fileName)
Open a file for reading.
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: io/CStream.h:29
virtual size_t Write(const void *Buffer, size_t Count)=0
Introduces a pure virtual method responsible for writing to the stream.
virtual size_t Read(void *Buffer, size_t Count)=0
Introduces a pure virtual method responsible for reading from the stream.
#define MRPT_START
Definition: exceptions.h:262
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
#define MRPT_END_WITH_CLEAN_UP(stuff)
Definition: exceptions.h:268
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
GLuint buffer
Definition: glext.h:3917
GLenum GLsizei GLenum format
Definition: glext.h:3531
GLsizei const GLchar ** string
Definition: glext.h:4101
std::string getTempFileName()
Returns the name of a proposed temporary file name.
Definition: filesystem.cpp:282
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Definition: datetime.h:87
bool vectorToBinaryFile(const std::vector< uint8_t > &vec, const std::string &fileName)
Saves a vector directly as a binary dump to a file:
Compression using the "zip" algorithm and from/to gzip (gz) files.
Definition: zip.h:23
bool decompress_gz_data_block(const std::vector< uint8_t > &in_gz_data, std::vector< uint8_t > &out_data)
Decompress an array of bytes storing a gz-compressed stream of data into a memory buffer.
Definition: zip.cpp:358
void compress(void *inData, size_t inDataSize, std::vector< unsigned char > &outData)
Compress an array of bytes into another one.
Definition: zip.cpp:35
bool compress_gz_file(const std::string &file_path, const std::vector< uint8_t > &buffer, const int compress_level=9)
Compress a memory buffer into a gzip file (xxxx.gz).
Definition: zip.cpp:234
void decompress(void *inData, size_t inDataSize, std::vector< unsigned char > &outData, size_t outDataEstimatedSize)
Decompress an array of bytes into another one.
Definition: zip.cpp:135
bool compress_gz_data_block(const std::vector< uint8_t > &in_data, std::vector< uint8_t > &out_gz_data, const int compress_level=9)
Compress a memory buffer in gz-file format and return it as a block a memory.
Definition: zip.cpp:260
bool decompress_gz_file(const std::string &file_path, std::vector< uint8_t > &buffer)
Decompress a gzip file (xxxx.gz) into a memory buffer.
Definition: zip.cpp:209
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define Z_OK
Definition: zlib.h:151
voidp gzFile
Definition: zlib.h:1026



Page generated by Doxygen 1.9.1 for MRPT 1.9.9 Git: 814d80880 Fri Aug 24 01:51:28 2018 +0200 at mar 26 may 2026 12:30:59 CEST