MRPT  2.0.4
zip.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://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/core/exceptions.h>
22 #include <mrpt/io/zip.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, static_cast<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, reinterpret_cast<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  auto 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  auto 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 }
bool vectorToBinaryFile(const std::vector< uint8_t > &vec, const std::string &fileName)
Saves a vector directly as a binary dump to a file:
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
#define MRPT_START
Definition: exceptions.h:241
bool open(const std::string &fileName)
Open a file for reading.
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
std::string std::string format(std::string_view fmt, ARGS &&... args)
Definition: format.h:26
bool open(const std::string &fileName, int compress_level=1, mrpt::optional_ref< std::string > error_msg=std::nullopt)
Open a file for write, choosing the compression level.
virtual size_t Read(void *Buffer, size_t Count)=0
Introduces a pure virtual method responsible for reading from the stream.
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
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Definition: datetime.h:86
#define MRPT_END_WITH_CLEAN_UP(stuff)
Definition: exceptions.h:247
bool fileOpenCorrectly() const
Returns true if the file was open without errors.
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: io/CStream.h:28
Compression using the "zip" algorithm and from/to gzip (gz) files.
Definition: zip.h:22
size_t Read(void *Buffer, size_t Count) override
Introduces a pure virtual method responsible for reading from the stream.
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.
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:120
std::string getTempFileName()
Returns the name of a proposed temporary file name.
Definition: filesystem.cpp:283
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
Method for getting the total number of compressed bytes of in the file (the physical size of the comp...
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
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
mrpt::vision::TStereoCalibResults out
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
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
size_t Write(const void *Buffer, size_t Count) override
Introduces a pure virtual method responsible for writing to the stream.
uint64_t getTotalBytesCount() const override
Returns the total amount of bytes in the stream.
Transparently opens a compressed "gz" file and reads uncompressed data from it.
Saves data to a file and transparently compress the data using the given compression level...
void compress(void *inData, size_t inDataSize, std::vector< unsigned char > &outData)
Compress an array of bytes into another one.
Definition: zip.cpp:35



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 33de1d0ad Sat Jun 20 11:02:42 2020 +0200 at sáb jun 20 17:35:17 CEST 2020