Browse Source
ADDED: Support compressed STEP and VRML files
ADDED: Support compressed STEP and VRML files
This adds support for opening .stpZ, step.gz and .wrz files where the files have been compressed using ZIP or gzip according to the "standard" published by the MBx volunteer forum at https://www.cax-if.org/documents/rec_prac_file_compression_v12.pdf Fixes https://gitlab.com/kicad/code/kicad/issues/2479pull/16/head
10 changed files with 291 additions and 99 deletions
-
9CMakeLists.txt
-
6plugins/3d/oce/CMakeLists.txt
-
67plugins/3d/oce/loadmodel.cpp
-
70plugins/3d/oce/oce.cpp
-
6plugins/3d/vrml/CMakeLists.txt
-
100plugins/3d/vrml/vrml.cpp
-
1thirdparty/CMakeLists.txt
-
7thirdparty/gzip-hpp/CMakeLists.txt
-
11thirdparty/gzip-hpp/LICENSE.BSD2
-
113thirdparty/gzip-hpp/decompress.hpp
@ -0,0 +1,7 @@ |
|||
add_library( gzip-hpp INTERFACE ) |
|||
|
|||
target_include_directories( gzip-hpp INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ) |
|||
|
|||
target_sources( gzip-hpp INTERFACE |
|||
${CMAKE_CURRENT_SOURCE_DIR}/decompress.hpp |
|||
) |
|||
@ -0,0 +1,11 @@ |
|||
|
|||
|
|||
Copyright (c) 2017, Mapbox Inc. |
|||
All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
|||
|
|||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
|||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
@ -0,0 +1,113 @@ |
|||
#ifndef ZLIB_CONST
|
|||
#define ZLIB_CONST
|
|||
#endif
|
|||
|
|||
// zlib
|
|||
#include <zlib.h>
|
|||
|
|||
// std
|
|||
#include <limits>
|
|||
#include <stdexcept>
|
|||
#include <string>
|
|||
|
|||
namespace gzip { |
|||
|
|||
inline void decompress(const char* data, |
|||
std::size_t size, |
|||
std::string& output, |
|||
std::size_t max_uncompressed_size = 0, |
|||
std::size_t buffering_size = 0) |
|||
{ |
|||
if (buffering_size == 0) |
|||
{ |
|||
buffering_size = (size * 2) - (size / 2) + 16; |
|||
} |
|||
z_stream inflate_s; |
|||
inflate_s.zalloc = Z_NULL; |
|||
inflate_s.zfree = Z_NULL; |
|||
inflate_s.opaque = Z_NULL; |
|||
inflate_s.avail_in = 0; |
|||
inflate_s.next_in = Z_NULL; |
|||
|
|||
// The windowBits parameter is the base two logarithm of the window size (the size of the history buffer).
|
|||
// It should be in the range 8..15 for this version of the library.
|
|||
// Larger values of this parameter result in better compression at the expense of memory usage.
|
|||
// This range of values also changes the decoding type:
|
|||
// -8 to -15 for raw deflate
|
|||
// 8 to 15 for zlib
|
|||
// (8 to 15) + 16 for gzip
|
|||
// (8 to 15) + 32 to automatically detect gzip/zlib header
|
|||
constexpr int window_bits = 15 + 32; // auto with windowbits of 15
|
|||
|
|||
constexpr unsigned int max_uint = std::numeric_limits<unsigned int>::max(); |
|||
const unsigned int size_step = buffering_size > max_uint ? max_uint : static_cast<unsigned int>(buffering_size); |
|||
if( max_uncompressed_size != 0 && size_step > max_uncompressed_size ) |
|||
{ |
|||
throw std::runtime_error( |
|||
"buffer size used during decompression of gzip will use more memory then allowed, " |
|||
"either increase the limit or reduce the buffer size" ); |
|||
} |
|||
|
|||
#pragma GCC diagnostic push
|
|||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
|||
if (inflateInit2(&inflate_s, window_bits) != Z_OK) |
|||
{ |
|||
throw std::runtime_error("inflate init failed"); |
|||
} |
|||
#pragma GCC diagnostic pop
|
|||
inflate_s.next_in = reinterpret_cast<z_const Bytef*>(data); |
|||
inflate_s.avail_in = static_cast<unsigned int>(size); |
|||
std::string buffer(static_cast<std::size_t>(size_step), char()); |
|||
do |
|||
{ |
|||
inflate_s.avail_out = size_step; |
|||
inflate_s.next_out = reinterpret_cast<Bytef*>(&buffer[0]); |
|||
const int ret = inflate(&inflate_s, Z_FINISH); |
|||
if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR) |
|||
{ |
|||
std::string error_msg = inflate_s.msg; |
|||
inflateEnd(&inflate_s); |
|||
throw std::runtime_error(error_msg); |
|||
} |
|||
if (max_uncompressed_size != 0 && (output.size() + size_step - inflate_s.avail_out) > max_uncompressed_size) |
|||
{ |
|||
inflateEnd(&inflate_s); |
|||
throw std::runtime_error("size of output string will use more memory then intended when decompressing"); |
|||
} |
|||
output.append(buffer, 0, size_step - inflate_s.avail_out); |
|||
} while (inflate_s.avail_out == 0); |
|||
const int ret2 = inflateEnd(&inflate_s); |
|||
if (ret2 != Z_OK) |
|||
{ |
|||
throw std::runtime_error("Unexpected gzip decompression error, state of stream was inconsistent"); |
|||
} |
|||
} |
|||
|
|||
inline void decompress(std::string const& input, |
|||
std::string& output, |
|||
std::size_t max_uncompressed_size = 0, |
|||
std::size_t buffering_size = 0) |
|||
{ |
|||
return decompress(input.data(), input.size(), output, max_uncompressed_size, buffering_size); |
|||
} |
|||
|
|||
inline std::string decompress(const char* data, |
|||
std::size_t size, |
|||
std::size_t max_uncompressed_size = 0, |
|||
std::size_t buffering_size = 0) |
|||
{ |
|||
std::string output; |
|||
decompress(data, size, output, max_uncompressed_size, buffering_size); |
|||
return output; |
|||
} |
|||
|
|||
inline std::string decompress(std::string const& input, |
|||
std::size_t max_uncompressed_size = 0, |
|||
std::size_t buffering_size = 0) |
|||
{ |
|||
std::string output; |
|||
decompress(input.data(), input.size(), output, max_uncompressed_size, buffering_size); |
|||
return output; |
|||
} |
|||
|
|||
} // namespace gzip
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue