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



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019