pull/198/head
commit
268a07b950
|
@ -12,15 +12,15 @@ SET ( PROJECT_VERSION "${ASSIMP_VERSION}" )
|
|||
set(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources")
|
||||
|
||||
option(ASSIMP_OPT_BUILD_PACKAGES "Set to ON to generate CPack configuration files and packaging targets" OFF)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules")
|
||||
set(LIBASSIMP_COMPONENT libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
|
||||
set(LIBASSIMP-DEV_COMPONENT libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}-dev)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
|
||||
set(LIBASSIMP_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}" )
|
||||
set(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}-dev" )
|
||||
set(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev)
|
||||
set(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW )
|
||||
add_definitions(-fPIC) # this is a very important switch and some libraries seem now to have it....
|
||||
## hide all not-exported symbols
|
||||
# hide all not-exported symbols
|
||||
add_definitions( -fvisibility=hidden -Wall )
|
||||
elseif(MSVC)
|
||||
# enable multi-core compilation with MSVC
|
||||
|
@ -37,9 +37,9 @@ INCLUDE (PrecompiledHeader)
|
|||
# source tree. During an out-of-source build, however, do not litter this
|
||||
# directory, since that is probably what the user wanted to avoid.
|
||||
IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
|
||||
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
|
||||
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib )
|
||||
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin )
|
||||
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
|
||||
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
|
||||
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" )
|
||||
ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
|
||||
|
||||
# Cache these to allow the user to override them manually.
|
||||
|
@ -50,7 +50,7 @@ SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE PATH
|
|||
SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH
|
||||
"Path the tool executables are installed to." )
|
||||
|
||||
SET(ASSIMP_DEBUG_POSTFIX "D" CACHE STRING "Debug Postfitx for lib, samples and tools")
|
||||
SET(ASSIMP_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools")
|
||||
|
||||
# Allow the user to build a static library
|
||||
SET ( ASSIMP_BUILD_STATIC_LIB OFF CACHE BOOL
|
||||
|
@ -62,9 +62,9 @@ CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assi
|
|||
INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
|
||||
|
||||
# cmake configuration files
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
|
||||
|
||||
# Only generate this target if no higher-level project already has
|
||||
IF (NOT TARGET uninstall)
|
||||
|
@ -75,7 +75,7 @@ ENDIF()
|
|||
|
||||
# Globally enbale Boost resp. the Boost workaround – it is also needed by the
|
||||
# tools which include the Assimp headers.
|
||||
SET ( ASSIMP_ENABLE_BOOST_WORKAROUND OFF CACHE BOOL
|
||||
SET ( ASSIMP_ENABLE_BOOST_WORKAROUND ON CACHE BOOL
|
||||
"If a simple implementation of the used Boost functions is used. Slightly reduces functionality, but enables builds without Boost available."
|
||||
)
|
||||
IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
|
||||
|
@ -113,8 +113,8 @@ if( NOT ZLIB_FOUND )
|
|||
# compile from sources
|
||||
add_subdirectory(contrib/zlib)
|
||||
set(ZLIB_FOUND 1)
|
||||
set(ZLIB_LIBRARIES zlib)
|
||||
set(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/zlib)
|
||||
set(ZLIB_LIBRARIES zlibstatic)
|
||||
set(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
|
||||
else(NOT ZLIB_FOUND)
|
||||
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
|
||||
endif(NOT ZLIB_FOUND)
|
||||
|
@ -154,7 +154,6 @@ ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "")
|
|||
|
||||
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
|
||||
|
||||
|
||||
ADD_SUBDIRECTORY( code/ )
|
||||
SET ( ASSIMP_BUILD_ASSIMP_TOOLS ON CACHE BOOL
|
||||
"If the supplementary tools for Assimp are built in addition to the library."
|
||||
|
@ -195,38 +194,38 @@ ENDIF(MSVC)
|
|||
|
||||
if(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
|
||||
# Packing information
|
||||
set(CPACK_PACKAGE_NAME assimp{ASSIMP_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.")
|
||||
set(CPACK_PACKAGE_VENDOR "http://assimp.sourceforge.net/")
|
||||
set(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY " - Open Asset Import Library ${ASSIMP_VERSION}")
|
||||
set(CPACK_PACKAGE_VERSION ${ASSIMP_VERSION}.${ASSIMP_PACKAGE_VERSION})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${ASSIMP_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${ASSIMP_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${ASSIMP_VERSION_PATCH})
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
|
||||
#set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_SOURCE_DIR}/description)
|
||||
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE)
|
||||
set(CPACK_PACKAGE_VENDOR "http://assimp.sourceforge.net/")
|
||||
set(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY " - Open Asset Import Library ${ASSIMP_VERSION}")
|
||||
set(CPACK_PACKAGE_VERSION "${ASSIMP_VERSION}.${ASSIMP_PACKAGE_VERSION}" )
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "${ASSIMP_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${ASSIMP_VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${ASSIMP_VERSION_PATCH}")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
|
||||
#set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
||||
|
||||
string(TOUPPER ${LIBASSIMP_COMPONENT} LIBASSIMP_COMPONENT_UPPER)
|
||||
string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} LIBASSIMP-DEV_COMPONENT_UPPER)
|
||||
string(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER")
|
||||
string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER")
|
||||
|
||||
set(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools")
|
||||
set(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS ${LIBASSIMP_COMPONENT})
|
||||
set(CPACK_COMPONENT_${LIBASSIMP_COMPONENT_UPPER}_DISPLAY_NAME "libraries")
|
||||
set(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools")
|
||||
set(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" )
|
||||
set(CPACK_COMPONENT_${LIBASSIMP_COMPONENT_UPPER}_DISPLAY_NAME "libraries")
|
||||
set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DISPLAY_NAME "common headers and installs")
|
||||
set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DEPENDS ${LIBASSIMP_COMPONENT})
|
||||
set(CPACK_COMPONENT_ASSIMP-DEV_DISPLAY_NAME ${CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT}_DISPLAY_NAME})
|
||||
set(CPACK_COMPONENT_ASSIMP-DEV_DEPENDS ${LIBASSIMP-DEV_COMPONENT})
|
||||
set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DEPENDS $ "{LIBASSIMP_COMPONENT}" )
|
||||
set(CPACK_COMPONENT_ASSIMP-DEV_DISPLAY_NAME "${CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT}_DISPLAY_NAME}" )
|
||||
set(CPACK_COMPONENT_ASSIMP-DEV_DEPENDS "${LIBASSIMP-DEV_COMPONENT}" )
|
||||
set(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake libboost-dev libboost-thread-dev libboost-math-dev zlib1g-dev pkg-config)
|
||||
|
||||
# debian
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY optional)
|
||||
set(CPACK_DEBIAN_CMAKE_OPTIONS "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION libs)
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS ${CPACK_COMPONENTS_ALL})
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
set(CPACK_DEBIAN_CMAKE_OPTIONS "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "libs" )
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SUGGESTS)
|
||||
set(CPACK_DEBIAN_PACKAGE_NAME assimp)
|
||||
set(CPACK_DEBIAN_PACKAGE_NAME "assimp")
|
||||
set(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/cppunit-1.12.1 contrib/cppunit_note.txt contrib/zlib workspaces test doc obj samples packaging)
|
||||
set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force)
|
||||
set(CPACK_DEBIAN_CHANGELOG)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
===============================================
|
||||
The Asset-Importer-Library Coding conventions
|
||||
===============================================
|
||||
|
||||
If you want to participate to the Asset-Importer_Library please have a look
|
||||
onto these coding conventions and try to follow them. They are more or less
|
||||
some kind of guide line to help others coming into the code and help all
|
||||
the Asset-Importer-Library users.
|
||||
|
||||
Tab width
|
||||
===========
|
||||
The tab width shall be 4 spaces.
|
||||
|
||||
|
57
Readme.md
57
Readme.md
|
@ -1,20 +1,19 @@
|
|||
Open Asset Import Library (assimp)
|
||||
========
|
||||
|
||||
Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a single, in-memory format__. It supports more than 30 file formats. It also supports exporting files to a few selected file formats.
|
||||
Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a single, in-memory format__. It supports more than __30 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials_ and many more.
|
||||
|
||||
Its abbreviated name under which it is commonly known is __assimp__.
|
||||
|
||||
This is the development trunk of assimp containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories. According to [Travis-CI] (https://travis-ci.org/), the current build status of the trunk is [![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
|
||||
|
||||
|
||||
#### 1.1 Supported file formats ####
|
||||
#### Supported file formats ####
|
||||
|
||||
The library provides importers for a lot of file formats, including:
|
||||
|
||||
- 3DS
|
||||
- BLEND (Blender 3D)
|
||||
- DAE (Collada)
|
||||
- DAE/Collada
|
||||
- FBX
|
||||
- IFC-STEP
|
||||
- ASE
|
||||
|
@ -46,6 +45,10 @@ The library provides importers for a lot of file formats, including:
|
|||
- NDO
|
||||
- Ogre XML
|
||||
- Q3D
|
||||
|
||||
Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries.
|
||||
|
||||
- C4D (https://github.com/acgessler/assimp-cinema4d)
|
||||
|
||||
Exporters include:
|
||||
|
||||
|
@ -58,7 +61,7 @@ See [the full list here](http://assimp.sourceforge.net/main_features_formats.htm
|
|||
|
||||
|
||||
|
||||
#### 1.2 Repository structure ####
|
||||
#### Repository structure ####
|
||||
|
||||
|
||||
Open Asset Import Library is implemented in C++ (but provides both a C and a
|
||||
|
@ -68,48 +71,50 @@ C++ish interface). The directory structure is:
|
|||
/code Source code
|
||||
/contrib Third-party libraries
|
||||
/doc Documentation (doxysource and pre-compiled docs)
|
||||
/include Public header C and C++ header files.
|
||||
/lib Static library location for Windows.
|
||||
/obj Object file location for Windows.
|
||||
/port Ports to other languages and scripts to maintain those.
|
||||
/test Unit- and regression tests, test suite of models.
|
||||
/tools Tools (viewer, command line `assimp`).
|
||||
/include Public header C and C++ header files
|
||||
/lib Static library location for Windows
|
||||
/obj Object file location for Windows
|
||||
/scripts Scripts used to generate the loading code for some formats
|
||||
/port Ports to other languages and scripts to maintain those.
|
||||
/test Unit- and regression tests, test suite of models
|
||||
/tools Tools (viewer, command line `assimp`)
|
||||
/samples A small number of samples to illustrate possible
|
||||
use cases for Assimp.
|
||||
use cases for Assimp
|
||||
/workspaces Build enviroments for vc,xcode,... (deprecated,
|
||||
CMake has superseeded all legacy build options!)
|
||||
|
||||
|
||||
|
||||
### 2. Build the library ###
|
||||
### Building ###
|
||||
|
||||
|
||||
Take a look into the `INSTALL` file. Or fire up CMake with the usual steps.
|
||||
|
||||
|
||||
|
||||
### 3. Where to get help ###
|
||||
### Where to get help ###
|
||||
|
||||
|
||||
For more information, visit [our website](http://assimp.sourceforge.net/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
|
||||
(CHMs for Windows are included in some release packages and should be located right here in the root folder).
|
||||
|
||||
If the documentation doesn't solve your problems, try our forums at SF.net
|
||||
If the documentation doesn't solve your problems,
|
||||
[try our forums at SF.net](http://sourceforge.net/p/assimp/discussion/817654) or ask on
|
||||
[StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
|
||||
|
||||
|
||||
- [Open Discussion](http://sourceforge.net/projects/assimp/forums/forum/817653)
|
||||
- [General Help](http://sourceforge.net/projects/assimp/forums/forum/817654)
|
||||
|
||||
|
||||
For development stuff, there is also a mailing list, _assimp-discussions_
|
||||
For development discussions, there is also a mailing list, _assimp-discussions_
|
||||
[(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions)
|
||||
|
||||
### Contributing ###
|
||||
|
||||
Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
|
||||
a pull request with your changes against the main repository's `master` branch.
|
||||
|
||||
|
||||
### 4. License ###
|
||||
### License ###
|
||||
|
||||
The license of the Asset Import Library is based on the modified, __3-clause BSD__-License, which is a very liberal license. An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - and don't sue us if our code doesn't work.
|
||||
Our license is based on the modified, __3-clause BSD__-License, which is very liberal.
|
||||
|
||||
Note that, unlike LGPLed code, you may link statically to Assimp.
|
||||
For the formal details, see the `LICENSE` file.
|
||||
An _informal_ summary is: do whatever you want, but include Assimp's license text with your product -
|
||||
and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp.
|
||||
For the legal details, see the `LICENSE` file.
|
||||
|
||||
|
|
|
@ -79,6 +79,8 @@ static const aiImporterDesc desc = {
|
|||
Discreet3DS::Chunk chunk; \
|
||||
ReadChunk(&chunk); \
|
||||
int chunkSize = chunk.Size-sizeof(Discreet3DS::Chunk); \
|
||||
if(chunkSize <= 0) \
|
||||
continue; \
|
||||
const int oldReadLimit = stream->GetReadLimit(); \
|
||||
stream->SetReadLimit(stream->GetCurrentPos() + chunkSize); \
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex
|
|||
return Exporter().GetExportFormatDescription(pIndex);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)
|
||||
{
|
||||
|
@ -72,8 +73,19 @@ ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)
|
|||
}
|
||||
|
||||
SceneCombiner::CopyScene(pOut,pIn,true);
|
||||
ScenePriv(*pOut)->mIsCopy = true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn)
|
||||
{
|
||||
// note: aiReleaseImport() is also able to delete scene copies, but in addition
|
||||
// it also handles scenes with import metadata.
|
||||
delete pIn;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing )
|
||||
{
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2013, assimp team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software 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.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
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
|
||||
OWNER 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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderBMesh.cpp
|
||||
* @brief Conversion of Blender's new BMesh stuff
|
||||
*/
|
||||
|
||||
#include "AssimpPCH.h"
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderScene.h"
|
||||
#include "BlenderBMesh.h"
|
||||
#include "BlenderTessellator.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
template< > const std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: ";
|
||||
}
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
using namespace Assimp::Formatter;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ):
|
||||
BMesh( mesh ),
|
||||
triMesh( NULL )
|
||||
{
|
||||
AssertValidMesh( );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderBMeshConverter::~BlenderBMeshConverter( )
|
||||
{
|
||||
DestroyTriMesh( );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool BlenderBMeshConverter::ContainsBMesh( ) const
|
||||
{
|
||||
// TODO - Should probably do some additional verification here
|
||||
return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const Mesh* BlenderBMeshConverter::TriangulateBMesh( )
|
||||
{
|
||||
AssertValidMesh( );
|
||||
AssertValidSizes( );
|
||||
PrepareTriMesh( );
|
||||
|
||||
for ( int i = 0; i < BMesh->totpoly; ++i )
|
||||
{
|
||||
const MPoly& poly = BMesh->mpoly[ i ];
|
||||
ConvertPolyToFaces( poly );
|
||||
}
|
||||
|
||||
return triMesh;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::AssertValidMesh( )
|
||||
{
|
||||
if ( !ContainsBMesh( ) )
|
||||
{
|
||||
ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::AssertValidSizes( )
|
||||
{
|
||||
if ( BMesh->totpoly != BMesh->mpoly.size( ) )
|
||||
{
|
||||
ThrowException( "BMesh poly array has incorrect size" );
|
||||
}
|
||||
if ( BMesh->totloop != BMesh->mloop.size( ) )
|
||||
{
|
||||
ThrowException( "BMesh loop array has incorrect size" );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::PrepareTriMesh( )
|
||||
{
|
||||
if ( triMesh )
|
||||
{
|
||||
DestroyTriMesh( );
|
||||
}
|
||||
|
||||
triMesh = new Mesh( *BMesh );
|
||||
triMesh->totface = 0;
|
||||
triMesh->mface.clear( );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::DestroyTriMesh( )
|
||||
{
|
||||
delete triMesh;
|
||||
triMesh = NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly )
|
||||
{
|
||||
const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ];
|
||||
if ( poly.totloop == 3 || poly.totloop == 4 )
|
||||
{
|
||||
AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 );
|
||||
}
|
||||
else if ( poly.totloop > 4 )
|
||||
{
|
||||
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
BlenderTessellatorGL tessGL( *this );
|
||||
tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
|
||||
#elif ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
BlenderTessellatorP2T tessP2T( *this );
|
||||
tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
|
||||
{
|
||||
MFace face;
|
||||
face.v1 = v1;
|
||||
face.v2 = v2;
|
||||
face.v3 = v3;
|
||||
face.v4 = v4;
|
||||
// TODO - Work out how materials work
|
||||
face.mat_nr = 0;
|
||||
triMesh->mface.push_back( face );
|
||||
triMesh->totface = triMesh->mface.size( );
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2013, assimp team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software 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.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
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
|
||||
OWNER 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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderBMesh.h
|
||||
* @brief Conversion of Blender's new BMesh stuff
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_BMESH_H
|
||||
#define INCLUDED_AI_BLEND_BMESH_H
|
||||
|
||||
#include "LogAux.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
// TinyFormatter.h
|
||||
namespace Formatter
|
||||
{
|
||||
template < typename T,typename TR, typename A > class basic_formatter;
|
||||
typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
|
||||
}
|
||||
|
||||
// BlenderScene.h
|
||||
namespace Blender
|
||||
{
|
||||
struct Mesh;
|
||||
struct MPoly;
|
||||
struct MLoop;
|
||||
}
|
||||
|
||||
class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter >
|
||||
{
|
||||
public:
|
||||
BlenderBMeshConverter( const Blender::Mesh* mesh );
|
||||
~BlenderBMeshConverter( );
|
||||
|
||||
bool ContainsBMesh( ) const;
|
||||
|
||||
const Blender::Mesh* TriangulateBMesh( );
|
||||
|
||||
private:
|
||||
void AssertValidMesh( );
|
||||
void AssertValidSizes( );
|
||||
void PrepareTriMesh( );
|
||||
void DestroyTriMesh( );
|
||||
void ConvertPolyToFaces( const Blender::MPoly& poly );
|
||||
void AddFace( int v1, int v2, int v3, int v4 = 0 );
|
||||
|
||||
const Blender::Mesh* BMesh;
|
||||
Blender::Mesh* triMesh;
|
||||
|
||||
friend class BlenderTessellatorGL;
|
||||
friend class BlenderTessellatorP2T;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // INCLUDED_AI_BLEND_BMESH_H
|
|
@ -278,19 +278,23 @@ public:
|
|||
// --------------------------------------------------------
|
||||
// field parsing for pointer or dynamic array types
|
||||
// (boost::shared_ptr or boost::shared_array)
|
||||
// The return value indicates whether the data was already cached.
|
||||
template <int error_policy, template <typename> class TOUT, typename T>
|
||||
void ReadFieldPtr(TOUT<T>& out, const char* name,
|
||||
const FileDatabase& db) const;
|
||||
bool ReadFieldPtr(TOUT<T>& out, const char* name,
|
||||
const FileDatabase& db,
|
||||
bool non_recursive = false) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// field parsing for static arrays of pointer or dynamic
|
||||
// array types (boost::shared_ptr[] or boost::shared_array[])
|
||||
// The return value indicates whether the data was already cached.
|
||||
template <int error_policy, template <typename> class TOUT, typename T, size_t N>
|
||||
void ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
|
||||
bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
|
||||
const FileDatabase& db) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// field parsing for `normal` values
|
||||
// The return value indicates whether the data was already cached.
|
||||
template <int error_policy, typename T>
|
||||
void ReadField(T& out, const char* name,
|
||||
const FileDatabase& db) const;
|
||||
|
@ -299,17 +303,18 @@ private:
|
|||
|
||||
// --------------------------------------------------------
|
||||
template <template <typename> class TOUT, typename T>
|
||||
void ResolvePointer(TOUT<T>& out, const Pointer & ptrval,
|
||||
const FileDatabase& db, const Field& f) const;
|
||||
bool ResolvePointer(TOUT<T>& out, const Pointer & ptrval,
|
||||
const FileDatabase& db, const Field& f,
|
||||
bool non_recursive = false) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
template <template <typename> class TOUT, typename T>
|
||||
void ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
|
||||
const FileDatabase& db, const Field& f) const;
|
||||
bool ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
|
||||
const FileDatabase& db, const Field& f, bool) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
void ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval,
|
||||
const FileDatabase& db, const Field& f) const;
|
||||
bool ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval,
|
||||
const FileDatabase& db, const Field& f, bool) const;
|
||||
|
||||
// --------------------------------------------------------
|
||||
inline const FileBlockHead* LocateFileBlockForAddress(
|
||||
|
@ -384,10 +389,11 @@ template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> {
|
|||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------
|
||||
template <> inline void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
|
||||
template <> inline bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
|
||||
const Pointer & ptrval,
|
||||
const FileDatabase& db,
|
||||
const Field& f
|
||||
const Field& f,
|
||||
bool
|
||||
) const;
|
||||
|
||||
|
||||
|
|
|
@ -180,7 +180,8 @@ void Structure :: ReadFieldArray2(T (& out)[M][N], const char* name, const FileD
|
|||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <int error_policy, template <typename> class TOUT, typename T>
|
||||
void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db) const
|
||||
bool Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db,
|
||||
bool non_recursive /*= false*/) const
|
||||
{
|
||||
const StreamReaderAny::pos old = db.reader->GetCurrentPos();
|
||||
Pointer ptrval;
|
||||
|
@ -203,23 +204,27 @@ void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabas
|
|||
_defaultInitializer<error_policy>()(out,e.what());
|
||||
|
||||
out.reset();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// resolve the pointer and load the corresponding structure
|
||||
ResolvePointer(out,ptrval,db,*f);
|
||||
const bool res = ResolvePointer(out,ptrval,db,*f, non_recursive);
|
||||
|
||||
// and recover the previous stream position
|
||||
db.reader->SetCurrentPos(old);
|
||||
if(!non_recursive) {
|
||||
// and recover the previous stream position
|
||||
db.reader->SetCurrentPos(old);
|
||||
}
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <int error_policy, template <typename> class TOUT, typename T, size_t N>
|
||||
void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
|
||||
bool Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
|
||||
const FileDatabase& db) const
|
||||
{
|
||||
// XXX see if we can reduce this to call to the 'normal' ReadFieldPtr
|
||||
|
@ -253,11 +258,13 @@ void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
|
|||
for(size_t i = 0; i < N; ++i) {
|
||||
out[i].reset();
|
||||
}
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool res = true;
|
||||
for(size_t i = 0; i < N; ++i) {
|
||||
// resolve the pointer and load the corresponding structure
|
||||
ResolvePointer(out[i],ptrval[i],db,*f);
|
||||
res = ResolvePointer(out[i],ptrval[i],db,*f) && res;
|
||||
}
|
||||
|
||||
// and recover the previous stream position
|
||||
|
@ -266,6 +273,7 @@ void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
|
|||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().fields_read;
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
|
@ -296,11 +304,13 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co
|
|||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <template <typename> class TOUT, typename T>
|
||||
void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const
|
||||
bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,
|
||||
const Field& f,
|
||||
bool non_recursive /*= false*/) const
|
||||
{
|
||||
out.reset();
|
||||
out.reset(); // ensure null pointers work
|
||||
if (!ptrval.val) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
const Structure& s = db.dna[f.type];
|
||||
// find the file block the pointer is pointing to
|
||||
|
@ -318,7 +328,7 @@ void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const Fil
|
|||
// try to retrieve the object from the cache
|
||||
db.cache(out).get(s,out,ptrval);
|
||||
if (out) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// seek to this location, but save the previous stream pointer.
|
||||
|
@ -334,27 +344,36 @@ void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const Fil
|
|||
// cache the object before we convert it to avoid cyclic recursion.
|
||||
db.cache(out).set(s,out,ptrval);
|
||||
|
||||
for (size_t i = 0; i < num; ++i,++o) {
|
||||
s.Convert(*o,db);
|
||||
}
|
||||
// if the non_recursive flag is set, we don't do anything but leave
|
||||
// the cursor at the correct position to resolve the object.
|
||||
if (!non_recursive) {
|
||||
for (size_t i = 0; i < num; ++i,++o) {
|
||||
s.Convert(*o,db);
|
||||
}
|
||||
|
||||
db.reader->SetCurrentPos(pold);
|
||||
db.reader->SetCurrentPos(pold);
|
||||
}
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
if(out) {
|
||||
++db.stats().pointers_resolved;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
inline void Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, const FileDatabase& db, const Field& /*f*/) const
|
||||
inline bool Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval,
|
||||
const FileDatabase& db,
|
||||
const Field&,
|
||||
bool) const
|
||||
{
|
||||
// Currently used exclusively by PackedFile::data to represent
|
||||
// a simple offset into the mapped BLEND file.
|
||||
out.reset();
|
||||
if (!ptrval.val) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the file block the pointer is pointing to
|
||||
|
@ -362,11 +381,15 @@ inline void Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, c
|
|||
|
||||
out = boost::shared_ptr< FileOffset > (new FileOffset());
|
||||
out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <template <typename> class TOUT, typename T>
|
||||
void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const
|
||||
bool Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
|
||||
const FileDatabase& db,
|
||||
const Field& f,
|
||||
bool) const
|
||||
{
|
||||
// This is a function overload, not a template specialization. According to
|
||||
// the partial ordering rules, it should be selected by the compiler
|
||||
|
@ -374,7 +397,7 @@ void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
|
|||
|
||||
out.reset();
|
||||
if (!ptrval.val) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the file block the pointer is pointing to
|
||||
|
@ -385,6 +408,7 @@ void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
|
|||
const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
|
||||
db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
|
||||
|
||||
bool res = false;
|
||||
// allocate raw storage for the array
|
||||
out.resize(num);
|
||||
for (size_t i = 0; i< num; ++i) {
|
||||
|
@ -392,17 +416,19 @@ void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
|
|||
Convert(val,db);
|
||||
|
||||
// and resolve the pointees
|
||||
ResolvePointer(out[i],val,db,f);
|
||||
res = ResolvePointer(out[i],val,db,f) && res;
|
||||
}
|
||||
|
||||
db.reader->SetCurrentPos(pold);
|
||||
return res;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
|
||||
template <> bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
|
||||
const Pointer & ptrval,
|
||||
const FileDatabase& db,
|
||||
const Field& /*f*/
|
||||
const Field&,
|
||||
bool
|
||||
) const
|
||||
{
|
||||
// Special case when the data type needs to be determined at runtime.
|
||||
|
@ -410,7 +436,7 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
|
|||
|
||||
out.reset();
|
||||
if (!ptrval.val) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the file block the pointer is pointing to
|
||||
|
@ -422,7 +448,7 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
|
|||
// try to retrieve the object from the cache
|
||||
db.cache(out).get(s,out,ptrval);
|
||||
if (out) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// seek to this location, but save the previous stream pointer.
|
||||
|
@ -440,7 +466,7 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
|
|||
DefaultLogger::get()->warn((Formatter::format(),
|
||||
"Failed to find a converter for the `",s.name,"` structure"
|
||||
));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocate the object hull
|
||||
|
@ -459,11 +485,11 @@ template <> void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::
|
|||
// to perform additional type checking.
|
||||
out->dna_type = s.name.c_str();
|
||||
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
|
||||
++db.stats().pointers_resolved;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
|
|
|
@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "BlenderIntermediate.h"
|
||||
#include "BlenderModifier.h"
|
||||
#include "BlenderBMesh.h"
|
||||
|
||||
#include "StreamReader.h"
|
||||
#include "MemoryIOWrapper.h"
|
||||
|
@ -446,9 +447,43 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
|
|||
else {
|
||||
name = aiString( img->name );
|
||||
}
|
||||
out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(
|
||||
conv_data.next_texture[aiTextureType_DIFFUSE]++)
|
||||
);
|
||||
|
||||
aiTextureType texture_type = aiTextureType_UNKNOWN;
|
||||
MTex::MapType map_type = tex->mapto;
|
||||
|
||||
if (map_type & MTex::MapType_COL)
|
||||
texture_type = aiTextureType_DIFFUSE;
|
||||
else if (map_type & MTex::MapType_NORM) {
|
||||
if (tex->tex->imaflag & Tex::ImageFlags_NORMALMAP) {
|
||||
texture_type = aiTextureType_NORMALS;
|
||||
}
|
||||
else {
|
||||
texture_type = aiTextureType_HEIGHT;
|
||||
}
|
||||
out->AddProperty(&tex->norfac,1,AI_MATKEY_BUMPSCALING);
|
||||
}
|
||||
else if (map_type & MTex::MapType_COLSPEC)
|
||||
texture_type = aiTextureType_SPECULAR;
|
||||
else if (map_type & MTex::MapType_COLMIR)
|
||||
texture_type = aiTextureType_REFLECTION;
|
||||
//else if (map_type & MTex::MapType_REF)
|
||||
else if (map_type & MTex::MapType_SPEC)
|
||||
texture_type = aiTextureType_SHININESS;
|
||||
else if (map_type & MTex::MapType_EMIT)
|
||||
texture_type = aiTextureType_EMISSIVE;
|
||||
//else if (map_type & MTex::MapType_ALPHA)
|
||||
//else if (map_type & MTex::MapType_HAR)
|
||||
//else if (map_type & MTex::MapType_RAYMIRR)
|
||||
//else if (map_type & MTex::MapType_TRANSLU)
|
||||
else if (map_type & MTex::MapType_AMB)
|
||||
texture_type = aiTextureType_AMBIENT;
|
||||
else if (map_type & MTex::MapType_DISPLACE)
|
||||
texture_type = aiTextureType_DISPLACEMENT;
|
||||
//else if (map_type & MTex::MapType_WARP)
|
||||
|
||||
out->AddProperty(&name,AI_MATKEY_TEXTURE(texture_type,
|
||||
conv_data.next_texture[texture_type]++));
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -624,6 +659,12 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
|||
ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp
|
||||
)
|
||||
{
|
||||
BlenderBMeshConverter BMeshConverter( mesh );
|
||||
if ( BMeshConverter.ContainsBMesh( ) )
|
||||
{
|
||||
mesh = BMeshConverter.TriangulateBMesh( );
|
||||
}
|
||||
|
||||
typedef std::pair<const int,size_t> MyPair;
|
||||
if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) {
|
||||
return;
|
||||
|
@ -958,19 +999,41 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* /*obj*/, const Camera* /*mesh*/, ConversionData& /*conv_data*/)
|
||||
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* camera, ConversionData& /*conv_data*/)
|
||||
{
|
||||
ScopeGuard<aiCamera> out(new aiCamera());
|
||||
|
||||
return NULL ; //out.dismiss();
|
||||
out->mName = obj->id.name+2;
|
||||
out->mPosition = aiVector3D(0.f, 0.f, 0.f);
|
||||
out->mUp = aiVector3D(0.f, 1.f, 0.f);
|
||||
out->mLookAt = aiVector3D(0.f, 0.f, -1.f);
|
||||
return out.dismiss();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* /*obj*/, const Lamp* /*mesh*/, ConversionData& /*conv_data*/)
|
||||
aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* lamp, ConversionData& conv_data)
|
||||
{
|
||||
ScopeGuard<aiLight> out(new aiLight());
|
||||
out->mName = obj->id.name+2;
|
||||
|
||||
return NULL ; //out.dismiss();
|
||||
switch (lamp->type)
|
||||
{
|
||||
case Lamp::Type_Local:
|
||||
out->mType = aiLightSource_POINT;
|
||||
break;
|
||||
case Lamp::Type_Sun:
|
||||
out->mType = aiLightSource_DIRECTIONAL;
|
||||
|
||||
// blender orients directional lights as facing toward -z
|
||||
out->mDirection = aiVector3D(0.f, 0.f, -1.f);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
|
||||
out->mColorSpecular = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
|
||||
out->mColorDiffuse = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
|
||||
return out.dismiss();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -598,6 +598,18 @@ struct Tex : ElemBase {
|
|||
,Type_VOXELDATA = 15
|
||||
};
|
||||
|
||||
enum ImageFlags {
|
||||
ImageFlags_INTERPOL = 1
|
||||
,ImageFlags_USEALPHA = 2
|
||||
,ImageFlags_MIPMAP = 4
|
||||
,ImageFlags_IMAROT = 16
|
||||
,ImageFlags_CALCALPHA = 32
|
||||
,ImageFlags_NORMALMAP = 2048
|
||||
,ImageFlags_GAUSS_MIP = 4096
|
||||
,ImageFlags_FILTER_MIN = 8192
|
||||
,ImageFlags_DERIVATIVEMAP = 16384
|
||||
};
|
||||
|
||||
ID id FAIL;
|
||||
// AnimData *adt;
|
||||
|
||||
|
@ -618,7 +630,8 @@ struct Tex : ElemBase {
|
|||
//short noisedepth, noisetype;
|
||||
//short noisebasis, noisebasis2;
|
||||
|
||||
//short imaflag, flag;
|
||||
//short flag;
|
||||
ImageFlags imaflag;
|
||||
Type type FAIL;
|
||||
//short stype;
|
||||
|
||||
|
@ -685,7 +698,25 @@ struct MTex : ElemBase {
|
|||
,BlendType_BLEND_COLOR = 13
|
||||
};
|
||||
|
||||
// short texco, mapto, maptoneg;
|
||||
enum MapType {
|
||||
MapType_COL = 1
|
||||
,MapType_NORM = 2
|
||||
,MapType_COLSPEC = 4
|
||||
,MapType_COLMIR = 8
|
||||
,MapType_REF = 16
|
||||
,MapType_SPEC = 32
|
||||
,MapType_EMIT = 64
|
||||
,MapType_ALPHA = 128
|
||||
,MapType_HAR = 256
|
||||
,MapType_RAYMIRR = 512
|
||||
,MapType_TRANSLU = 1024
|
||||
,MapType_AMB = 2048
|
||||
,MapType_DISPLACE = 4096
|
||||
,MapType_WARP = 8192
|
||||
};
|
||||
|
||||
// short texco, maptoneg;
|
||||
MapType mapto;
|
||||
|
||||
BlendType blendtype;
|
||||
boost::shared_ptr<Object> object;
|
||||
|
@ -705,7 +736,8 @@ struct MTex : ElemBase {
|
|||
|
||||
//float colfac, varfac;
|
||||
|
||||
//float norfac, dispfac, warpfac;
|
||||
float norfac;
|
||||
//float dispfac, warpfac;
|
||||
float colspecfac, mirrfac, alphafac;
|
||||
float difffac, specfac, emitfac, hardfac;
|
||||
//float raymirrfac, translfac, ambfac;
|
||||
|
|
|
@ -47,204 +47,204 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace Assimp {
|
||||
namespace Blender {
|
||||
|
||||
|
||||
template <> void Structure :: Convert<Object> (
|
||||
Object& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Group> (
|
||||
Group& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MTex> (
|
||||
MTex& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<TFace> (
|
||||
TFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<SubsurfModifierData> (
|
||||
SubsurfModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MFace> (
|
||||
MFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Lamp> (
|
||||
Lamp& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MDeformWeight> (
|
||||
MDeformWeight& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<PackedFile> (
|
||||
PackedFile& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Base> (
|
||||
Base& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MTFace> (
|
||||
MTFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Material> (
|
||||
Material& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MTexPoly> (
|
||||
MTexPoly& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Mesh> (
|
||||
Mesh& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MDeformVert> (
|
||||
MDeformVert& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<World> (
|
||||
World& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MLoopCol> (
|
||||
MLoopCol& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MVert> (
|
||||
MVert& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MEdge> (
|
||||
MEdge& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MLoopUV> (
|
||||
MLoopUV& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<GroupObject> (
|
||||
GroupObject& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<ListBase> (
|
||||
ListBase& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MLoop> (
|
||||
MLoop& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<ModifierData> (
|
||||
ModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<ID> (
|
||||
ID& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MCol> (
|
||||
MCol& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MPoly> (
|
||||
MPoly& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Scene> (
|
||||
Scene& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Library> (
|
||||
Library& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Tex> (
|
||||
Tex& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Camera> (
|
||||
Camera& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MirrorModifierData> (
|
||||
MirrorModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Image> (
|
||||
Image& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Object> (
|
||||
Object& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Group> (
|
||||
Group& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MTex> (
|
||||
MTex& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<TFace> (
|
||||
TFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<SubsurfModifierData> (
|
||||
SubsurfModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MFace> (
|
||||
MFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Lamp> (
|
||||
Lamp& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MDeformWeight> (
|
||||
MDeformWeight& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<PackedFile> (
|
||||
PackedFile& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Base> (
|
||||
Base& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MTFace> (
|
||||
MTFace& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Material> (
|
||||
Material& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MTexPoly> (
|
||||
MTexPoly& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Mesh> (
|
||||
Mesh& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MDeformVert> (
|
||||
MDeformVert& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<World> (
|
||||
World& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MLoopCol> (
|
||||
MLoopCol& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MVert> (
|
||||
MVert& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MEdge> (
|
||||
MEdge& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MLoopUV> (
|
||||
MLoopUV& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<GroupObject> (
|
||||
GroupObject& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<ListBase> (
|
||||
ListBase& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MLoop> (
|
||||
MLoop& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<ModifierData> (
|
||||
ModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<ID> (
|
||||
ID& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MCol> (
|
||||
MCol& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MPoly> (
|
||||
MPoly& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Scene> (
|
||||
Scene& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Library> (
|
||||
Library& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Tex> (
|
||||
Tex& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Camera> (
|
||||
Camera& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<MirrorModifierData> (
|
||||
MirrorModifierData& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
template <> void Structure :: Convert<Image> (
|
||||
Image& dest,
|
||||
const FileDatabase& db
|
||||
) const
|
||||
;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2013, assimp team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software 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.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
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
|
||||
OWNER 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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderTessellator.cpp
|
||||
* @brief A simple tessellation wrapper
|
||||
*/
|
||||
|
||||
#include "AssimpPCH.h"
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
|
||||
|
||||
#include "BlenderDNA.h"
|
||||
#include "BlenderScene.h"
|
||||
#include "BlenderBMesh.h"
|
||||
#include "BlenderTessellator.h"
|
||||
|
||||
#define BLEND_TESS_MAGIC ( 0x83ed9ac3 )
|
||||
|
||||
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: ";
|
||||
}
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
|
||||
#ifndef CALLBACK
|
||||
#define CALLBACK
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ):
|
||||
converter( &converter )
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderTessellatorGL::~BlenderTessellatorGL( )
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
|
||||
{
|
||||
AssertVertexCount( vertexCount );
|
||||
|
||||
std::vector< VertexGL > polyLoopGL;
|
||||
GenerateLoopVerts( polyLoopGL, polyLoop, vertexCount, vertices );
|
||||
|
||||
TessDataGL tessData;
|
||||
Tesssellate( polyLoopGL, tessData );
|
||||
|
||||
TriangulateDrawCalls( tessData );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::AssertVertexCount( int vertexCount )
|
||||
{
|
||||
if ( vertexCount <= 4 )
|
||||
{
|
||||
ThrowException( "Expected more than 4 vertices for tessellation" );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::GenerateLoopVerts( std::vector< VertexGL >& polyLoopGL, const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
|
||||
{
|
||||
for ( int i = 0; i < vertexCount; ++i )
|
||||
{
|
||||
const MLoop& loopItem = polyLoop[ i ];
|
||||
const MVert& vertex = vertices[ loopItem.v ];
|
||||
polyLoopGL.push_back( VertexGL( vertex.co[ 0 ], vertex.co[ 1 ], vertex.co[ 2 ], loopItem.v, BLEND_TESS_MAGIC ) );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::Tesssellate( std::vector< VertexGL >& polyLoopGL, TessDataGL& tessData )
|
||||
{
|
||||
GLUtesselator* tessellator = gluNewTess( );
|
||||
gluTessCallback( tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateBegin ) );
|
||||
gluTessCallback( tessellator, GLU_TESS_END_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEnd ) );
|
||||
gluTessCallback( tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateVertex ) );
|
||||
gluTessCallback( tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateCombine ) );
|
||||
gluTessCallback( tessellator, GLU_TESS_EDGE_FLAG_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEdgeFlag ) );
|
||||
gluTessCallback( tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateError ) );
|
||||
gluTessProperty( tessellator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
|
||||
|
||||
gluTessBeginPolygon( tessellator, &tessData );
|
||||
gluTessBeginContour( tessellator );
|
||||
|
||||
for ( unsigned int i = 0; i < polyLoopGL.size( ); ++i )
|
||||
{
|
||||
gluTessVertex( tessellator, reinterpret_cast< GLdouble* >( &polyLoopGL[ i ] ), &polyLoopGL[ i ] );
|
||||
}
|
||||
|
||||
gluTessEndContour( tessellator );
|
||||
gluTessEndPolygon( tessellator );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TriangulateDrawCalls( const TessDataGL& tessData )
|
||||
{
|
||||
// NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically
|
||||
// need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case
|
||||
// GLU tessellate changes or tristrips and fans are wanted.
|
||||
// See: http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml
|
||||
for ( unsigned int i = 0; i < tessData.drawCalls.size( ); ++i )
|
||||
{
|
||||
const DrawCallGL& drawCallGL = tessData.drawCalls[ i ];
|
||||
const VertexGL* vertices = &tessData.vertices[ drawCallGL.baseVertex ];
|
||||
if ( drawCallGL.drawMode == GL_TRIANGLES )
|
||||
{
|
||||
MakeFacesFromTris( vertices, drawCallGL.vertexCount );
|
||||
}
|
||||
else if ( drawCallGL.drawMode == GL_TRIANGLE_STRIP )
|
||||
{
|
||||
MakeFacesFromTriStrip( vertices, drawCallGL.vertexCount );
|
||||
}
|
||||
else if ( drawCallGL.drawMode == GL_TRIANGLE_FAN )
|
||||
{
|
||||
MakeFacesFromTriFan( vertices, drawCallGL.vertexCount );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vertexCount )
|
||||
{
|
||||
int triangleCount = vertexCount / 3;
|
||||
for ( int i = 0; i < triangleCount; ++i )
|
||||
{
|
||||
int vertexBase = i * 3;
|
||||
converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int vertexCount )
|
||||
{
|
||||
int triangleCount = vertexCount - 2;
|
||||
for ( int i = 0; i < triangleCount; ++i )
|
||||
{
|
||||
int vertexBase = i;
|
||||
converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::MakeFacesFromTriFan( const VertexGL* vertices, int vertexCount )
|
||||
{
|
||||
int triangleCount = vertexCount - 2;
|
||||
for ( int i = 0; i < triangleCount; ++i )
|
||||
{
|
||||
int vertexBase = i;
|
||||
converter->AddFace( vertices[ 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateBegin( GLenum drawModeGL, void* userData )
|
||||
{
|
||||
TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
|
||||
tessData.drawCalls.push_back( DrawCallGL( drawModeGL, tessData.vertices.size( ) ) );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateEnd( void* )
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateVertex( const void* vtxData, void* userData )
|
||||
{
|
||||
TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
|
||||
|
||||
const VertexGL& vertex = *reinterpret_cast< const VertexGL* >( vtxData );
|
||||
if ( vertex.magic != BLEND_TESS_MAGIC )
|
||||
{
|
||||
ThrowException( "Point returned by GLU Tessellate was probably not one of ours. This indicates we need a new way to store vertex information" );
|
||||
}
|
||||
tessData.vertices.push_back( vertex );
|
||||
if ( tessData.drawCalls.size( ) == 0 )
|
||||
{
|
||||
ThrowException( "\"Vertex\" callback received before \"Begin\"" );
|
||||
}
|
||||
++( tessData.drawCalls.back( ).vertexCount );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData )
|
||||
{
|
||||
ThrowException( "Intersected polygon loops are not yet supported" );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateEdgeFlag( GLboolean, void* )
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
|
||||
{
|
||||
ThrowException( reinterpret_cast< const char* >( gluErrorString( errorCode ) ) );
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
|
||||
#if ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: ";
|
||||
}
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Blender;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderTessellatorP2T::BlenderTessellatorP2T( BlenderBMeshConverter& converter ):
|
||||
converter( &converter )
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
BlenderTessellatorP2T::~BlenderTessellatorP2T( )
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
|
||||
{
|
||||
AssertVertexCount( vertexCount );
|
||||
|
||||
// NOTE - We have to hope that points in a Blender polygon are roughly on the same plane.
|
||||
// There may be some triangulation artifacts if they are wildly different.
|
||||
|
||||
std::vector< PointP2T > points;
|
||||
Copy3DVertices( polyLoop, vertexCount, vertices, points );
|
||||
|
||||
PlaneP2T plane = FindLLSQPlane( points );
|
||||
|
||||
aiMatrix4x4 transform = GeneratePointTransformMatrix( plane );
|
||||
|
||||
TransformAndFlattenVectices( transform, points );
|
||||
|
||||
std::vector< p2t::Point* > pointRefs;
|
||||
ReferencePoints( points, pointRefs );
|
||||
|
||||
p2t::CDT cdt( pointRefs );
|
||||
|
||||
cdt.Triangulate( );
|
||||
std::vector< p2t::Triangle* > triangles = cdt.GetTriangles( );
|
||||
|
||||
MakeFacesFromTriangles( triangles );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::AssertVertexCount( int vertexCount )
|
||||
{
|
||||
if ( vertexCount <= 4 )
|
||||
{
|
||||
ThrowException( "Expected more than 4 vertices for tessellation" );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices, std::vector< PointP2T >& points ) const
|
||||
{
|
||||
points.resize( vertexCount );
|
||||
for ( int i = 0; i < vertexCount; ++i )
|
||||
{
|
||||
const MLoop& loop = polyLoop[ i ];
|
||||
const MVert& vert = vertices[ loop.v ];
|
||||
|
||||
PointP2T& point = points[ i ];
|
||||
point.point3D.Set( vert.co[ 0 ], vert.co[ 1 ], vert.co[ 2 ] );
|
||||
point.index = loop.v;
|
||||
point.magic = BLEND_TESS_MAGIC;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const
|
||||
{
|
||||
aiVector3D sideA( 1.0f, 0.0f, 0.0f );
|
||||
if ( fabs( plane.normal * sideA ) > 0.999f )
|
||||
{
|
||||
sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
|
||||
}
|
||||
|
||||
aiVector3D sideB( plane.normal ^ sideA );
|
||||
sideB.Normalize( );
|
||||
sideA = sideB ^ plane.normal;
|
||||
|
||||
aiMatrix4x4 result;
|
||||
result.a1 = sideA.x;
|
||||
result.a2 = sideA.y;
|
||||
result.a3 = sideA.z;
|
||||
result.b1 = sideB.x;
|
||||
result.b2 = sideB.y;
|
||||
result.b3 = sideB.z;
|
||||
result.c1 = plane.normal.x;
|
||||
result.c2 = plane.normal.y;
|
||||
result.c3 = plane.normal.z;
|
||||
result.a4 = plane.centre.x;
|
||||
result.b4 = plane.centre.y;
|
||||
result.c4 = plane.centre.z;
|
||||
result.Inverse( );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const
|
||||
{
|
||||
for ( unsigned int i = 0; i < vertices.size( ); ++i )
|
||||
{
|
||||
PointP2T& point = vertices[ i ];
|
||||
point.point3D = transform * point.point3D;
|
||||
point.point2D.set( point.point3D.y, point.point3D.z );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const
|
||||
{
|
||||
pointRefs.resize( points.size( ) );
|
||||
for ( unsigned int i = 0; i < points.size( ); ++i )
|
||||
{
|
||||
pointRefs[ i ] = &points[ i ].point2D;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Yes this is filthy... but we have no choice
|
||||
#define OffsetOf( Class, Member ) ( static_cast< unsigned int >( \
|
||||
reinterpret_cast<uint8_t*>(&( reinterpret_cast< Class* >( NULL )->*( &Class::Member ) )) - \
|
||||
static_cast<uint8_t*>(NULL) ) )
|
||||
|
||||
inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& point ) const
|
||||
{
|
||||
unsigned int pointOffset = OffsetOf( PointP2T, point2D );
|
||||
PointP2T& pointStruct = *reinterpret_cast< PointP2T* >( reinterpret_cast< char* >( &point ) - pointOffset );
|
||||
if ( pointStruct.magic != BLEND_TESS_MAGIC )
|
||||
{
|
||||
ThrowException( "Point returned by poly2tri was probably not one of ours. This indicates we need a new way to store vertex information" );
|
||||
}
|
||||
return pointStruct;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BlenderTessellatorP2T::MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const
|
||||
{
|
||||
for ( unsigned int i = 0; i < triangles.size( ); ++i )
|
||||
{
|
||||
p2t::Triangle& Triangle = *triangles[ i ];
|
||||
|
||||
PointP2T& pointA = GetActualPointStructure( *Triangle.GetPoint( 0 ) );
|
||||
PointP2T& pointB = GetActualPointStructure( *Triangle.GetPoint( 1 ) );
|
||||
PointP2T& pointC = GetActualPointStructure( *Triangle.GetPoint( 2 ) );
|
||||
|
||||
converter->AddFace( pointA.index, pointB.index, pointC.index );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
inline float p2tMax( float a, float b )
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
|
||||
float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) const
|
||||
{
|
||||
float result = 0.0f;
|
||||
|
||||
for ( int x = 0; x < 3; ++x )
|
||||
{
|
||||
for ( int y = 0; y < 3; ++y )
|
||||
{
|
||||
result = p2tMax( fabs( mtx[ x ][ y ] ), result );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Aparently Assimp doesn't have matrix scaling
|
||||
aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const
|
||||
{
|
||||
aiMatrix3x3 result;
|
||||
|
||||
for ( int x = 0; x < 3; ++x )
|
||||
{
|
||||
for ( int y = 0; y < 3; ++y )
|
||||
{
|
||||
result[ x ][ y ] = mtx[ x ][ y ] * scale;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
|
||||
aiVector3D BlenderTessellatorP2T::GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const
|
||||
{
|
||||
float scale = FindLargestMatrixElem( mtx );
|
||||
aiMatrix3x3 mc = ScaleMatrix( mtx, 1.0f / scale );
|
||||
mc = mc * mc * mc;
|
||||
|
||||
aiVector3D v( 1.0f );
|
||||
aiVector3D lastV = v;
|
||||
for ( int i = 0; i < 100; ++i )
|
||||
{
|
||||
v = mc * v;
|
||||
v.Normalize( );
|
||||
if ( ( v - lastV ).SquareLength( ) < 1e-16f )
|
||||
{
|
||||
break;
|
||||
}
|
||||
lastV = v;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
|
||||
PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& points ) const
|
||||
{
|
||||
PlaneP2T result;
|
||||
|
||||
aiVector3D sum( 0.0f );
|
||||
for ( unsigned int i = 0; i < points.size( ); ++i )
|
||||
{
|
||||
sum += points[ i ].point3D;
|
||||
}
|
||||
result.centre = sum * ( 1.0f / points.size( ) );
|
||||
|
||||
float sumXX = 0.0f;
|
||||
float sumXY = 0.0f;
|
||||
float sumXZ = 0.0f;
|
||||
float sumYY = 0.0f;
|
||||
float sumYZ = 0.0f;
|
||||
float sumZZ = 0.0f;
|
||||
for ( unsigned int i = 0; i < points.size( ); ++i )
|
||||
{
|
||||
aiVector3D offset = points[ i ].point3D - result.centre;
|
||||
sumXX += offset.x * offset.x;
|
||||
sumXY += offset.x * offset.y;
|
||||
sumXZ += offset.x * offset.z;
|
||||
sumYY += offset.y * offset.y;
|
||||
sumYZ += offset.y * offset.z;
|
||||
sumZZ += offset.z * offset.z;
|
||||
}
|
||||
|
||||
aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ );
|
||||
|
||||
float det = mtx.Determinant( );
|
||||
if ( det == 0.0f )
|
||||
{
|
||||
result.normal = aiVector3D( 0.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
aiMatrix3x3 invMtx = mtx;
|
||||
invMtx.Inverse( );
|
||||
result.normal = GetEigenVectorFromLargestEigenValue( invMtx );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2013, assimp team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software 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.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
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
|
||||
OWNER 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.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @file BlenderTessellator.h
|
||||
* @brief A simple tessellation wrapper
|
||||
*/
|
||||
#ifndef INCLUDED_AI_BLEND_TESSELLATOR_H
|
||||
#define INCLUDED_AI_BLEND_TESSELLATOR_H
|
||||
|
||||
// Use these to toggle between GLU Tessellate or poly2tri
|
||||
// Note (acg) keep GLU Tesselate disabled by default - if it is turned on,
|
||||
// assimp needs to be linked against GLU, which is currently not yet
|
||||
// made configurable in CMake and potentially not wanted by most users
|
||||
// as it requires a Gl environment.
|
||||
#ifndef ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
# define ASSIMP_BLEND_WITH_GLU_TESSELLATE 0
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
# define ASSIMP_BLEND_WITH_POLY_2_TRI 1
|
||||
#endif
|
||||
|
||||
#include "LogAux.h"
|
||||
|
||||
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
|
||||
#if defined( WIN32 ) || defined( _WIN32 ) || defined( _MSC_VER )
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <GL/glu.h>
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
class BlenderBMeshConverter;
|
||||
|
||||
// TinyFormatter.h
|
||||
namespace Formatter
|
||||
{
|
||||
template < typename T,typename TR, typename A > class basic_formatter;
|
||||
typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
|
||||
}
|
||||
|
||||
// BlenderScene.h
|
||||
namespace Blender
|
||||
{
|
||||
struct MLoop;
|
||||
struct MVert;
|
||||
|
||||
struct VertexGL
|
||||
{
|
||||
GLdouble X;
|
||||
GLdouble Y;
|
||||
GLdouble Z;
|
||||
int index;
|
||||
int magic;
|
||||
|
||||
VertexGL( GLdouble X, GLdouble Y, GLdouble Z, int index, int magic ): X( X ), Y( Y ), Z( Z ), index( index ), magic( magic ) { }
|
||||
};
|
||||
|
||||
struct DrawCallGL
|
||||
{
|
||||
GLenum drawMode;
|
||||
int baseVertex;
|
||||
int vertexCount;
|
||||
|
||||
DrawCallGL( GLenum drawMode, int baseVertex ): drawMode( drawMode ), baseVertex( baseVertex ), vertexCount( 0 ) { }
|
||||
};
|
||||
|
||||
struct TessDataGL
|
||||
{
|
||||
std::vector< DrawCallGL > drawCalls;
|
||||
std::vector< VertexGL > vertices;
|
||||
};
|
||||
}
|
||||
|
||||
class BlenderTessellatorGL: public LogFunctions< BlenderTessellatorGL >
|
||||
{
|
||||
public:
|
||||
BlenderTessellatorGL( BlenderBMeshConverter& converter );
|
||||
~BlenderTessellatorGL( );
|
||||
|
||||
void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
|
||||
|
||||
private:
|
||||
void AssertVertexCount( int vertexCount );
|
||||
void GenerateLoopVerts( std::vector< Blender::VertexGL >& polyLoopGL, const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
|
||||
void Tesssellate( std::vector< Blender::VertexGL >& polyLoopGL, Blender::TessDataGL& tessData );
|
||||
void TriangulateDrawCalls( const Blender::TessDataGL& tessData );
|
||||
void MakeFacesFromTris( const Blender::VertexGL* vertices, int vertexCount );
|
||||
void MakeFacesFromTriStrip( const Blender::VertexGL* vertices, int vertexCount );
|
||||
void MakeFacesFromTriFan( const Blender::VertexGL* vertices, int vertexCount );
|
||||
|
||||
static void TessellateBegin( GLenum drawModeGL, void* userData );
|
||||
static void TessellateEnd( void* userData );
|
||||
static void TessellateVertex( const void* vtxData, void* userData );
|
||||
static void TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData );
|
||||
static void TessellateEdgeFlag( GLboolean edgeFlag, void* userData );
|
||||
static void TessellateError( GLenum errorCode, void* userData );
|
||||
|
||||
BlenderBMeshConverter* converter;
|
||||
};
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
|
||||
|
||||
#if ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
|
||||
#include "../contrib/poly2tri/poly2tri/poly2tri.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
class BlenderBMeshConverter;
|
||||
|
||||
// TinyFormatter.h
|
||||
namespace Formatter
|
||||
{
|
||||
template < typename T,typename TR, typename A > class basic_formatter;
|
||||
typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
|
||||
}
|
||||
|
||||
// BlenderScene.h
|
||||
namespace Blender
|
||||
{
|
||||
struct MLoop;
|
||||
struct MVert;
|
||||
|
||||
struct PointP2T
|
||||
{
|
||||
aiVector3D point3D;
|
||||
p2t::Point point2D;
|
||||
int magic;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct PlaneP2T
|
||||
{
|
||||
aiVector3D centre;
|
||||
aiVector3D normal;
|
||||
};
|
||||
}
|
||||
|
||||
class BlenderTessellatorP2T: public LogFunctions< BlenderTessellatorP2T >
|
||||
{
|
||||
public:
|
||||
BlenderTessellatorP2T( BlenderBMeshConverter& converter );
|
||||
~BlenderTessellatorP2T( );
|
||||
|
||||
void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
|
||||
|
||||
private:
|
||||
void AssertVertexCount( int vertexCount );
|
||||
void Copy3DVertices( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices, std::vector< Blender::PointP2T >& targetVertices ) const;
|
||||
aiMatrix4x4 GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const;
|
||||
void TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const;
|
||||
void ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const;
|
||||
inline Blender::PointP2T& GetActualPointStructure( p2t::Point& point ) const;
|
||||
void MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const;
|
||||
|
||||
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
|
||||
float FindLargestMatrixElem( const aiMatrix3x3& mtx ) const;
|
||||
aiMatrix3x3 ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const;
|
||||
aiVector3D GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const;
|
||||
Blender::PlaneP2T FindLLSQPlane( const std::vector< Blender::PointP2T >& points ) const;
|
||||
|
||||
BlenderBMeshConverter* converter;
|
||||
};
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BLEND_WITH_POLY_2_TRI
|
||||
|
||||
#endif // INCLUDED_AI_BLEND_TESSELLATOR_H
|
|
@ -88,9 +88,9 @@ public:
|
|||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
virtual size_t Read(void* pvBuffer,
|
||||
size_t pSize,
|
||||
size_t pCount)
|
||||
virtual size_t Read( void *,
|
||||
size_t,
|
||||
size_t )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#ifndef __AI_BOOST_WORKAROUND_LEXICAL_CAST
|
||||
#define __AI_BOOST_WORKAROUND_LEXICAL_CAST
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
|
|
|
@ -362,6 +362,10 @@ SET(BLENDER_SRCS
|
|||
BlenderIntermediate.h
|
||||
BlenderModifier.h
|
||||
BlenderModifier.cpp
|
||||
BlenderBMesh.h
|
||||
BlenderBMesh.cpp
|
||||
BlenderTessellator.h
|
||||
BlenderTessellator.cpp
|
||||
)
|
||||
SOURCE_GROUP( BLENDER FILES ${BLENDER_SRCS})
|
||||
|
||||
|
|
|
@ -235,9 +235,13 @@ void ColladaExporter::WriteMaterials()
|
|||
if( mat->Get( AI_MATKEY_NAME, name) != aiReturn_SUCCESS )
|
||||
name = "mat";
|
||||
materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str();
|
||||
for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it )
|
||||
if( !isalnum( *it) )
|
||||
for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
|
||||
// isalnum on MSVC asserts for code points in [0,255]. Thus prevent unwanted promotion
|
||||
// of char to signed int and take the unsigned char value.
|
||||
if( !isalnum( static_cast<uint8_t>(*it) ) ) {
|
||||
*it = '_';
|
||||
}
|
||||
}
|
||||
|
||||
ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT);
|
||||
if( !materials[a].ambient.texture.empty() ) numTextures++;
|
||||
|
|
|
@ -321,6 +321,8 @@ struct Mesh
|
|||
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||
mNumUVComponents[i] = 2;
|
||||
}
|
||||
|
||||
std::string mName;
|
||||
|
||||
// just to check if there's some sophisticated addressing involved...
|
||||
// which we don't support, and therefore should warn about.
|
||||
|
|
|
@ -73,7 +73,7 @@ static const aiImporterDesc desc = {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
ColladaLoader::ColladaLoader()
|
||||
: noSkeletonMesh()
|
||||
: noSkeletonMesh(), ignoreUpDirection(false)
|
||||
{}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -108,6 +108,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
|
|||
void ColladaLoader::SetupProperties(const Importer* pImp)
|
||||
{
|
||||
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
|
||||
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -160,21 +161,21 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
|||
0, parser.mUnitSize, 0, 0,
|
||||
0, 0, parser.mUnitSize, 0,
|
||||
0, 0, 0, 1);
|
||||
|
||||
if( !ignoreUpDirection ) {
|
||||
// Convert to Y_UP, if different orientation
|
||||
if( parser.mUpDirection == ColladaParser::UP_X)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
0, -1, 0, 0,
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1);
|
||||
else if( parser.mUpDirection == ColladaParser::UP_Z)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, 0, 1);
|
||||
|
||||
if( parser.mUpDirection == ColladaParser::UP_X)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
0, -1, 0, 0,
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1);
|
||||
else if( parser.mUpDirection == ColladaParser::UP_Z)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
// store all meshes
|
||||
StoreSceneMeshes( pScene);
|
||||
|
||||
|
@ -520,7 +521,10 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
|||
|
||||
// assign the material index
|
||||
dstMesh->mMaterialIndex = matIdx;
|
||||
dstMesh->mName = mid.mMeshOrController;
|
||||
if(dstMesh->mName.length == 0)
|
||||
{
|
||||
dstMesh->mName = mid.mMeshOrController;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -540,6 +544,8 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
|
|||
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace)
|
||||
{
|
||||
aiMesh* dstMesh = new aiMesh;
|
||||
|
||||
dstMesh->mName = pSrcMesh->mName;
|
||||
|
||||
// count the vertices addressed by its faces
|
||||
const size_t numVertices = std::accumulate( pSrcMesh->mFaceSize.begin() + pStartFace,
|
||||
|
|
|
@ -234,6 +234,7 @@ protected:
|
|||
std::vector<aiAnimation*> mAnims;
|
||||
|
||||
bool noSkeletonMesh;
|
||||
bool ignoreUpDirection;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -1492,6 +1492,13 @@ void ColladaParser::ReadGeometryLibrary()
|
|||
// create a mesh and store it in the library under its ID
|
||||
Mesh* mesh = new Mesh;
|
||||
mMeshLibrary[id] = mesh;
|
||||
|
||||
// read the mesh name if it exists
|
||||
const int nameIndex = TestAttribute("name");
|
||||
if(nameIndex != -1)
|
||||
{
|
||||
mesh->mName = mReader->getAttributeValue(nameIndex);
|
||||
}
|
||||
|
||||
// read on from there
|
||||
ReadGeometry( mesh);
|
||||
|
|
|
@ -110,7 +110,14 @@ size_t DefaultIOStream::FileSize() const
|
|||
|
||||
if (SIZE_MAX == cachedSize) {
|
||||
|
||||
// TODO: Is that really faster if we're already owning a handle to the file?
|
||||
// Although fseek/ftell would allow us to reuse the exising file handle here,
|
||||
// it is generally unsafe because:
|
||||
// - For binary streams, it is not technically well-defined
|
||||
// - For text files the results are meaningless
|
||||
// That's why we use the safer variant fstat here.
|
||||
//
|
||||
// See here for details:
|
||||
// https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file
|
||||
#if defined _WIN32 && !defined __GNUC__
|
||||
struct __stat64 fileStat;
|
||||
int err = _stat64( mFilename.c_str(), &fileStat );
|
||||
|
|
|
@ -60,6 +60,7 @@ Here we implement only the C++ interface (Assimp::Exporter).
|
|||
#include "BaseProcess.h"
|
||||
#include "Importer.h" // need this for GetPostProcessingStepInstanceList()
|
||||
|
||||
#include "JoinVerticesProcess.h"
|
||||
#include "MakeVerboseFormat.h"
|
||||
#include "ConvertToLHProcess.h"
|
||||
|
||||
|
@ -73,6 +74,7 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
|
|||
void ExportSceneCollada(const char*,IOSystem*, const aiScene*);
|
||||
void ExportSceneObj(const char*,IOSystem*, const aiScene*);
|
||||
void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
|
||||
void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
|
||||
void ExportScenePly(const char*,IOSystem*, const aiScene*);
|
||||
void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
|
||||
|
||||
|
@ -86,13 +88,16 @@ Exporter::ExportFormatEntry gExporters[] =
|
|||
|
||||
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
|
||||
Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj,
|
||||
aiProcess_GenNormals | aiProcess_PreTransformVertices),
|
||||
aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
|
||||
Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL,
|
||||
aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
|
||||
),
|
||||
Exporter::ExportFormatEntry( "stlb", "Stereolithography(binary)", "stlb" , &ExportSceneSTLBinary,
|
||||
aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
|
||||
),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_PLY_EXPORTER
|
||||
|
@ -197,7 +202,7 @@ bool Exporter :: IsDefaultIOHandler() const
|
|||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing )
|
||||
const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int )
|
||||
{
|
||||
if (pimpl->blob) {
|
||||
delete pimpl->blob;
|
||||
|
@ -222,11 +227,47 @@ const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const
|
|||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool IsVerboseFormat(const aiMesh* mesh)
|
||||
{
|
||||
// avoid slow vector<bool> specialization
|
||||
std::vector<unsigned int> seen(mesh->mNumVertices,0);
|
||||
for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
|
||||
const aiFace& f = mesh->mFaces[i];
|
||||
for(unsigned int j = 0; j < f.mNumIndices; ++j) {
|
||||
if(++seen[f.mIndices[j]] == 2) {
|
||||
// found a duplicate index
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool IsVerboseFormat(const aiScene* pScene)
|
||||
{
|
||||
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
if(!IsVerboseFormat(pScene->mMeshes[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing )
|
||||
{
|
||||
ASSIMP_BEGIN_EXCEPTION_REGION();
|
||||
|
||||
// when they create scenes from scratch, users will likely create them not in verbose
|
||||
// format. They will likely not be aware that there is a flag in the scene to indicate
|
||||
// this, however. To avoid surprises and bug reports, we check for duplicates in
|
||||
// meshes upfront.
|
||||
const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);
|
||||
|
||||
pimpl->mError = "";
|
||||
for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
|
||||
const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
|
||||
|
@ -248,19 +289,21 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
|||
const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
|
||||
|
||||
// Erase all pp steps that were already applied to this scene
|
||||
unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv
|
||||
const unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv && !priv->mIsCopy
|
||||
? (priv->mPPStepsApplied & ~nonIdempotentSteps)
|
||||
: 0u);
|
||||
|
||||
// If no extra postprocessing was specified, and we obtained this scene from an
|
||||
// Assimp importer, apply the reverse steps automatically.
|
||||
if (!pPreprocessing && priv) {
|
||||
pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
|
||||
}
|
||||
// TODO: either drop this, or document it. Otherwise it is just a bad surprise.
|
||||
//if (!pPreprocessing && priv) {
|
||||
// pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
|
||||
//}
|
||||
|
||||
// If the input scene is not in verbose format, but there is at least postprocessing step that relies on it,
|
||||
// we need to run the MakeVerboseFormat step first.
|
||||
if (scenecopy->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
|
||||
bool must_join_again = false;
|
||||
if (!is_verbose_format) {
|
||||
|
||||
bool verbosify = false;
|
||||
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
|
||||
|
@ -277,6 +320,10 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
|||
|
||||
MakeVerboseFormatProcess proc;
|
||||
proc.Execute(scenecopy.get());
|
||||
|
||||
if(!(exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
|
||||
must_join_again = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,6 +368,11 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const
|
|||
privOut->mPPStepsApplied |= pp;
|
||||
}
|
||||
|
||||
if(must_join_again) {
|
||||
JoinVerticesProcess proc;
|
||||
proc.Execute(scenecopy.get());
|
||||
}
|
||||
|
||||
exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
|
||||
}
|
||||
catch (DeadlyExportError& err) {
|
||||
|
|
|
@ -232,7 +232,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
|
|||
|
||||
// compute length based on type and check against the stored value
|
||||
if(encoding == 0) {
|
||||
uint32_t stride;
|
||||
uint32_t stride = 0;
|
||||
switch(type)
|
||||
{
|
||||
case 'f':
|
||||
|
@ -248,6 +248,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
|
|||
default:
|
||||
ai_assert(false);
|
||||
};
|
||||
ai_assert(stride > 0);
|
||||
if(length * stride != comp_len) {
|
||||
TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor);
|
||||
}
|
||||
|
|
|
@ -547,6 +547,10 @@ private:
|
|||
default:
|
||||
ai_assert(false);
|
||||
}
|
||||
|
||||
ai_assert((order[0] >= 0) && (order[0] <= 2));
|
||||
ai_assert((order[1] >= 0) && (order[1] <= 2));
|
||||
ai_assert((order[2] >= 0) && (order[2] <= 2));
|
||||
|
||||
if(!is_id[order[0]]) {
|
||||
out = temp[order[0]];
|
||||
|
@ -1844,7 +1848,7 @@ private:
|
|||
}}
|
||||
#endif
|
||||
|
||||
const AnimationCurveNode* curve_node;
|
||||
const AnimationCurveNode* curve_node = NULL;
|
||||
BOOST_FOREACH(const AnimationCurveNode* node, curves) {
|
||||
ai_assert(node);
|
||||
|
||||
|
|
|
@ -290,14 +290,19 @@ void Document::ReadHeader()
|
|||
const Scope& shead = *ehead->Compound();
|
||||
fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
|
||||
|
||||
|
||||
if(fbxVersion < 7200 || fbxVersion > 7300) {
|
||||
// while we maye have some success with newer files, we don't support
|
||||
// the older 6.n fbx format
|
||||
if(fbxVersion < 7100) {
|
||||
DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");
|
||||
}
|
||||
if(fbxVersion > 7300) {
|
||||
if(Settings().strictMode) {
|
||||
DOMError("unsupported format version, supported are only FBX 2012 and FBX 2013"\
|
||||
" in ASCII format (turn off strict mode to try anyhow) ");
|
||||
DOMError("unsupported, newer format version, supported are only FBX 2011, FBX 2012 and FBX 2013"
|
||||
" (turn off strict mode to try anyhow) ");
|
||||
}
|
||||
else {
|
||||
DOMWarning("unsupported format version, supported are only FBX 2012 and FBX 2013, trying to read it nevertheless");
|
||||
DOMWarning("unsupported, newer format version, supported are only FBX 2011, FBX 2012 and FBX 2013,"
|
||||
" trying to read it nevertheless");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ namespace Util {
|
|||
|
||||
|
||||
/* DOM/Parse error reporting - does not return */
|
||||
void DOMError(const std::string& message, const Token& token);
|
||||
void DOMError(const std::string& message, const Element* element = NULL);
|
||||
AI_WONT_RETURN void DOMError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
|
||||
AI_WONT_RETURN void DOMError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
// does return
|
||||
void DOMWarning(const std::string& message, const Token& token);
|
||||
|
|
|
@ -512,7 +512,7 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
|
|||
ai_assert(data + comp_len == end);
|
||||
|
||||
// determine the length of the uncompressed data by looking at the type signature
|
||||
uint32_t stride;
|
||||
uint32_t stride = 0;
|
||||
switch(type)
|
||||
{
|
||||
case 'f':
|
||||
|
|
|
@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "AssimpPCH.h"
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
|
||||
#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER
|
||||
|
||||
#include "IRRMeshLoader.h"
|
||||
#include "ParsingUtils.h"
|
||||
|
@ -512,4 +512,4 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
|
|||
AI_DEBUG_INVALIDATE_PTR(reader);
|
||||
}
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
|
||||
#endif // !! ASSIMP_BUILD_NO_IRRMESH_IMPORTER
|
||||
|
|
|
@ -45,7 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "AssimpPCH.h"
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER
|
||||
//This section should be excluded only if both the Irrlicht AND the Irrlicht Mesh importers were omitted.
|
||||
#if !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))
|
||||
|
||||
#include "IRRShared.h"
|
||||
#include "ParsingUtils.h"
|
||||
|
@ -497,4 +498,4 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
|
|||
return mat;
|
||||
}
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
|
||||
#endif // !(defined(ASSIMP_BUILD_NO_IRR_IMPORTER) && defined(ASSIMP_BUILD_NO_IRRMESH_IMPORTER))
|
||||
|
|
|
@ -1296,6 +1296,11 @@ void LWOImporter::LoadLWO2File()
|
|||
uint8_t* const next = mFileBuffer+head->length;
|
||||
unsigned int iUnnamed = 0;
|
||||
|
||||
if(!head->length) {
|
||||
mFileBuffer = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (head->type)
|
||||
{
|
||||
// new layer
|
||||
|
|
|
@ -167,19 +167,21 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
// The older LWOB format does not use indirect references to clips.
|
||||
// The file name of a texture is directly specified in the tex chunk.
|
||||
if (mIsLWO2) {
|
||||
// find the corresponding clip
|
||||
ClipList::iterator clip = mClips.begin();
|
||||
// find the corresponding clip (take the last one if multiple
|
||||
// share the same index)
|
||||
ClipList::iterator end = mClips.end(), candidate = end;
|
||||
temp = (*it).mClipIdx;
|
||||
for (ClipList::iterator end = mClips.end(); clip != end; ++clip) {
|
||||
if ((*clip).idx == temp)
|
||||
break;
|
||||
for (ClipList::iterator clip = mClips.begin(); clip != end; ++clip) {
|
||||
if ((*clip).idx == temp) {
|
||||
candidate = clip;
|
||||
}
|
||||
|
||||
}
|
||||
if (mClips.end() == clip) {
|
||||
if (candidate == end) {
|
||||
DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
|
||||
temp = 0;
|
||||
|
||||
// fixme: appearently some LWO files shipping with Doom3 don't
|
||||
// fixme: apparently some LWO files shipping with Doom3 don't
|
||||
// have clips at all ... check whether that's true or whether
|
||||
// it's a bug in the loader.
|
||||
|
||||
|
@ -188,16 +190,16 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
|
|||
//continue;
|
||||
}
|
||||
else {
|
||||
if (Clip::UNSUPPORTED == (*clip).type) {
|
||||
if (Clip::UNSUPPORTED == (*candidate).type) {
|
||||
DefaultLogger::get()->error("LWO2: Clip type is not supported");
|
||||
continue;
|
||||
}
|
||||
AdjustTexturePath((*clip).path);
|
||||
s.Set((*clip).path);
|
||||
AdjustTexturePath((*candidate).path);
|
||||
s.Set((*candidate).path);
|
||||
|
||||
// Additional image settings
|
||||
int flags = 0;
|
||||
if ((*clip).negate) {
|
||||
if ((*candidate).negate) {
|
||||
flags |= aiTextureFlags_Invert;
|
||||
}
|
||||
pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur));
|
||||
|
|
|
@ -563,7 +563,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
|
|||
}
|
||||
|
||||
// ... add dummy nodes under a single root, each holding a reference to one
|
||||
// mesh. If we didn't do this, we'd loose the group name.
|
||||
// mesh. If we didn't do this, we'd lose the group name.
|
||||
aiNode* rt = pScene->mRootNode = new aiNode("<MS3DRoot>");
|
||||
|
||||
#ifdef ASSIMP_BUILD_MS3D_ONE_NODE_PER_MESH
|
||||
|
|
|
@ -102,7 +102,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
|
|||
}
|
||||
|
||||
// data is given in floats, simply copy it
|
||||
unsigned int iWrite;
|
||||
unsigned int iWrite = 0;
|
||||
if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) {
|
||||
iWrite = prop->mDataLength / sizeof(float);
|
||||
if (pMax) {
|
||||
|
@ -175,7 +175,7 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
|
|||
}
|
||||
|
||||
// data is given in ints, simply copy it
|
||||
unsigned int iWrite;
|
||||
unsigned int iWrite = 0;
|
||||
if( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) {
|
||||
iWrite = prop->mDataLength / sizeof(int32_t);
|
||||
if (pMax) {
|
||||
|
|
|
@ -61,14 +61,14 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
|
|||
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
|
||||
if(outfile == NULL) {
|
||||
throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
|
||||
}
|
||||
}
|
||||
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
|
||||
}
|
||||
{
|
||||
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
|
||||
if(outfile == NULL) {
|
||||
throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
|
||||
}
|
||||
}
|
||||
outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
|
||||
}
|
||||
}
|
||||
|
@ -199,6 +199,7 @@ void ObjExporter :: WriteGeometryFile()
|
|||
AddNode(pScene->mRootNode,mBase);
|
||||
|
||||
// write vertex positions
|
||||
vpMap.getVectors(vp);
|
||||
mOutput << "# " << vp.size() << " vertex positions" << endl;
|
||||
BOOST_FOREACH(const aiVector3D& v, vp) {
|
||||
mOutput << "v " << v.x << " " << v.y << " " << v.z << endl;
|
||||
|
@ -206,6 +207,7 @@ void ObjExporter :: WriteGeometryFile()
|
|||
mOutput << endl;
|
||||
|
||||
// write uv coordinates
|
||||
vtMap.getVectors(vt);
|
||||
mOutput << "# " << vt.size() << " UV coordinates" << endl;
|
||||
BOOST_FOREACH(const aiVector3D& v, vt) {
|
||||
mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
|
||||
|
@ -213,6 +215,7 @@ void ObjExporter :: WriteGeometryFile()
|
|||
mOutput << endl;
|
||||
|
||||
// write vertex normals
|
||||
vnMap.getVectors(vn);
|
||||
mOutput << "# " << vn.size() << " vertex normals" << endl;
|
||||
BOOST_FOREACH(const aiVector3D& v, vn) {
|
||||
mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
|
||||
|
@ -252,6 +255,31 @@ void ObjExporter :: WriteGeometryFile()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
|
||||
{
|
||||
vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
|
||||
if(vertIt != vecMap.end()){// vertex already exists, so reference it
|
||||
return vertIt->second;
|
||||
}
|
||||
vecMap[vec] = mNextIndex;
|
||||
int ret = mNextIndex;
|
||||
mNextIndex++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
|
||||
{
|
||||
vecs.resize(vecMap.size());
|
||||
for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); it++){
|
||||
vecs[it->second-1] = it->first;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
|
||||
{
|
||||
|
@ -262,6 +290,7 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
|
|||
mesh.matname = GetMaterialName(m->mMaterialIndex);
|
||||
|
||||
mesh.faces.resize(m->mNumFaces);
|
||||
|
||||
for(unsigned int i = 0; i < m->mNumFaces; ++i) {
|
||||
const aiFace& f = m->mFaces[i];
|
||||
|
||||
|
@ -281,21 +310,22 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
|
|||
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
|
||||
const unsigned int idx = f.mIndices[a];
|
||||
|
||||
// XXX need a way to check if this is an unique vertex or if we had it already,
|
||||
// in which case we should instead reference the previous occurrence.
|
||||
ai_assert(m->mVertices);
|
||||
vp.push_back( mat * m->mVertices[idx] );
|
||||
face.indices[a].vp = vp.size();
|
||||
aiVector3D vert = mat * m->mVertices[idx];
|
||||
face.indices[a].vp = vpMap.getIndex(vert);
|
||||
|
||||
if (m->mNormals) {
|
||||
vn.push_back( m->mNormals[idx] );
|
||||
face.indices[a].vn = vnMap.getIndex(m->mNormals[idx]);
|
||||
}
|
||||
else{
|
||||
face.indices[a].vn = 0;
|
||||
}
|
||||
face.indices[a].vn = vn.size();
|
||||
|
||||
if (m->mTextureCoords[0]) {
|
||||
vt.push_back( m->mTextureCoords[0][idx] );
|
||||
face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]);
|
||||
}
|
||||
else{
|
||||
face.indices[a].vt = 0;
|
||||
}
|
||||
face.indices[a].vt = vt.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,36 @@ private:
|
|||
const aiScene* const pScene;
|
||||
|
||||
std::vector<aiVector3D> vp, vn, vt;
|
||||
|
||||
|
||||
struct aiVectorCompare
|
||||
{
|
||||
bool operator() (const aiVector3D& a, const aiVector3D& b) const
|
||||
{
|
||||
if(a.x < b.x) return true;
|
||||
if(a.x > b.x) return false;
|
||||
if(a.y < b.y) return true;
|
||||
if(a.y > b.y) return false;
|
||||
if(a.z < b.z) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class vecIndexMap
|
||||
{
|
||||
int mNextIndex;
|
||||
typedef std::map<aiVector3D, int, aiVectorCompare> dataType;
|
||||
dataType vecMap;
|
||||
public:
|
||||
|
||||
vecIndexMap():mNextIndex(1)
|
||||
{}
|
||||
|
||||
int getIndex(const aiVector3D& vec);
|
||||
void getVectors( std::vector<aiVector3D>& vecs );
|
||||
};
|
||||
|
||||
vecIndexMap vpMap, vnMap, vtMap;
|
||||
std::vector<MeshInstance> meshes;
|
||||
|
||||
// this endl() doesn't flush() the stream
|
||||
|
|
|
@ -277,7 +277,7 @@ struct Model
|
|||
//! Material map
|
||||
std::map<std::string, Material*> m_MaterialMap;
|
||||
|
||||
//! \brief Default constructor
|
||||
//! \brief The default class constructor
|
||||
Model() :
|
||||
m_ModelName(""),
|
||||
m_pCurrent(NULL),
|
||||
|
@ -290,7 +290,7 @@ struct Model
|
|||
// empty
|
||||
}
|
||||
|
||||
//! \brief Destructor
|
||||
//! \brief The class destructor
|
||||
~Model()
|
||||
{
|
||||
// Clear all stored object instances
|
||||
|
|
|
@ -123,8 +123,9 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
|
||||
// Get the file-size and validate it, throwing an exception when fails
|
||||
size_t fileSize = file->FileSize();
|
||||
if( fileSize < 16)
|
||||
if( fileSize < 16) {
|
||||
throw DeadlyImportError( "OBJ-file is too small.");
|
||||
}
|
||||
|
||||
// Allocate buffer and read file into it
|
||||
TextFileToBuffer(file.get(),m_Buffer);
|
||||
|
@ -167,15 +168,15 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
|
|||
}
|
||||
else
|
||||
{
|
||||
// This is an error, so break down the application
|
||||
// This is a fatal error, so break down the application
|
||||
ai_assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Create nodes for the whole scene
|
||||
std::vector<aiMesh*> MeshArray;
|
||||
for (size_t index = 0; index < pModel->m_Objects.size(); index++)
|
||||
{
|
||||
createNodes(pModel, pModel->m_Objects[ index ], index, pScene->mRootNode, pScene, MeshArray);
|
||||
createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray);
|
||||
}
|
||||
|
||||
// Create mesh pointer buffer for this scene
|
||||
|
@ -195,7 +196,6 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Creates all nodes of the model
|
||||
aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject,
|
||||
unsigned int /*uiMeshIndex*/,
|
||||
aiNode *pParent, aiScene* pScene,
|
||||
std::vector<aiMesh*> &MeshArray )
|
||||
{
|
||||
|
@ -276,14 +276,23 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
|
|||
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
|
||||
{
|
||||
ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
|
||||
|
||||
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
|
||||
pMesh->mNumFaces += inp->m_pVertices->size() - 1;
|
||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
|
||||
}
|
||||
else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
|
||||
pMesh->mNumFaces += inp->m_pVertices->size();
|
||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
||||
}
|
||||
else {
|
||||
++pMesh->mNumFaces;
|
||||
if (inp->m_pVertices->size() > 3) {
|
||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
||||
}
|
||||
else {
|
||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,7 +393,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
|
|||
pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
|
||||
|
||||
// Copy all normals
|
||||
if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty())
|
||||
if ( !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_pNormals->size())
|
||||
{
|
||||
const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex );
|
||||
if ( normal >= pModel->m_Normals.size() )
|
||||
|
@ -394,21 +403,16 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
|
|||
}
|
||||
|
||||
// Copy all texture coordinates
|
||||
if ( !pModel->m_TextureCoord.empty() )
|
||||
if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
|
||||
{
|
||||
if ( !pSourceFace->m_pTexturCoords->empty() )
|
||||
{
|
||||
const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
|
||||
ai_assert( tex < pModel->m_TextureCoord.size() );
|
||||
for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ )
|
||||
{
|
||||
if ( tex >= pModel->m_TextureCoord.size() )
|
||||
throw DeadlyImportError("OBJ: texture coord index out of range");
|
||||
const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
|
||||
ai_assert( tex < pModel->m_TextureCoord.size() );
|
||||
|
||||
if ( tex >= pModel->m_TextureCoord.size() )
|
||||
throw DeadlyImportError("OBJ: texture coord index out of range");
|
||||
|
||||
aiVector2D coord2d = pModel->m_TextureCoord[ tex ];
|
||||
pMesh->mTextureCoords[ i ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
|
||||
}
|
||||
}
|
||||
aiVector2D coord2d = pModel->m_TextureCoord[ tex ];
|
||||
pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
|
||||
}
|
||||
|
||||
ai_assert( pMesh->mNumVertices > newIndex );
|
||||
|
@ -587,15 +591,12 @@ void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild)
|
|||
|
||||
// Assign parent to child
|
||||
pChild->mParent = pParent;
|
||||
size_t sNumChildren = 0;
|
||||
(void)sNumChildren; // remove warning on release build
|
||||
|
||||
// If already children was assigned to the parent node, store them in a
|
||||
std::vector<aiNode*> temp;
|
||||
if (pParent->mChildren != NULL)
|
||||
{
|
||||
sNumChildren = pParent->mNumChildren;
|
||||
ai_assert( 0 != sNumChildren );
|
||||
ai_assert( 0 != pParent->mNumChildren );
|
||||
for (size_t index = 0; index < pParent->mNumChildren; index++)
|
||||
{
|
||||
temp.push_back(pParent->mChildren [ index ] );
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
//! \brief Appends the supported extention.
|
||||
//! \brief Appends the supported extension.
|
||||
const aiImporterDesc* GetInfo () const;
|
||||
|
||||
//! \brief File import implementation.
|
||||
|
@ -87,7 +87,7 @@ private:
|
|||
void CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene);
|
||||
|
||||
//! \brief Creates all nodes stored in imported content.
|
||||
aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData, unsigned int uiMeshIndex,
|
||||
aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData,
|
||||
aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
|
||||
|
||||
//! \brief Creates topology data like faces and meshes for the geometry.
|
||||
|
@ -104,18 +104,15 @@ private:
|
|||
//! \brief Material creation.
|
||||
void createMaterials(const ObjFile::Model* pModel, aiScene* pScene);
|
||||
|
||||
//! \brief Appends a child node to a parentnode and updates the datastructures.
|
||||
//! \brief Appends a child node to a parent node and updates the data structures.
|
||||
void appendChildToParentNode(aiNode *pParent, aiNode *pChild);
|
||||
|
||||
//! \brief TODO!
|
||||
void createAnimations();
|
||||
|
||||
private:
|
||||
//! Data buffer
|
||||
std::vector<char> m_Buffer;
|
||||
//! Pointer to root object instance
|
||||
ObjFile::Object *m_pRootObject;
|
||||
//! Absolute pathname of model in filesystem
|
||||
//! Absolute pathname of model in file system
|
||||
std::string m_strAbsPath;
|
||||
};
|
||||
|
||||
|
|
|
@ -50,10 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "../include/assimp/types.h"
|
||||
#include "DefaultIOSystem.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
namespace Assimp {
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -71,9 +69,10 @@ ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModel
|
|||
m_pModel = new ObjFile::Model();
|
||||
m_pModel->m_ModelName = strModelName;
|
||||
|
||||
// create default material and store it
|
||||
m_pModel->m_pDefaultMaterial = new ObjFile::Material();
|
||||
m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL );
|
||||
m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL );
|
||||
m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL );
|
||||
m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial;
|
||||
|
||||
// Start parsing the file
|
||||
|
@ -84,9 +83,6 @@ ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModel
|
|||
// Destructor
|
||||
ObjFileParser::~ObjFileParser()
|
||||
{
|
||||
/*delete m_pModel->m_pDefaultMaterial;
|
||||
m_pModel->m_pDefaultMaterial = NULL;*/
|
||||
|
||||
delete m_pModel;
|
||||
m_pModel = NULL;
|
||||
}
|
||||
|
@ -112,7 +108,7 @@ void ObjFileParser::parseFile()
|
|||
case 'v': // Parse a vertex texture coordinate
|
||||
{
|
||||
++m_DataIt;
|
||||
if (*m_DataIt == ' ')
|
||||
if (*m_DataIt == ' ' || *m_DataIt == '\t')
|
||||
{
|
||||
// Read in vertex definition
|
||||
getVector3(m_pModel->m_Vertices);
|
||||
|
@ -200,6 +196,8 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
|
|||
break;
|
||||
++m_DataIt;
|
||||
}
|
||||
|
||||
ai_assert(index < length);
|
||||
pBuffer[index] = '\0';
|
||||
}
|
||||
|
||||
|
@ -207,16 +205,30 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
|
|||
// Copy the next line into a temporary buffer
|
||||
void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
|
||||
{
|
||||
size_t index = 0;
|
||||
while (m_DataIt != m_DataItEnd)
|
||||
{
|
||||
if (*m_DataIt == '\n' || *m_DataIt == '\r' || index == length-1)
|
||||
break;
|
||||
size_t index = 0u;
|
||||
|
||||
pBuffer[ index ] = *m_DataIt;
|
||||
++index;
|
||||
++m_DataIt;
|
||||
// some OBJ files have line continuations using \ (such as in C++ et al)
|
||||
bool continuation = false;
|
||||
for (;m_DataIt != m_DataItEnd && index < length-1; ++m_DataIt)
|
||||
{
|
||||
const char c = *m_DataIt;
|
||||
if (c == '\\') {
|
||||
continuation = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '\n' || c == '\r') {
|
||||
if(continuation) {
|
||||
pBuffer[ index++ ] = ' ';
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
continuation = false;
|
||||
pBuffer[ index++ ] = c;
|
||||
}
|
||||
ai_assert(index < length);
|
||||
pBuffer[ index ] = '\0';
|
||||
}
|
||||
|
||||
|
@ -274,6 +286,10 @@ void ObjFileParser::getFace(aiPrimitiveType type)
|
|||
std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
|
||||
bool hasNormal = false;
|
||||
|
||||
const int vSize = m_pModel->m_Vertices.size();
|
||||
const int vtSize = m_pModel->m_TextureCoord.size();
|
||||
const int vnSize = m_pModel->m_Normals.size();
|
||||
|
||||
const bool vt = (!m_pModel->m_TextureCoord.empty());
|
||||
const bool vn = (!m_pModel->m_Normals.empty());
|
||||
int iStep = 0, iPos = 0;
|
||||
|
@ -307,7 +323,11 @@ void ObjFileParser::getFace(aiPrimitiveType type)
|
|||
{
|
||||
//OBJ USES 1 Base ARRAYS!!!!
|
||||
const int iVal = atoi( pPtr );
|
||||
|
||||
// increment iStep position based off of the sign and # of digits
|
||||
int tmp = iVal;
|
||||
if (iVal < 0)
|
||||
++iStep;
|
||||
while ( ( tmp = tmp / 10 )!=0 )
|
||||
++iStep;
|
||||
|
||||
|
@ -332,6 +352,27 @@ void ObjFileParser::getFace(aiPrimitiveType type)
|
|||
reportErrorTokenInFace();
|
||||
}
|
||||
}
|
||||
else if ( iVal < 0 )
|
||||
{
|
||||
// Store relatively index
|
||||
if ( 0 == iPos )
|
||||
{
|
||||
pIndices->push_back( vSize + iVal );
|
||||
}
|
||||
else if ( 1 == iPos )
|
||||
{
|
||||
pTexID->push_back( vtSize + iVal );
|
||||
}
|
||||
else if ( 2 == iPos )
|
||||
{
|
||||
pNormalID->push_back( vnSize + iVal );
|
||||
hasNormal = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reportErrorTokenInFace();
|
||||
}
|
||||
}
|
||||
}
|
||||
pPtr += iStep;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
|
|||
|
||||
mOutput << "ply" << endl;
|
||||
mOutput << "format ascii 1.0" << endl;
|
||||
mOutput << "Created by Open Asset Import Library - http://assimp.sf.net (v"
|
||||
mOutput << "comment Created by Open Asset Import Library - http://assimp.sf.net (v"
|
||||
<< aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
|
||||
<< aiGetVersionRevision() << ")" << endl;
|
||||
|
||||
|
@ -159,7 +159,7 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
|
|||
}
|
||||
|
||||
mOutput << "element face " << faces << endl;
|
||||
mOutput << "property list uint uint vertex_indices" << endl;
|
||||
mOutput << "property list uint uint vertex_index" << endl;
|
||||
mOutput << "end_header" << endl;
|
||||
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
|
|
|
@ -47,6 +47,7 @@ corresponding preprocessor flag to selectively disable steps.
|
|||
*/
|
||||
|
||||
#include "AssimpPCH.h"
|
||||
#include "ProcessHelper.h"
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS
|
||||
# include "CalcTangentsProcess.h"
|
||||
|
@ -215,7 +216,7 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out)
|
|||
#if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS)
|
||||
out.push_back( new FlipWindingOrderProcess());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_DEBONE_PROCESS)
|
||||
#if (!defined ASSIMP_BUILD_NO_DEBONE_PROCESS)
|
||||
out.push_back( new DeboneProcess());
|
||||
#endif
|
||||
#if (!defined ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS)
|
||||
|
|
|
@ -63,12 +63,25 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
|
|||
|
||||
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
|
||||
}
|
||||
void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene)
|
||||
{
|
||||
// invoke the exporter
|
||||
STLExporter exporter(pFile, pScene, true);
|
||||
|
||||
// we're still here - export successfully completed. Write the file.
|
||||
boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
|
||||
if(outfile == NULL) {
|
||||
throw DeadlyExportError("could not open output .stl file: " + std::string(pFile));
|
||||
}
|
||||
|
||||
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
|
||||
}
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
STLExporter :: STLExporter(const char* _filename, const aiScene* pScene)
|
||||
STLExporter :: STLExporter(const char* _filename, const aiScene* pScene, bool binary)
|
||||
: filename(_filename)
|
||||
, pScene(pScene)
|
||||
, endl("\n")
|
||||
|
@ -76,14 +89,31 @@ STLExporter :: STLExporter(const char* _filename, const aiScene* pScene)
|
|||
// make sure that all formatting happens using the standard, C locale and not the user's current locale
|
||||
const std::locale& l = std::locale("C");
|
||||
mOutput.imbue(l);
|
||||
|
||||
const std::string& name = "AssimpScene";
|
||||
if (binary) {
|
||||
char buf[80] = {0} ;
|
||||
buf[0] = 'A'; buf[1] = 's'; buf[2] = 's'; buf[3] = 'i'; buf[4] = 'm'; buf[5] = 'p';
|
||||
buf[6] = 'S'; buf[7] = 'c'; buf[8] = 'e'; buf[9] = 'n'; buf[10] = 'e';
|
||||
mOutput.write(buf, 80);
|
||||
unsigned int meshnum = 0;
|
||||
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
for (unsigned int j = 0; j < pScene->mMeshes[i]->mNumFaces; ++j) {
|
||||
meshnum++;
|
||||
}
|
||||
}
|
||||
AI_SWAP4(meshnum);
|
||||
mOutput.write((char *)&meshnum, 4);
|
||||
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
WriteMeshBinary(pScene->mMeshes[i]);
|
||||
}
|
||||
} else {
|
||||
const std::string& name = "AssimpScene";
|
||||
|
||||
mOutput << "solid " << name << endl;
|
||||
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
WriteMesh(pScene->mMeshes[i]);
|
||||
mOutput << "solid " << name << endl;
|
||||
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
|
||||
WriteMesh(pScene->mMeshes[i]);
|
||||
}
|
||||
mOutput << "endsolid " << name << endl;
|
||||
}
|
||||
mOutput << "endsolid " << name << endl;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -113,4 +143,31 @@ void STLExporter :: WriteMesh(const aiMesh* m)
|
|||
}
|
||||
}
|
||||
|
||||
void STLExporter :: WriteMeshBinary(const aiMesh* m)
|
||||
{
|
||||
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
|
||||
const aiFace& f = m->mFaces[i];
|
||||
// we need per-face normals. We specified aiProcess_GenNormals as pre-requisite for this exporter,
|
||||
// but nonetheless we have to expect per-vertex normals.
|
||||
aiVector3D nor;
|
||||
if (m->mNormals) {
|
||||
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
|
||||
nor += m->mNormals[f.mIndices[a]];
|
||||
}
|
||||
nor.Normalize();
|
||||
}
|
||||
float nx = nor.x, ny = nor.y, nz = nor.z;
|
||||
AI_SWAP4(nx); AI_SWAP4(ny); AI_SWAP4(nz);
|
||||
mOutput.write((char *)&nx, 4); mOutput.write((char *)&ny, 4); mOutput.write((char *)&nz, 4);
|
||||
for(unsigned int a = 0; a < f.mNumIndices; ++a) {
|
||||
const aiVector3D& v = m->mVertices[f.mIndices[a]];
|
||||
float vx = v.x, vy = v.y, vz = v.z;
|
||||
AI_SWAP4(vx); AI_SWAP4(vy); AI_SWAP4(vz);
|
||||
mOutput.write((char *)&vx, 4); mOutput.write((char *)&vy, 4); mOutput.write((char *)&vz, 4);
|
||||
}
|
||||
char dummy[2] = {0};
|
||||
mOutput.write(dummy, 2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -59,7 +59,7 @@ class STLExporter
|
|||
{
|
||||
public:
|
||||
/// Constructor for a specific scene to export
|
||||
STLExporter(const char* filename, const aiScene* pScene);
|
||||
STLExporter(const char* filename, const aiScene* pScene, bool binary = false);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -69,6 +69,7 @@ public:
|
|||
private:
|
||||
|
||||
void WriteMesh(const aiMesh* m);
|
||||
void WriteMeshBinary(const aiMesh* m);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
using namespace Assimp;
|
||||
|
||||
namespace {
|
||||
static const aiImporterDesc desc = {
|
||||
"Stereolithography (STL) Importer",
|
||||
"",
|
||||
|
@ -64,6 +65,39 @@ static const aiImporterDesc desc = {
|
|||
"stl"
|
||||
};
|
||||
|
||||
// A valid binary STL buffer should consist of the following elements, in order:
|
||||
// 1) 80 byte header
|
||||
// 2) 4 byte face count
|
||||
// 3) 50 bytes per face
|
||||
bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
|
||||
if (fileSize < 84)
|
||||
return false;
|
||||
|
||||
const uint32_t faceCount = *reinterpret_cast<const uint32_t*>(buffer + 80);
|
||||
const uint32_t expectedBinaryFileSize = faceCount * 50 + 84;
|
||||
|
||||
return expectedBinaryFileSize == fileSize;
|
||||
}
|
||||
|
||||
// An ascii STL buffer will begin with "solid NAME", where NAME is optional.
|
||||
// Note: The "solid NAME" check is necessary, but not sufficient, to determine
|
||||
// if the buffer is ASCII; a binary header could also begin with "solid NAME".
|
||||
bool IsAsciiSTL(const char* buffer, unsigned int fileSize) {
|
||||
if (IsBinarySTL(buffer, fileSize))
|
||||
return false;
|
||||
|
||||
const char* bufferEnd = buffer + fileSize;
|
||||
|
||||
if (!SkipSpaces(&buffer))
|
||||
return false;
|
||||
|
||||
if (buffer + 5 >= bufferEnd)
|
||||
return false;
|
||||
|
||||
return strncmp(buffer, "solid", 5) == 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
STLImporter::STLImporter()
|
||||
|
@ -136,12 +170,13 @@ void STLImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
bool bMatClr = false;
|
||||
|
||||
// check whether the file starts with 'solid' -
|
||||
// in this case we can simply assume it IS a text file. finished.
|
||||
if (!::strncmp(mBuffer,"solid",5)) {
|
||||
if (IsBinarySTL(mBuffer, fileSize)) {
|
||||
bMatClr = LoadBinaryFile();
|
||||
} else if (IsAsciiSTL(mBuffer, fileSize)) {
|
||||
LoadASCIIFile();
|
||||
} else {
|
||||
throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + ".");
|
||||
}
|
||||
else bMatClr = LoadBinaryFile();
|
||||
|
||||
// now copy faces
|
||||
pMesh->mFaces = new aiFace[pMesh->mNumFaces];
|
||||
|
@ -179,7 +214,11 @@ void STLImporter::LoadASCIIFile()
|
|||
{
|
||||
aiMesh* pMesh = pScene->mMeshes[0];
|
||||
|
||||
const char* sz = mBuffer + 5; // skip the "solid"
|
||||
const char* sz = mBuffer;
|
||||
SkipSpaces(&sz);
|
||||
ai_assert(!IsLineEnd(sz));
|
||||
|
||||
sz += 5; // skip the "solid"
|
||||
SkipSpaces(&sz);
|
||||
const char* szMe = sz;
|
||||
while (!::IsSpaceOrNewLine(*sz)) {
|
||||
|
|
|
@ -53,6 +53,7 @@ struct ScenePrivateData {
|
|||
ScenePrivateData()
|
||||
: mOrigImporter()
|
||||
, mPPStepsApplied()
|
||||
, mIsCopy()
|
||||
{}
|
||||
|
||||
// Importer that originally loaded the scene though the C-API
|
||||
|
@ -61,6 +62,13 @@ struct ScenePrivateData {
|
|||
|
||||
// List of postprocessing steps already applied to the scene.
|
||||
unsigned int mPPStepsApplied;
|
||||
|
||||
// true if the scene is a copy made with aiCopyScene()
|
||||
// or the corresponding C++ API. This means that user code
|
||||
// may have made modifications to it, so mPPStepsApplied
|
||||
// and mOrigImporter are no longer safe to rely on and only
|
||||
// serve informative purposes.
|
||||
bool mIsCopy;
|
||||
};
|
||||
|
||||
// Access private data stored in the scene
|
||||
|
|
|
@ -151,7 +151,7 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
|
|||
std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
{
|
||||
aiMesh* mesh = pScene->mMeshes[i];
|
||||
aiMesh* const mesh = pScene->mMeshes[i];
|
||||
ai_assert(0 != mesh->mPrimitiveTypes);
|
||||
|
||||
// if there's just one primitive type in the mesh there's nothing to do for us
|
||||
|
@ -367,6 +367,9 @@ void SortByPTypeProcess::Execute( aiScene* pScene)
|
|||
|
||||
// delete the input mesh
|
||||
delete mesh;
|
||||
|
||||
// avoid invalid pointer
|
||||
pScene->mMeshes[i] = NULL;
|
||||
}
|
||||
|
||||
if (outMeshes.empty())
|
||||
|
|
|
@ -193,7 +193,7 @@ public:
|
|||
|
||||
// ---------------------------------------------------------------------
|
||||
/** Increase the file pointer (relative seeking) */
|
||||
void IncPtr(int plus) {
|
||||
void IncPtr(size_t plus) {
|
||||
current += plus;
|
||||
if (current > limit) {
|
||||
throw DeadlyImportError("End of file or read limit was reached");
|
||||
|
|
|
@ -82,7 +82,7 @@ protected:
|
|||
/** Report a validation error. This will throw an exception,
|
||||
* control won't return.
|
||||
* @param msg Format string for sprintf().*/
|
||||
AI_WONT_RETURN void ReportError(const char* msg,...);
|
||||
AI_WONT_RETURN void ReportError(const char* msg,...) AI_WONT_RETURN_SUFFIX;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define __FAST_A_TO_F_H_INCLUDED__
|
||||
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
|
|
@ -164,6 +164,8 @@ int Triangle::Index(const Point* p)
|
|||
return 2;
|
||||
}
|
||||
assert(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Triangle::EdgeIndex(const Point* p1, const Point* p2)
|
||||
|
@ -223,6 +225,8 @@ Point* Triangle::PointCW(Point& point)
|
|||
return points_[1];
|
||||
}
|
||||
assert(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The point counter-clockwise to given point
|
||||
|
@ -236,6 +240,8 @@ Point* Triangle::PointCCW(Point& point)
|
|||
return points_[0];
|
||||
}
|
||||
assert(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The neighbor clockwise to given point
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <stdexcept>
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
namespace p2t {
|
||||
|
||||
|
@ -137,8 +138,8 @@ struct Edge {
|
|||
p = &p2;
|
||||
} else if (p1.x == p2.x) {
|
||||
// Repeat points
|
||||
// ASSIMP_CHANGE (aramis_acg)
|
||||
throw std::runtime_error("repeat points");
|
||||
// ASSIMP_CHANGE (aramis_acg)
|
||||
throw std::runtime_error(std::string("repeat points"));
|
||||
//assert(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,25 @@
|
|||
cmake_minimum_required(VERSION 2.4.4)
|
||||
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
|
||||
|
||||
project(zlib C)
|
||||
|
||||
set(VERSION "1.2.8")
|
||||
|
||||
option(ASM686 "Enable building i686 assembly implementation for zlib")
|
||||
option(AMD64 "Enable building amd64 assembly implementation for zlib")
|
||||
|
||||
#set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
|
||||
#set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
|
||||
#set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
|
||||
#set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
|
||||
#set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
|
||||
|
||||
include(CheckTypeSize)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckCSourceCompiles)
|
||||
enable_testing()
|
||||
|
||||
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
|
||||
check_include_file(stdint.h HAVE_STDINT_H)
|
||||
check_include_file(stddef.h HAVE_STDDEF_H)
|
||||
|
@ -18,7 +40,6 @@ endif()
|
|||
if(HAVE_STDDEF_H)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
|
||||
endif()
|
||||
|
||||
check_type_size(off64_t OFF64_T)
|
||||
if(HAVE_OFF64_T)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE=1)
|
||||
|
@ -42,22 +63,28 @@ if(MSVC)
|
|||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||
# If we're doing an out of source build and the user has a zconf.h
|
||||
# in their source tree...
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h)
|
||||
message(FATAL_ERROR
|
||||
"You must remove ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h "
|
||||
"from the source tree. This file is included with zlib "
|
||||
"but CMake generates this file for you automatically "
|
||||
"in the build directory.")
|
||||
message(STATUS "Renaming")
|
||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h")
|
||||
message(STATUS "to 'zconf.h.included' because this file is included with zlib")
|
||||
message(STATUS "but CMake generates it automatically in the build directory.")
|
||||
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zconf.in.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h @ONLY)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
|
||||
${ZLIB_PC} @ONLY)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
|
||||
|
||||
|
||||
#============================================================================
|
||||
|
@ -65,28 +92,104 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
|||
#============================================================================
|
||||
|
||||
set(ZLIB_PUBLIC_HDRS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zconf.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zconf.h
|
||||
zlib.h
|
||||
)
|
||||
set(ZLIB_PRIVATE_HDRS
|
||||
crc32.h deflate.h inffast.h inffixed.h inflate.h inftrees.h trees.h zconf.h zlib.h zutil.h
|
||||
|
||||
crc32.h
|
||||
deflate.h
|
||||
gzguts.h
|
||||
inffast.h
|
||||
inffixed.h
|
||||
inflate.h
|
||||
inftrees.h
|
||||
trees.h
|
||||
zutil.h
|
||||
)
|
||||
set(ZLIB_SRCS
|
||||
adler32.c compress.c crc32.c deflate.c inffast.c inflate.c inftrees.c trees.c zutil.c
|
||||
adler32.c
|
||||
compress.c
|
||||
crc32.c
|
||||
deflate.c
|
||||
gzclose.c
|
||||
gzlib.c
|
||||
gzread.c
|
||||
gzwrite.c
|
||||
inflate.c
|
||||
infback.c
|
||||
inftrees.c
|
||||
inffast.c
|
||||
trees.c
|
||||
uncompr.c
|
||||
zutil.c
|
||||
)
|
||||
|
||||
if(NOT MINGW)
|
||||
set(ZLIB_DLL_SRCS
|
||||
win32/zlib1.rc # If present will override custom build rule below.
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
if(ASM686)
|
||||
set(ZLIB_ASMS contrib/asm686/match.S)
|
||||
elseif (AMD64)
|
||||
set(ZLIB_ASMS contrib/amd64/amd64-match.S)
|
||||
endif ()
|
||||
|
||||
if(ZLIB_ASMS)
|
||||
add_definitions(-DASMV)
|
||||
set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
if(ASM686)
|
||||
ENABLE_LANGUAGE(ASM_MASM)
|
||||
set(ZLIB_ASMS
|
||||
contrib/masmx86/inffas32.asm
|
||||
contrib/masmx86/match686.asm
|
||||
)
|
||||
elseif (AMD64)
|
||||
ENABLE_LANGUAGE(ASM_MASM)
|
||||
set(ZLIB_ASMS
|
||||
contrib/masmx64/gvmat64.asm
|
||||
contrib/masmx64/inffasx64.asm
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ZLIB_ASMS)
|
||||
add_definitions(-DASMV -DASMINF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents)
|
||||
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([0-9A-Za-z.]+)\".*"
|
||||
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
|
||||
"\\1" ZLIB_FULL_VERSION ${_zlib_h_contents})
|
||||
|
||||
add_library(zlib STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS}")
|
||||
if(MINGW)
|
||||
# This gets us DLL resource information when compiling on MinGW.
|
||||
if(NOT CMAKE_RC_COMPILER)
|
||||
set(CMAKE_RC_COMPILER windres.exe)
|
||||
endif()
|
||||
|
||||
set_target_properties(zlib PROPERTIES SOVERSION 1)
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
||||
COMMAND ${CMAKE_RC_COMPILER}
|
||||
-D GCC_WINDRES
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-I ${CMAKE_CURRENT_BINARY_DIR}
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
||||
-i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
|
||||
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
|
||||
endif(MINGW)
|
||||
|
||||
if(NOT CYGWIN)
|
||||
#add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
#set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
|
||||
#set_target_properties(zlib PROPERTIES SOVERSION 1)
|
||||
|
||||
#if(NOT CYGWIN)
|
||||
# This property causes shared libraries on Linux to have the full version
|
||||
# encoded into their final filename. We disable this on Cygwin because
|
||||
# it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
|
||||
|
@ -94,48 +197,33 @@ if(NOT CYGWIN)
|
|||
#
|
||||
# This has no effect with MSVC, on that platform the version info for
|
||||
# the DLL comes from the resource file win32/zlib1.rc
|
||||
set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
|
||||
endif()
|
||||
#set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
|
||||
#endif()
|
||||
|
||||
if(UNIX)
|
||||
#if(UNIX)
|
||||
# On unix-like platforms the library is almost always called libz
|
||||
set_target_properties(zlib PROPERTIES OUTPUT_NAME z)
|
||||
elseif(BUILD_SHARED_LIBS AND WIN32)
|
||||
# Creates zlib1.dll when building shared library version
|
||||
set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
|
||||
endif()
|
||||
#set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
|
||||
#if(NOT APPLE)
|
||||
# set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
|
||||
#endif()
|
||||
#elseif(BUILD_SHARED_LIBS AND WIN32)
|
||||
# # Creates zlib1.dll when building shared library version
|
||||
# set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
|
||||
#endif()
|
||||
|
||||
#if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
|
||||
# install(TARGETS zlib
|
||||
# RUNTIME DESTINATION bin
|
||||
# ARCHIVE DESTINATION lib
|
||||
# LIBRARY DESTINATION lib )
|
||||
# install(TARGETS zlib zlibstatic
|
||||
# RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
|
||||
# ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
|
||||
# LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
|
||||
#endif()
|
||||
#if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
|
||||
# install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION include)
|
||||
# install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}")
|
||||
#endif()
|
||||
#if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
# install(FILES zlib.3 DESTINATION share/man/man3)
|
||||
# install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3")
|
||||
#endif()
|
||||
#if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
# install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
|
||||
#endif()
|
||||
|
||||
#============================================================================
|
||||
# Example binaries
|
||||
#============================================================================
|
||||
|
||||
#add_executable(example example.c)
|
||||
#target_link_libraries(example zlib)
|
||||
#add_test(example example)
|
||||
#
|
||||
#add_executable(minigzip minigzip.c)
|
||||
#target_link_libraries(minigzip zlib)
|
||||
#
|
||||
#if(HAVE_OFF64_T)
|
||||
# add_executable(example64 example.c)
|
||||
# target_link_libraries(example64 zlib)
|
||||
# set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||
# add_test(example64 example64)
|
||||
#
|
||||
# add_executable(minigzip64 minigzip.c)
|
||||
# target_link_libraries(minigzip64 zlib)
|
||||
# set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||
#endif()
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.5 is a general purpose data compression library. All the code is
|
||||
zlib 1.2.8 is a general purpose data compression library. All the code is
|
||||
thread safe. The data format used by the zlib library is described by RFCs
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
|
||||
and rfc1952.txt (gzip format).
|
||||
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
|
||||
rfc1952 (gzip format).
|
||||
|
||||
All functions of the compression library are documented in the file zlib.h
|
||||
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
|
||||
of the library is given in the file example.c which also tests that the library
|
||||
is working correctly. Another example is given in the file minigzip.c. The
|
||||
compression library itself is composed of all source files except example.c and
|
||||
minigzip.c.
|
||||
of the library is given in the file test/example.c which also tests that
|
||||
the library is working correctly. Another example is given in the file
|
||||
test/minigzip.c. The compression library itself is composed of all source
|
||||
files in the root directory.
|
||||
|
||||
To compile all files and run the test program, follow the instructions given at
|
||||
the top of Makefile.in. In short "./configure; make test", and if that goes
|
||||
well, "make install" should work for most flavors of Unix. For Windows, use one
|
||||
of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
|
||||
well, "make install" should work for most flavors of Unix. For Windows, use
|
||||
one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
|
||||
make_vms.com.
|
||||
|
||||
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
|
||||
|
@ -31,7 +31,7 @@ Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
|
|||
issue of Dr. Dobb's Journal; a copy of the article is available at
|
||||
http://marknelson.us/1997/01/01/zlib-engine/ .
|
||||
|
||||
The changes made in version 1.2.5 are documented in the file ChangeLog.
|
||||
The changes made in version 1.2.8 are documented in the file ChangeLog.
|
||||
|
||||
Unsupported third party contributions are provided in directory contrib/ .
|
||||
|
||||
|
@ -44,7 +44,7 @@ http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
|
|||
|
||||
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
|
||||
available in Python 1.5 and later versions, see
|
||||
http://www.python.org/doc/lib/module-zlib.html .
|
||||
http://docs.python.org/library/zlib.html .
|
||||
|
||||
zlib is built into tcl: http://wiki.tcl.tk/4610 .
|
||||
|
||||
|
@ -84,7 +84,7 @@ Acknowledgments:
|
|||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-2010 Jean-loup Gailly and Mark Adler
|
||||
(C) 1995-2013 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2007 Mark Adler
|
||||
* Copyright (C) 1995-2011 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -9,9 +9,9 @@
|
|||
|
||||
#define local static
|
||||
|
||||
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
|
||||
local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
|
||||
|
||||
#define BASE 65521UL /* largest prime smaller than 65536 */
|
||||
#define BASE 65521 /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
|
@ -21,39 +21,44 @@ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
|
|||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware */
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware --
|
||||
try it both ways to see which is faster */
|
||||
#ifdef NO_DIVIDE
|
||||
# define MOD(a) \
|
||||
/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
|
||||
(thank you to John Reiser for pointing this out) */
|
||||
# define CHOP(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 16)) a -= (BASE << 16); \
|
||||
if (a >= (BASE << 15)) a -= (BASE << 15); \
|
||||
if (a >= (BASE << 14)) a -= (BASE << 14); \
|
||||
if (a >= (BASE << 13)) a -= (BASE << 13); \
|
||||
if (a >= (BASE << 12)) a -= (BASE << 12); \
|
||||
if (a >= (BASE << 11)) a -= (BASE << 11); \
|
||||
if (a >= (BASE << 10)) a -= (BASE << 10); \
|
||||
if (a >= (BASE << 9)) a -= (BASE << 9); \
|
||||
if (a >= (BASE << 8)) a -= (BASE << 8); \
|
||||
if (a >= (BASE << 7)) a -= (BASE << 7); \
|
||||
if (a >= (BASE << 6)) a -= (BASE << 6); \
|
||||
if (a >= (BASE << 5)) a -= (BASE << 5); \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
unsigned long tmp = a >> 16; \
|
||||
a &= 0xffffUL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
} while (0)
|
||||
# define MOD28(a) \
|
||||
do { \
|
||||
CHOP(a); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
# define MOD4(a) \
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
CHOP(a); \
|
||||
MOD28(a); \
|
||||
} while (0)
|
||||
# define MOD63(a) \
|
||||
do { /* this assumes a is not negative */ \
|
||||
z_off64_t tmp = a >> 32; \
|
||||
a &= 0xffffffffL; \
|
||||
a += (tmp << 8) - (tmp << 5) + tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
# define MOD4(a) a %= BASE
|
||||
# define MOD28(a) a %= BASE
|
||||
# define MOD63(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
|
@ -92,7 +97,7 @@ uLong ZEXPORT adler32(adler, buf, len)
|
|||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
MOD4(sum2); /* only added so many BASE's */
|
||||
MOD28(sum2); /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
|
@ -137,8 +142,13 @@ local uLong adler32_combine_(adler1, adler2, len2)
|
|||
unsigned long sum2;
|
||||
unsigned rem;
|
||||
|
||||
/* for negative len, return invalid adler32 as a clue for debugging */
|
||||
if (len2 < 0)
|
||||
return 0xffffffffUL;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
rem = (unsigned)(len2 % BASE);
|
||||
MOD63(len2); /* assumes len2 >= 0 */
|
||||
rem = (unsigned)len2;
|
||||
sum1 = adler1 & 0xffff;
|
||||
sum2 = rem * sum1;
|
||||
MOD(sum2);
|
||||
|
|
|
@ -29,7 +29,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
|||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.next_in = (z_const Bytef *)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010 Mark Adler
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||
|
@ -17,6 +17,8 @@
|
|||
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
||||
first call get_crc_table() to initialize the tables before allowing more than
|
||||
one thread to use crc32().
|
||||
|
||||
DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
|
||||
*/
|
||||
|
||||
#ifdef MAKECRCH
|
||||
|
@ -30,31 +32,11 @@
|
|||
|
||||
#define local static
|
||||
|
||||
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
|
||||
#ifndef NOBYFOUR
|
||||
# ifdef STDC /* need ANSI C limits.h to determine sizes */
|
||||
# include <limits.h>
|
||||
# define BYFOUR
|
||||
# if (UINT_MAX == 0xffffffffUL)
|
||||
typedef unsigned int u4;
|
||||
# else
|
||||
# if (ULONG_MAX == 0xffffffffUL)
|
||||
typedef unsigned long u4;
|
||||
# else
|
||||
# if (USHRT_MAX == 0xffffffffUL)
|
||||
typedef unsigned short u4;
|
||||
# else
|
||||
# undef BYFOUR /* can't find a four-byte integer type! */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif /* STDC */
|
||||
#endif /* !NOBYFOUR */
|
||||
|
||||
/* Definitions for doing the crc four data bytes at a time. */
|
||||
#if !defined(NOBYFOUR) && defined(Z_U4)
|
||||
# define BYFOUR
|
||||
#endif
|
||||
#ifdef BYFOUR
|
||||
# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
|
||||
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
|
||||
local unsigned long crc32_little OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
local unsigned long crc32_big OF((unsigned long,
|
||||
|
@ -68,16 +50,16 @@
|
|||
local unsigned long gf2_matrix_times OF((unsigned long *mat,
|
||||
unsigned long vec));
|
||||
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
|
||||
local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);
|
||||
local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
|
||||
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
|
||||
local volatile int crc_table_empty = 1;
|
||||
local unsigned long FAR crc_table[TBLS][256];
|
||||
local z_crc_t FAR crc_table[TBLS][256];
|
||||
local void make_crc_table OF((void));
|
||||
#ifdef MAKECRCH
|
||||
local void write_table OF((FILE *, const unsigned long FAR *));
|
||||
local void write_table OF((FILE *, const z_crc_t FAR *));
|
||||
#endif /* MAKECRCH */
|
||||
/*
|
||||
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||
|
@ -107,9 +89,9 @@ local void make_crc_table OF((void));
|
|||
*/
|
||||
local void make_crc_table()
|
||||
{
|
||||
unsigned long c;
|
||||
z_crc_t c;
|
||||
int n, k;
|
||||
unsigned long poly; /* polynomial exclusive-or pattern */
|
||||
z_crc_t poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static volatile int first = 1; /* flag to limit concurrent making */
|
||||
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||
|
@ -121,13 +103,13 @@ local void make_crc_table()
|
|||
first = 0;
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
|
||||
poly = 0UL;
|
||||
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
|
||||
poly |= 1UL << (31 - p[n]);
|
||||
poly = 0;
|
||||
for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
|
||||
poly |= (z_crc_t)1 << (31 - p[n]);
|
||||
|
||||
/* generate a crc for every 8-bit value */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (unsigned long)n;
|
||||
c = (z_crc_t)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
crc_table[0][n] = c;
|
||||
|
@ -138,11 +120,11 @@ local void make_crc_table()
|
|||
and then the byte reversal of those as well as the first table */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = crc_table[0][n];
|
||||
crc_table[4][n] = REV(c);
|
||||
crc_table[4][n] = ZSWAP32(c);
|
||||
for (k = 1; k < 4; k++) {
|
||||
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
||||
crc_table[k][n] = c;
|
||||
crc_table[k + 4][n] = REV(c);
|
||||
crc_table[k + 4][n] = ZSWAP32(c);
|
||||
}
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
|
@ -164,7 +146,7 @@ local void make_crc_table()
|
|||
if (out == NULL) return;
|
||||
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
||||
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
||||
fprintf(out, "local const unsigned long FAR ");
|
||||
fprintf(out, "local const z_crc_t FAR ");
|
||||
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
|
||||
write_table(out, crc_table[0]);
|
||||
# ifdef BYFOUR
|
||||
|
@ -184,12 +166,13 @@ local void make_crc_table()
|
|||
#ifdef MAKECRCH
|
||||
local void write_table(out, table)
|
||||
FILE *out;
|
||||
const unsigned long FAR *table;
|
||||
const z_crc_t FAR *table;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
|
||||
(unsigned long)(table[n]),
|
||||
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
|
@ -204,13 +187,13 @@ local void write_table(out, table)
|
|||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const unsigned long FAR * ZEXPORT get_crc_table()
|
||||
const z_crc_t FAR * ZEXPORT get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
return (const unsigned long FAR *)crc_table;
|
||||
return (const z_crc_t FAR *)crc_table;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
@ -232,7 +215,7 @@ unsigned long ZEXPORT crc32(crc, buf, len)
|
|||
|
||||
#ifdef BYFOUR
|
||||
if (sizeof(void *) == sizeof(ptrdiff_t)) {
|
||||
u4 endian;
|
||||
z_crc_t endian;
|
||||
|
||||
endian = 1;
|
||||
if (*((unsigned char *)(&endian)))
|
||||
|
@ -266,17 +249,17 @@ local unsigned long crc32_little(crc, buf, len)
|
|||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
register u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
|
||||
c = (u4)crc;
|
||||
c = (z_crc_t)crc;
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOLIT32;
|
||||
len -= 32;
|
||||
|
@ -306,17 +289,17 @@ local unsigned long crc32_big(crc, buf, len)
|
|||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
register u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
|
||||
c = REV((u4)crc);
|
||||
c = ZSWAP32((z_crc_t)crc);
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
|
||||
buf4--;
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
|
@ -333,7 +316,7 @@ local unsigned long crc32_big(crc, buf, len)
|
|||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)(REV(c));
|
||||
return (unsigned long)(ZSWAP32(c));
|
||||
}
|
||||
|
||||
#endif /* BYFOUR */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Generated automatically by crc32.c
|
||||
*/
|
||||
|
||||
local const unsigned long FAR crc_table[TBLS][256] =
|
||||
local const z_crc_t FAR crc_table[TBLS][256] =
|
||||
{
|
||||
{
|
||||
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* deflate.c -- compress data using the deflation algorithm
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
|
||||
* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
|||
* REFERENCES
|
||||
*
|
||||
* Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
|
||||
* Available in http://www.ietf.org/rfc/rfc1951.txt
|
||||
* Available in http://tools.ietf.org/html/rfc1951
|
||||
*
|
||||
* A description of the Rabin and Karp algorithm is given in the book
|
||||
* "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
|
||||
|
@ -52,7 +52,7 @@
|
|||
#include "deflate.h"
|
||||
|
||||
const char deflate_copyright[] =
|
||||
" deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
|
||||
" deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
|
@ -155,6 +155,9 @@ local const config configuration_table[10] = {
|
|||
struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
|
||||
#endif
|
||||
|
||||
/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
|
||||
#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0))
|
||||
|
||||
/* ===========================================================================
|
||||
* Update a hash value with the given input byte
|
||||
* IN assertion: all calls to to UPDATE_HASH are made with consecutive
|
||||
|
@ -235,10 +238,19 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
|||
|
||||
strm->msg = Z_NULL;
|
||||
if (strm->zalloc == (alloc_func)0) {
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = (voidpf)0;
|
||||
#endif
|
||||
}
|
||||
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
|
||||
if (strm->zfree == (free_func)0)
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zfree = zcfree;
|
||||
#endif
|
||||
|
||||
#ifdef FASTEST
|
||||
if (level != 0) level = 1;
|
||||
|
@ -293,7 +305,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
|
|||
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
|
||||
s->pending_buf == Z_NULL) {
|
||||
s->status = FINISH_STATE;
|
||||
strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
|
||||
strm->msg = ERR_MSG(Z_MEM_ERROR);
|
||||
deflateEnd (strm);
|
||||
return Z_MEM_ERROR;
|
||||
}
|
||||
|
@ -314,43 +326,70 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
|
|||
uInt dictLength;
|
||||
{
|
||||
deflate_state *s;
|
||||
uInt length = dictLength;
|
||||
uInt n;
|
||||
IPos hash_head = 0;
|
||||
uInt str, n;
|
||||
int wrap;
|
||||
unsigned avail;
|
||||
z_const unsigned char *next;
|
||||
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
|
||||
strm->state->wrap == 2 ||
|
||||
(strm->state->wrap == 1 && strm->state->status != INIT_STATE))
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
s = strm->state;
|
||||
wrap = s->wrap;
|
||||
if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
s = strm->state;
|
||||
if (s->wrap)
|
||||
/* when using zlib wrappers, compute Adler-32 for provided dictionary */
|
||||
if (wrap == 1)
|
||||
strm->adler = adler32(strm->adler, dictionary, dictLength);
|
||||
s->wrap = 0; /* avoid computing Adler-32 in read_buf */
|
||||
|
||||
if (length < MIN_MATCH) return Z_OK;
|
||||
if (length > s->w_size) {
|
||||
length = s->w_size;
|
||||
dictionary += dictLength - length; /* use the tail of the dictionary */
|
||||
/* if dictionary would fill window, just replace the history */
|
||||
if (dictLength >= s->w_size) {
|
||||
if (wrap == 0) { /* already empty otherwise */
|
||||
CLEAR_HASH(s);
|
||||
s->strstart = 0;
|
||||
s->block_start = 0L;
|
||||
s->insert = 0;
|
||||
}
|
||||
dictionary += dictLength - s->w_size; /* use the tail */
|
||||
dictLength = s->w_size;
|
||||
}
|
||||
zmemcpy(s->window, dictionary, length);
|
||||
s->strstart = length;
|
||||
s->block_start = (long)length;
|
||||
|
||||
/* Insert all strings in the hash table (except for the last two bytes).
|
||||
* s->lookahead stays null, so s->ins_h will be recomputed at the next
|
||||
* call of fill_window.
|
||||
*/
|
||||
s->ins_h = s->window[0];
|
||||
UPDATE_HASH(s, s->ins_h, s->window[1]);
|
||||
for (n = 0; n <= length - MIN_MATCH; n++) {
|
||||
INSERT_STRING(s, n, hash_head);
|
||||
/* insert dictionary into window and hash */
|
||||
avail = strm->avail_in;
|
||||
next = strm->next_in;
|
||||
strm->avail_in = dictLength;
|
||||
strm->next_in = (z_const Bytef *)dictionary;
|
||||
fill_window(s);
|
||||
while (s->lookahead >= MIN_MATCH) {
|
||||
str = s->strstart;
|
||||
n = s->lookahead - (MIN_MATCH-1);
|
||||
do {
|
||||
UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
|
||||
#ifndef FASTEST
|
||||
s->prev[str & s->w_mask] = s->head[s->ins_h];
|
||||
#endif
|
||||
s->head[s->ins_h] = (Pos)str;
|
||||
str++;
|
||||
} while (--n);
|
||||
s->strstart = str;
|
||||
s->lookahead = MIN_MATCH-1;
|
||||
fill_window(s);
|
||||
}
|
||||
if (hash_head) hash_head = 0; /* to make compiler happy */
|
||||
s->strstart += s->lookahead;
|
||||
s->block_start = (long)s->strstart;
|
||||
s->insert = s->lookahead;
|
||||
s->lookahead = 0;
|
||||
s->match_length = s->prev_length = MIN_MATCH-1;
|
||||
s->match_available = 0;
|
||||
strm->next_in = next;
|
||||
strm->avail_in = avail;
|
||||
s->wrap = wrap;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
int ZEXPORT deflateReset (strm)
|
||||
int ZEXPORT deflateResetKeep (strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
deflate_state *s;
|
||||
|
@ -380,11 +419,22 @@ int ZEXPORT deflateReset (strm)
|
|||
s->last_flush = Z_NO_FLUSH;
|
||||
|
||||
_tr_init(s);
|
||||
lm_init(s);
|
||||
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
int ZEXPORT deflateReset (strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = deflateResetKeep(strm);
|
||||
if (ret == Z_OK)
|
||||
lm_init(strm->state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
int ZEXPORT deflateSetHeader (strm, head)
|
||||
z_streamp strm;
|
||||
|
@ -396,15 +446,43 @@ int ZEXPORT deflateSetHeader (strm, head)
|
|||
return Z_OK;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
int ZEXPORT deflatePending (strm, pending, bits)
|
||||
unsigned *pending;
|
||||
int *bits;
|
||||
z_streamp strm;
|
||||
{
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
if (pending != Z_NULL)
|
||||
*pending = strm->state->pending;
|
||||
if (bits != Z_NULL)
|
||||
*bits = strm->state->bi_valid;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
int ZEXPORT deflatePrime (strm, bits, value)
|
||||
z_streamp strm;
|
||||
int bits;
|
||||
int value;
|
||||
{
|
||||
deflate_state *s;
|
||||
int put;
|
||||
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
strm->state->bi_valid = bits;
|
||||
strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
|
||||
s = strm->state;
|
||||
if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
|
||||
return Z_BUF_ERROR;
|
||||
do {
|
||||
put = Buf_size - s->bi_valid;
|
||||
if (put > bits)
|
||||
put = bits;
|
||||
s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
|
||||
s->bi_valid += put;
|
||||
_tr_flush_bits(s);
|
||||
value >>= put;
|
||||
bits -= put;
|
||||
} while (bits);
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
@ -435,6 +513,8 @@ int ZEXPORT deflateParams(strm, level, strategy)
|
|||
strm->total_in != 0) {
|
||||
/* Flush the last buffer: */
|
||||
err = deflate(strm, Z_BLOCK);
|
||||
if (err == Z_BUF_ERROR && s->pending == 0)
|
||||
err = Z_OK;
|
||||
}
|
||||
if (s->level != level) {
|
||||
s->level = level;
|
||||
|
@ -562,19 +642,22 @@ local void putShortMSB (s, b)
|
|||
local void flush_pending(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
unsigned len = strm->state->pending;
|
||||
unsigned len;
|
||||
deflate_state *s = strm->state;
|
||||
|
||||
_tr_flush_bits(s);
|
||||
len = s->pending;
|
||||
if (len > strm->avail_out) len = strm->avail_out;
|
||||
if (len == 0) return;
|
||||
|
||||
zmemcpy(strm->next_out, strm->state->pending_out, len);
|
||||
zmemcpy(strm->next_out, s->pending_out, len);
|
||||
strm->next_out += len;
|
||||
strm->state->pending_out += len;
|
||||
s->pending_out += len;
|
||||
strm->total_out += len;
|
||||
strm->avail_out -= len;
|
||||
strm->state->pending -= len;
|
||||
if (strm->state->pending == 0) {
|
||||
strm->state->pending_out = strm->state->pending_buf;
|
||||
s->pending -= len;
|
||||
if (s->pending == 0) {
|
||||
s->pending_out = s->pending_buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -801,7 +884,7 @@ int ZEXPORT deflate (strm, flush)
|
|||
* flushes. For repeated and useless calls with Z_FINISH, we keep
|
||||
* returning Z_STREAM_END instead of Z_BUF_ERROR.
|
||||
*/
|
||||
} else if (strm->avail_in == 0 && flush <= old_flush &&
|
||||
} else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
|
||||
flush != Z_FINISH) {
|
||||
ERR_RETURN(strm, Z_BUF_ERROR);
|
||||
}
|
||||
|
@ -850,6 +933,7 @@ int ZEXPORT deflate (strm, flush)
|
|||
if (s->lookahead == 0) {
|
||||
s->strstart = 0;
|
||||
s->block_start = 0L;
|
||||
s->insert = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -945,12 +1029,12 @@ int ZEXPORT deflateCopy (dest, source)
|
|||
|
||||
ss = source->state;
|
||||
|
||||
zmemcpy(dest, source, sizeof(z_stream));
|
||||
zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
|
||||
|
||||
ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
|
||||
if (ds == Z_NULL) return Z_MEM_ERROR;
|
||||
dest->state = (struct internal_state FAR *) ds;
|
||||
zmemcpy(ds, ss, sizeof(deflate_state));
|
||||
zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
|
||||
ds->strm = dest;
|
||||
|
||||
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
|
||||
|
@ -966,8 +1050,8 @@ int ZEXPORT deflateCopy (dest, source)
|
|||
}
|
||||
/* following zmemcpy do not work for 16-bit MSDOS */
|
||||
zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
|
||||
zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
|
||||
zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
|
||||
zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
|
||||
zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
|
||||
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
|
||||
|
||||
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
|
||||
|
@ -1001,15 +1085,15 @@ local int read_buf(strm, buf, size)
|
|||
|
||||
strm->avail_in -= len;
|
||||
|
||||
zmemcpy(buf, strm->next_in, len);
|
||||
if (strm->state->wrap == 1) {
|
||||
strm->adler = adler32(strm->adler, strm->next_in, len);
|
||||
strm->adler = adler32(strm->adler, buf, len);
|
||||
}
|
||||
#ifdef GZIP
|
||||
else if (strm->state->wrap == 2) {
|
||||
strm->adler = crc32(strm->adler, strm->next_in, len);
|
||||
strm->adler = crc32(strm->adler, buf, len);
|
||||
}
|
||||
#endif
|
||||
zmemcpy(buf, strm->next_in, len);
|
||||
strm->next_in += len;
|
||||
strm->total_in += len;
|
||||
|
||||
|
@ -1036,6 +1120,7 @@ local void lm_init (s)
|
|||
s->strstart = 0;
|
||||
s->block_start = 0L;
|
||||
s->lookahead = 0;
|
||||
s->insert = 0;
|
||||
s->match_length = s->prev_length = MIN_MATCH-1;
|
||||
s->match_available = 0;
|
||||
s->ins_h = 0;
|
||||
|
@ -1310,6 +1395,8 @@ local void fill_window(s)
|
|||
unsigned more; /* Amount of free space at the end of the window. */
|
||||
uInt wsize = s->w_size;
|
||||
|
||||
Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
|
||||
|
||||
do {
|
||||
more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
|
||||
|
||||
|
@ -1362,7 +1449,7 @@ local void fill_window(s)
|
|||
#endif
|
||||
more += wsize;
|
||||
}
|
||||
if (s->strm->avail_in == 0) return;
|
||||
if (s->strm->avail_in == 0) break;
|
||||
|
||||
/* If there was no sliding:
|
||||
* strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
|
||||
|
@ -1381,12 +1468,24 @@ local void fill_window(s)
|
|||
s->lookahead += n;
|
||||
|
||||
/* Initialize the hash value now that we have some input: */
|
||||
if (s->lookahead >= MIN_MATCH) {
|
||||
s->ins_h = s->window[s->strstart];
|
||||
UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
|
||||
if (s->lookahead + s->insert >= MIN_MATCH) {
|
||||
uInt str = s->strstart - s->insert;
|
||||
s->ins_h = s->window[str];
|
||||
UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
|
||||
#if MIN_MATCH != 3
|
||||
Call UPDATE_HASH() MIN_MATCH-3 more times
|
||||
#endif
|
||||
while (s->insert) {
|
||||
UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
|
||||
#ifndef FASTEST
|
||||
s->prev[str & s->w_mask] = s->head[s->ins_h];
|
||||
#endif
|
||||
s->head[s->ins_h] = (Pos)str;
|
||||
str++;
|
||||
s->insert--;
|
||||
if (s->lookahead + s->insert < MIN_MATCH)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
|
||||
* but this is not important since only literal bytes will be emitted.
|
||||
|
@ -1427,6 +1526,9 @@ local void fill_window(s)
|
|||
s->high_water += init;
|
||||
}
|
||||
}
|
||||
|
||||
Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
|
||||
"not enough room for search");
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
|
@ -1506,8 +1608,14 @@ local block_state deflate_stored(s, flush)
|
|||
FLUSH_BLOCK(s, 0);
|
||||
}
|
||||
}
|
||||
FLUSH_BLOCK(s, flush == Z_FINISH);
|
||||
return flush == Z_FINISH ? finish_done : block_done;
|
||||
s->insert = 0;
|
||||
if (flush == Z_FINISH) {
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if ((long)s->strstart > s->block_start)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
|
@ -1603,8 +1711,14 @@ local block_state deflate_fast(s, flush)
|
|||
}
|
||||
if (bflush) FLUSH_BLOCK(s, 0);
|
||||
}
|
||||
FLUSH_BLOCK(s, flush == Z_FINISH);
|
||||
return flush == Z_FINISH ? finish_done : block_done;
|
||||
s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
|
||||
if (flush == Z_FINISH) {
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
|
||||
#ifndef FASTEST
|
||||
|
@ -1728,8 +1842,14 @@ local block_state deflate_slow(s, flush)
|
|||
_tr_tally_lit(s, s->window[s->strstart-1], bflush);
|
||||
s->match_available = 0;
|
||||
}
|
||||
FLUSH_BLOCK(s, flush == Z_FINISH);
|
||||
return flush == Z_FINISH ? finish_done : block_done;
|
||||
s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
|
||||
if (flush == Z_FINISH) {
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
#endif /* FASTEST */
|
||||
|
||||
|
@ -1749,11 +1869,11 @@ local block_state deflate_rle(s, flush)
|
|||
for (;;) {
|
||||
/* Make sure that we always have enough lookahead, except
|
||||
* at the end of the input file. We need MAX_MATCH bytes
|
||||
* for the longest encodable run.
|
||||
* for the longest run, plus one for the unrolled loop.
|
||||
*/
|
||||
if (s->lookahead < MAX_MATCH) {
|
||||
if (s->lookahead <= MAX_MATCH) {
|
||||
fill_window(s);
|
||||
if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
|
||||
if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
|
||||
return need_more;
|
||||
}
|
||||
if (s->lookahead == 0) break; /* flush the current block */
|
||||
|
@ -1776,6 +1896,7 @@ local block_state deflate_rle(s, flush)
|
|||
if (s->match_length > s->lookahead)
|
||||
s->match_length = s->lookahead;
|
||||
}
|
||||
Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
|
||||
}
|
||||
|
||||
/* Emit match if have run of MIN_MATCH or longer, else emit literal */
|
||||
|
@ -1796,8 +1917,14 @@ local block_state deflate_rle(s, flush)
|
|||
}
|
||||
if (bflush) FLUSH_BLOCK(s, 0);
|
||||
}
|
||||
FLUSH_BLOCK(s, flush == Z_FINISH);
|
||||
return flush == Z_FINISH ? finish_done : block_done;
|
||||
s->insert = 0;
|
||||
if (flush == Z_FINISH) {
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
|
@ -1829,6 +1956,12 @@ local block_state deflate_huff(s, flush)
|
|||
s->strstart++;
|
||||
if (bflush) FLUSH_BLOCK(s, 0);
|
||||
}
|
||||
FLUSH_BLOCK(s, flush == Z_FINISH);
|
||||
return flush == Z_FINISH ? finish_done : block_done;
|
||||
s->insert = 0;
|
||||
if (flush == Z_FINISH) {
|
||||
FLUSH_BLOCK(s, 1);
|
||||
return finish_done;
|
||||
}
|
||||
if (s->last_lit)
|
||||
FLUSH_BLOCK(s, 0);
|
||||
return block_done;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly
|
||||
* Copyright (C) 1995-2012 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -48,6 +48,9 @@
|
|||
#define MAX_BITS 15
|
||||
/* All codes must not exceed MAX_BITS bits */
|
||||
|
||||
#define Buf_size 16
|
||||
/* size of bit buffer in bi_buf */
|
||||
|
||||
#define INIT_STATE 42
|
||||
#define EXTRA_STATE 69
|
||||
#define NAME_STATE 73
|
||||
|
@ -101,7 +104,7 @@ typedef struct internal_state {
|
|||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
gz_headerp gzhead; /* gzip header information to write */
|
||||
uInt gzindex; /* where in extra, name, or comment */
|
||||
Byte method; /* STORED (for zip only) or DEFLATED */
|
||||
Byte method; /* can only be DEFLATED */
|
||||
int last_flush; /* value of flush param for previous deflate call */
|
||||
|
||||
/* used by deflate.c: */
|
||||
|
@ -188,7 +191,7 @@ typedef struct internal_state {
|
|||
int nice_match; /* Stop searching when current match exceeds this */
|
||||
|
||||
/* used by trees.c: */
|
||||
/* Didn't use ct_data typedef below to supress compiler warning */
|
||||
/* Didn't use ct_data typedef below to suppress compiler warning */
|
||||
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
||||
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
||||
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
||||
|
@ -244,7 +247,7 @@ typedef struct internal_state {
|
|||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
uInt matches; /* number of string matches in current block */
|
||||
int last_eob_len; /* bit length of EOB code for last block */
|
||||
uInt insert; /* bytes at end of window left to insert */
|
||||
|
||||
#ifdef DEBUG
|
||||
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
|
||||
|
@ -294,6 +297,7 @@ void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
|
|||
int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
|
||||
void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
|
||||
ulg stored_len, int last));
|
||||
void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
|
||||
void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
|
||||
void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
|
||||
ulg stored_len, int last));
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/* gzclose.c -- zlib gzclose() function
|
||||
* Copyright (C) 2004, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* gzclose() is in a separate file so that it is linked in only if it is used.
|
||||
That way the other gzclose functions can be used instead to avoid linking in
|
||||
unneeded compression or decompression routines. */
|
||||
int ZEXPORT gzclose(file)
|
||||
gzFile file;
|
||||
{
|
||||
#ifndef NO_GZCOMPRESS
|
||||
gz_statep state;
|
||||
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
|
||||
#else
|
||||
return gzclose_r(file);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef _LARGEFILE64_SOURCE
|
||||
# ifndef _LARGEFILE_SOURCE
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
# endif
|
||||
# ifdef _FILE_OFFSET_BITS
|
||||
# undef _FILE_OFFSET_BITS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
# define ZLIB_INTERNAL
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "zlib.h"
|
||||
#ifdef STDC
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <limits.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
|
||||
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef WINAPI_FAMILY
|
||||
# define open _open
|
||||
# define read _read
|
||||
# define write _write
|
||||
# define close _close
|
||||
#endif
|
||||
|
||||
#ifdef NO_DEFLATE /* for compatibility with old definition */
|
||||
# define NO_GZCOMPRESS
|
||||
#endif
|
||||
|
||||
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
# ifdef MSDOS
|
||||
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
|
||||
but for now we just assume it doesn't. */
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __TURBOC__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef WIN32
|
||||
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
|
||||
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
|
||||
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __SASC
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef VMS
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __OS400__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __MVS__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* unlike snprintf (which is required in C99, yet still not supported by
|
||||
Microsoft more than a decade later!), _snprintf does not guarantee null
|
||||
termination of the result -- however this is only used in gzlib.c where
|
||||
the result is assured to fit in the space provided */
|
||||
#ifdef _MSC_VER
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
||||
|
||||
/* gz* functions always use library allocation functions */
|
||||
#ifndef STDC
|
||||
extern voidp malloc OF((uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
/* get errno and strerror definition */
|
||||
#if defined UNDER_CE
|
||||
# include <windows.h>
|
||||
# define zstrerror() gz_strwinerror((DWORD)GetLastError())
|
||||
#else
|
||||
# ifndef NO_STRERROR
|
||||
# include <errno.h>
|
||||
# define zstrerror() strerror(errno)
|
||||
# else
|
||||
# define zstrerror() "stdio error (consult errno)"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* provide prototypes for these when building zlib without LFS */
|
||||
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
|
||||
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
|
||||
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
|
||||
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
|
||||
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
|
||||
#endif
|
||||
|
||||
/* default memLevel */
|
||||
#if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
#else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
#endif
|
||||
|
||||
/* default i/o buffer size -- double this for output when reading (this and
|
||||
twice this must be able to fit in an unsigned type) */
|
||||
#define GZBUFSIZE 8192
|
||||
|
||||
/* gzip modes, also provide a little integrity check on the passed structure */
|
||||
#define GZ_NONE 0
|
||||
#define GZ_READ 7247
|
||||
#define GZ_WRITE 31153
|
||||
#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
|
||||
|
||||
/* values for gz_state how */
|
||||
#define LOOK 0 /* look for a gzip header */
|
||||
#define COPY 1 /* copy input directly */
|
||||
#define GZIP 2 /* decompress a gzip stream */
|
||||
|
||||
/* internal gzip file state data structure */
|
||||
typedef struct {
|
||||
/* exposed contents for gzgetc() macro */
|
||||
struct gzFile_s x; /* "x" for exposed */
|
||||
/* x.have: number of bytes available at x.next */
|
||||
/* x.next: next output data to deliver or write */
|
||||
/* x.pos: current position in uncompressed data */
|
||||
/* used for both reading and writing */
|
||||
int mode; /* see gzip modes above */
|
||||
int fd; /* file descriptor */
|
||||
char *path; /* path or fd for error messages */
|
||||
unsigned size; /* buffer size, zero if not allocated yet */
|
||||
unsigned want; /* requested buffer size, default is GZBUFSIZE */
|
||||
unsigned char *in; /* input buffer */
|
||||
unsigned char *out; /* output buffer (double-sized when reading) */
|
||||
int direct; /* 0 if processing gzip, 1 if transparent */
|
||||
/* just for reading */
|
||||
int how; /* 0: get header, 1: copy, 2: decompress */
|
||||
z_off64_t start; /* where the gzip data started, for rewinding */
|
||||
int eof; /* true if end of input file reached */
|
||||
int past; /* true if read requested past end */
|
||||
/* just for writing */
|
||||
int level; /* compression level */
|
||||
int strategy; /* compression strategy */
|
||||
/* seek request */
|
||||
z_off64_t skip; /* amount to skip (already rewound if backwards) */
|
||||
int seek; /* true if seek request pending */
|
||||
/* error information */
|
||||
int err; /* error code */
|
||||
char *msg; /* error message */
|
||||
/* zlib inflate or deflate stream */
|
||||
z_stream strm; /* stream structure in-place (not a pointer) */
|
||||
} gz_state;
|
||||
typedef gz_state FAR *gz_statep;
|
||||
|
||||
/* shared functions */
|
||||
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
|
||||
#if defined UNDER_CE
|
||||
char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
|
||||
#endif
|
||||
|
||||
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
|
||||
value -- needed when comparing unsigned to z_off64_t, which is signed
|
||||
(possible z_off64_t types off_t, off64_t, and long are all signed) */
|
||||
#ifdef INT_MAX
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
|
||||
#else
|
||||
unsigned ZLIB_INTERNAL gz_intmax OF((void));
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
|
||||
#endif
|
|
@ -0,0 +1,634 @@
|
|||
/* gzlib.c -- zlib functions common to reading and writing gzip files
|
||||
* Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__BORLANDC__)
|
||||
# define LSEEK _lseeki64
|
||||
#else
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
# define LSEEK lseek64
|
||||
#else
|
||||
# define LSEEK lseek
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Local functions */
|
||||
local void gz_reset OF((gz_statep));
|
||||
local gzFile gz_open OF((const void *, int, const char *));
|
||||
|
||||
#if defined UNDER_CE
|
||||
|
||||
/* Map the Windows error number in ERROR to a locale-dependent error message
|
||||
string and return a pointer to it. Typically, the values for ERROR come
|
||||
from GetLastError.
|
||||
|
||||
The string pointed to shall not be modified by the application, but may be
|
||||
overwritten by a subsequent call to gz_strwinerror
|
||||
|
||||
The gz_strwinerror function does not change the current setting of
|
||||
GetLastError. */
|
||||
char ZLIB_INTERNAL *gz_strwinerror (error)
|
||||
DWORD error;
|
||||
{
|
||||
static char buf[1024];
|
||||
|
||||
wchar_t *msgbuf;
|
||||
DWORD lasterr = GetLastError();
|
||||
DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||
NULL,
|
||||
error,
|
||||
0, /* Default language */
|
||||
(LPVOID)&msgbuf,
|
||||
0,
|
||||
NULL);
|
||||
if (chars != 0) {
|
||||
/* If there is an \r\n appended, zap it. */
|
||||
if (chars >= 2
|
||||
&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
|
||||
chars -= 2;
|
||||
msgbuf[chars] = 0;
|
||||
}
|
||||
|
||||
if (chars > sizeof (buf) - 1) {
|
||||
chars = sizeof (buf) - 1;
|
||||
msgbuf[chars] = 0;
|
||||
}
|
||||
|
||||
wcstombs(buf, msgbuf, chars + 1);
|
||||
LocalFree(msgbuf);
|
||||
}
|
||||
else {
|
||||
sprintf(buf, "unknown win32 error (%ld)", error);
|
||||
}
|
||||
|
||||
SetLastError(lasterr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* UNDER_CE */
|
||||
|
||||
/* Reset gzip file state */
|
||||
local void gz_reset(state)
|
||||
gz_statep state;
|
||||
{
|
||||
state->x.have = 0; /* no output data available */
|
||||
if (state->mode == GZ_READ) { /* for reading ... */
|
||||
state->eof = 0; /* not at end of file */
|
||||
state->past = 0; /* have not read past end yet */
|
||||
state->how = LOOK; /* look for gzip header */
|
||||
}
|
||||
state->seek = 0; /* no seek request pending */
|
||||
gz_error(state, Z_OK, NULL); /* clear error */
|
||||
state->x.pos = 0; /* no uncompressed data yet */
|
||||
state->strm.avail_in = 0; /* no input data yet */
|
||||
}
|
||||
|
||||
/* Open a gzip file either by name or file descriptor. */
|
||||
local gzFile gz_open(path, fd, mode)
|
||||
const void *path;
|
||||
int fd;
|
||||
const char *mode;
|
||||
{
|
||||
gz_statep state;
|
||||
size_t len;
|
||||
int oflag;
|
||||
#ifdef O_CLOEXEC
|
||||
int cloexec = 0;
|
||||
#endif
|
||||
#ifdef O_EXCL
|
||||
int exclusive = 0;
|
||||
#endif
|
||||
|
||||
/* check input */
|
||||
if (path == NULL)
|
||||
return NULL;
|
||||
|
||||
/* allocate gzFile structure to return */
|
||||
state = (gz_statep)malloc(sizeof(gz_state));
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
state->size = 0; /* no buffers allocated yet */
|
||||
state->want = GZBUFSIZE; /* requested buffer size */
|
||||
state->msg = NULL; /* no error message yet */
|
||||
|
||||
/* interpret mode */
|
||||
state->mode = GZ_NONE;
|
||||
state->level = Z_DEFAULT_COMPRESSION;
|
||||
state->strategy = Z_DEFAULT_STRATEGY;
|
||||
state->direct = 0;
|
||||
while (*mode) {
|
||||
if (*mode >= '0' && *mode <= '9')
|
||||
state->level = *mode - '0';
|
||||
else
|
||||
switch (*mode) {
|
||||
case 'r':
|
||||
state->mode = GZ_READ;
|
||||
break;
|
||||
#ifndef NO_GZCOMPRESS
|
||||
case 'w':
|
||||
state->mode = GZ_WRITE;
|
||||
break;
|
||||
case 'a':
|
||||
state->mode = GZ_APPEND;
|
||||
break;
|
||||
#endif
|
||||
case '+': /* can't read and write at the same time */
|
||||
free(state);
|
||||
return NULL;
|
||||
case 'b': /* ignore -- will request binary anyway */
|
||||
break;
|
||||
#ifdef O_CLOEXEC
|
||||
case 'e':
|
||||
cloexec = 1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef O_EXCL
|
||||
case 'x':
|
||||
exclusive = 1;
|
||||
break;
|
||||
#endif
|
||||
case 'f':
|
||||
state->strategy = Z_FILTERED;
|
||||
break;
|
||||
case 'h':
|
||||
state->strategy = Z_HUFFMAN_ONLY;
|
||||
break;
|
||||
case 'R':
|
||||
state->strategy = Z_RLE;
|
||||
break;
|
||||
case 'F':
|
||||
state->strategy = Z_FIXED;
|
||||
break;
|
||||
case 'T':
|
||||
state->direct = 1;
|
||||
break;
|
||||
default: /* could consider as an error, but just ignore */
|
||||
;
|
||||
}
|
||||
mode++;
|
||||
}
|
||||
|
||||
/* must provide an "r", "w", or "a" */
|
||||
if (state->mode == GZ_NONE) {
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* can't force transparent read */
|
||||
if (state->mode == GZ_READ) {
|
||||
if (state->direct) {
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
state->direct = 1; /* for empty file */
|
||||
}
|
||||
|
||||
/* save the path name for error messages */
|
||||
#ifdef _WIN32
|
||||
if (fd == -2) {
|
||||
len = wcstombs(NULL, path, 0);
|
||||
if (len == (size_t)-1)
|
||||
len = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
len = strlen((const char *)path);
|
||||
state->path = (char *)malloc(len + 1);
|
||||
if (state->path == NULL) {
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (fd == -2)
|
||||
if (len)
|
||||
wcstombs(state->path, path, len + 1);
|
||||
else
|
||||
*(state->path) = 0;
|
||||
else
|
||||
#endif
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(state->path, len + 1, "%s", (const char *)path);
|
||||
#else
|
||||
strcpy(state->path, path);
|
||||
#endif
|
||||
|
||||
/* compute the flags for open() */
|
||||
oflag =
|
||||
#ifdef O_LARGEFILE
|
||||
O_LARGEFILE |
|
||||
#endif
|
||||
#ifdef O_BINARY
|
||||
O_BINARY |
|
||||
#endif
|
||||
#ifdef O_CLOEXEC
|
||||
(cloexec ? O_CLOEXEC : 0) |
|
||||
#endif
|
||||
(state->mode == GZ_READ ?
|
||||
O_RDONLY :
|
||||
(O_WRONLY | O_CREAT |
|
||||
#ifdef O_EXCL
|
||||
(exclusive ? O_EXCL : 0) |
|
||||
#endif
|
||||
(state->mode == GZ_WRITE ?
|
||||
O_TRUNC :
|
||||
O_APPEND)));
|
||||
|
||||
/* open the file with the appropriate flags (or just use fd) */
|
||||
state->fd = fd > -1 ? fd : (
|
||||
#ifdef _WIN32
|
||||
fd == -2 ? _wopen(path, oflag, 0666) :
|
||||
#endif
|
||||
open((const char *)path, oflag, 0666));
|
||||
if (state->fd == -1) {
|
||||
free(state->path);
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
if (state->mode == GZ_APPEND)
|
||||
state->mode = GZ_WRITE; /* simplify later checks */
|
||||
|
||||
/* save the current position for rewinding (only if reading) */
|
||||
if (state->mode == GZ_READ) {
|
||||
state->start = LSEEK(state->fd, 0, SEEK_CUR);
|
||||
if (state->start == -1) state->start = 0;
|
||||
}
|
||||
|
||||
/* initialize stream */
|
||||
gz_reset(state);
|
||||
|
||||
/* return stream */
|
||||
return (gzFile)state;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzopen(path, mode)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzopen64(path, mode)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open(path, -1, mode);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
gzFile ZEXPORT gzdopen(fd, mode)
|
||||
int fd;
|
||||
const char *mode;
|
||||
{
|
||||
char *path; /* identifier for error messages */
|
||||
gzFile gz;
|
||||
|
||||
if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
|
||||
return NULL;
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
|
||||
#else
|
||||
sprintf(path, "<fd:%d>", fd); /* for debugging */
|
||||
#endif
|
||||
gz = gz_open(path, fd, mode);
|
||||
free(path);
|
||||
return gz;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
#ifdef _WIN32
|
||||
gzFile ZEXPORT gzopen_w(path, mode)
|
||||
const wchar_t *path;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open(path, -2, mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzbuffer(file, size)
|
||||
gzFile file;
|
||||
unsigned size;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* make sure we haven't already allocated memory */
|
||||
if (state->size != 0)
|
||||
return -1;
|
||||
|
||||
/* check and set requested size */
|
||||
if (size < 2)
|
||||
size = 2; /* need two bytes to check magic header */
|
||||
state->want = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzrewind(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no error */
|
||||
if (state->mode != GZ_READ ||
|
||||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* back up and start over */
|
||||
if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
|
||||
return -1;
|
||||
gz_reset(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gzseek64(file, offset, whence)
|
||||
gzFile file;
|
||||
z_off64_t offset;
|
||||
int whence;
|
||||
{
|
||||
unsigned n;
|
||||
z_off64_t ret;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* check that there's no error */
|
||||
if (state->err != Z_OK && state->err != Z_BUF_ERROR)
|
||||
return -1;
|
||||
|
||||
/* can only seek from start or relative to current position */
|
||||
if (whence != SEEK_SET && whence != SEEK_CUR)
|
||||
return -1;
|
||||
|
||||
/* normalize offset to a SEEK_CUR specification */
|
||||
if (whence == SEEK_SET)
|
||||
offset -= state->x.pos;
|
||||
else if (state->seek)
|
||||
offset += state->skip;
|
||||
state->seek = 0;
|
||||
|
||||
/* if within raw area while reading, just go there */
|
||||
if (state->mode == GZ_READ && state->how == COPY &&
|
||||
state->x.pos + offset >= 0) {
|
||||
ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
state->x.have = 0;
|
||||
state->eof = 0;
|
||||
state->past = 0;
|
||||
state->seek = 0;
|
||||
gz_error(state, Z_OK, NULL);
|
||||
state->strm.avail_in = 0;
|
||||
state->x.pos += offset;
|
||||
return state->x.pos;
|
||||
}
|
||||
|
||||
/* calculate skip amount, rewinding if needed for back seek when reading */
|
||||
if (offset < 0) {
|
||||
if (state->mode != GZ_READ) /* writing -- can't go backwards */
|
||||
return -1;
|
||||
offset += state->x.pos;
|
||||
if (offset < 0) /* before start of file! */
|
||||
return -1;
|
||||
if (gzrewind(file) == -1) /* rewind, then skip to offset */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if reading, skip what's in output buffer (one less gzgetc() check) */
|
||||
if (state->mode == GZ_READ) {
|
||||
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
|
||||
(unsigned)offset : state->x.have;
|
||||
state->x.have -= n;
|
||||
state->x.next += n;
|
||||
state->x.pos += n;
|
||||
offset -= n;
|
||||
}
|
||||
|
||||
/* request skip (if not zero) */
|
||||
if (offset) {
|
||||
state->seek = 1;
|
||||
state->skip = offset;
|
||||
}
|
||||
return state->x.pos + offset;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gzseek(file, offset, whence)
|
||||
gzFile file;
|
||||
z_off_t offset;
|
||||
int whence;
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gzseek64(file, (z_off64_t)offset, whence);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gztell64(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* return position */
|
||||
return state->x.pos + (state->seek ? state->skip : 0);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gztell(file)
|
||||
gzFile file;
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gztell64(file);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off64_t ZEXPORT gzoffset64(file)
|
||||
gzFile file;
|
||||
{
|
||||
z_off64_t offset;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return -1;
|
||||
|
||||
/* compute and return effective offset in file */
|
||||
offset = LSEEK(state->fd, 0, SEEK_CUR);
|
||||
if (offset == -1)
|
||||
return -1;
|
||||
if (state->mode == GZ_READ) /* reading */
|
||||
offset -= state->strm.avail_in; /* don't count buffered input */
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
z_off_t ZEXPORT gzoffset(file)
|
||||
gzFile file;
|
||||
{
|
||||
z_off64_t ret;
|
||||
|
||||
ret = gzoffset64(file);
|
||||
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzeof(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return 0;
|
||||
|
||||
/* return end-of-file state */
|
||||
return state->mode == GZ_READ ? state->past : 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
const char * ZEXPORT gzerror(file, errnum)
|
||||
gzFile file;
|
||||
int *errnum;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return NULL;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return NULL;
|
||||
|
||||
/* return error information */
|
||||
if (errnum != NULL)
|
||||
*errnum = state->err;
|
||||
return state->err == Z_MEM_ERROR ? "out of memory" :
|
||||
(state->msg == NULL ? "" : state->msg);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
void ZEXPORT gzclearerr(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure and check integrity */
|
||||
if (file == NULL)
|
||||
return;
|
||||
state = (gz_statep)file;
|
||||
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
|
||||
return;
|
||||
|
||||
/* clear error and end-of-file */
|
||||
if (state->mode == GZ_READ) {
|
||||
state->eof = 0;
|
||||
state->past = 0;
|
||||
}
|
||||
gz_error(state, Z_OK, NULL);
|
||||
}
|
||||
|
||||
/* Create an error message in allocated memory and set state->err and
|
||||
state->msg accordingly. Free any previous error message already there. Do
|
||||
not try to free or allocate space if the error is Z_MEM_ERROR (out of
|
||||
memory). Simply save the error message as a static string. If there is an
|
||||
allocation failure constructing the error message, then convert the error to
|
||||
out of memory. */
|
||||
void ZLIB_INTERNAL gz_error(state, err, msg)
|
||||
gz_statep state;
|
||||
int err;
|
||||
const char *msg;
|
||||
{
|
||||
/* free previously allocated message and clear */
|
||||
if (state->msg != NULL) {
|
||||
if (state->err != Z_MEM_ERROR)
|
||||
free(state->msg);
|
||||
state->msg = NULL;
|
||||
}
|
||||
|
||||
/* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
|
||||
if (err != Z_OK && err != Z_BUF_ERROR)
|
||||
state->x.have = 0;
|
||||
|
||||
/* set error code, and if no message, then done */
|
||||
state->err = err;
|
||||
if (msg == NULL)
|
||||
return;
|
||||
|
||||
/* for an out of memory error, return literal string when requested */
|
||||
if (err == Z_MEM_ERROR)
|
||||
return;
|
||||
|
||||
/* construct error message with path */
|
||||
if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
|
||||
NULL) {
|
||||
state->err = Z_MEM_ERROR;
|
||||
return;
|
||||
}
|
||||
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
|
||||
snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
|
||||
"%s%s%s", state->path, ": ", msg);
|
||||
#else
|
||||
strcpy(state->msg, state->path);
|
||||
strcat(state->msg, ": ");
|
||||
strcat(state->msg, msg);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef INT_MAX
|
||||
/* portably return maximum value for an int (when limits.h presumed not
|
||||
available) -- we need to do this to cover cases where 2's complement not
|
||||
used, since C standard permits 1's complement and sign-bit representations,
|
||||
otherwise we could just use ((unsigned)-1) >> 1 */
|
||||
unsigned ZLIB_INTERNAL gz_intmax()
|
||||
{
|
||||
unsigned p, q;
|
||||
|
||||
p = 1;
|
||||
do {
|
||||
q = p;
|
||||
p <<= 1;
|
||||
p++;
|
||||
} while (p > q);
|
||||
return q >> 1;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,594 @@
|
|||
/* gzread.c -- zlib functions for reading gzip files
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
|
||||
local int gz_avail OF((gz_statep));
|
||||
local int gz_look OF((gz_statep));
|
||||
local int gz_decomp OF((gz_statep));
|
||||
local int gz_fetch OF((gz_statep));
|
||||
local int gz_skip OF((gz_statep, z_off64_t));
|
||||
|
||||
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
|
||||
state->fd, and update state->eof, state->err, and state->msg as appropriate.
|
||||
This function needs to loop on read(), since read() is not guaranteed to
|
||||
read the number of bytes requested, depending on the type of descriptor. */
|
||||
local int gz_load(state, buf, len, have)
|
||||
gz_statep state;
|
||||
unsigned char *buf;
|
||||
unsigned len;
|
||||
unsigned *have;
|
||||
{
|
||||
int ret;
|
||||
|
||||
*have = 0;
|
||||
do {
|
||||
ret = read(state->fd, buf + *have, len - *have);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
*have += ret;
|
||||
} while (*have < len);
|
||||
if (ret < 0) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0)
|
||||
state->eof = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load up input buffer and set eof flag if last data loaded -- return -1 on
|
||||
error, 0 otherwise. Note that the eof flag is set when the end of the input
|
||||
file is reached, even though there may be unused data in the buffer. Once
|
||||
that data has been used, no more attempts will be made to read the file.
|
||||
If strm->avail_in != 0, then the current data is moved to the beginning of
|
||||
the input buffer, and then the remainder of the buffer is loaded with the
|
||||
available data from the input file. */
|
||||
local int gz_avail(state)
|
||||
gz_statep state;
|
||||
{
|
||||
unsigned got;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
if (state->err != Z_OK && state->err != Z_BUF_ERROR)
|
||||
return -1;
|
||||
if (state->eof == 0) {
|
||||
if (strm->avail_in) { /* copy what's there to the start */
|
||||
unsigned char *p = state->in;
|
||||
unsigned const char *q = strm->next_in;
|
||||
unsigned n = strm->avail_in;
|
||||
do {
|
||||
*p++ = *q++;
|
||||
} while (--n);
|
||||
}
|
||||
if (gz_load(state, state->in + strm->avail_in,
|
||||
state->size - strm->avail_in, &got) == -1)
|
||||
return -1;
|
||||
strm->avail_in += got;
|
||||
strm->next_in = state->in;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
|
||||
If this is the first time in, allocate required memory. state->how will be
|
||||
left unchanged if there is no more input data available, will be set to COPY
|
||||
if there is no gzip header and direct copying will be performed, or it will
|
||||
be set to GZIP for decompression. If direct copying, then leftover input
|
||||
data from the input buffer will be copied to the output buffer. In that
|
||||
case, all further file reads will be directly to either the output buffer or
|
||||
a user buffer. If decompressing, the inflate state will be initialized.
|
||||
gz_look() will return 0 on success or -1 on failure. */
|
||||
local int gz_look(state)
|
||||
gz_statep state;
|
||||
{
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* allocate read buffers and inflate memory */
|
||||
if (state->size == 0) {
|
||||
/* allocate buffers */
|
||||
state->in = (unsigned char *)malloc(state->want);
|
||||
state->out = (unsigned char *)malloc(state->want << 1);
|
||||
if (state->in == NULL || state->out == NULL) {
|
||||
if (state->out != NULL)
|
||||
free(state->out);
|
||||
if (state->in != NULL)
|
||||
free(state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
state->size = state->want;
|
||||
|
||||
/* allocate inflate memory */
|
||||
state->strm.zalloc = Z_NULL;
|
||||
state->strm.zfree = Z_NULL;
|
||||
state->strm.opaque = Z_NULL;
|
||||
state->strm.avail_in = 0;
|
||||
state->strm.next_in = Z_NULL;
|
||||
if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
|
||||
free(state->out);
|
||||
free(state->in);
|
||||
state->size = 0;
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* get at least the magic bytes in the input buffer */
|
||||
if (strm->avail_in < 2) {
|
||||
if (gz_avail(state) == -1)
|
||||
return -1;
|
||||
if (strm->avail_in == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* look for gzip magic bytes -- if there, do gzip decoding (note: there is
|
||||
a logical dilemma here when considering the case of a partially written
|
||||
gzip file, to wit, if a single 31 byte is written, then we cannot tell
|
||||
whether this is a single-byte file, or just a partially written gzip
|
||||
file -- for here we assume that if a gzip file is being written, then
|
||||
the header will be written in a single operation, so that reading a
|
||||
single byte is sufficient indication that it is not a gzip file) */
|
||||
if (strm->avail_in > 1 &&
|
||||
strm->next_in[0] == 31 && strm->next_in[1] == 139) {
|
||||
inflateReset(strm);
|
||||
state->how = GZIP;
|
||||
state->direct = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* no gzip header -- if we were decoding gzip before, then this is trailing
|
||||
garbage. Ignore the trailing garbage and finish. */
|
||||
if (state->direct == 0) {
|
||||
strm->avail_in = 0;
|
||||
state->eof = 1;
|
||||
state->x.have = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* doing raw i/o, copy any leftover input to output -- this assumes that
|
||||
the output buffer is larger than the input buffer, which also assures
|
||||
space for gzungetc() */
|
||||
state->x.next = state->out;
|
||||
if (strm->avail_in) {
|
||||
memcpy(state->x.next, strm->next_in, strm->avail_in);
|
||||
state->x.have = strm->avail_in;
|
||||
strm->avail_in = 0;
|
||||
}
|
||||
state->how = COPY;
|
||||
state->direct = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decompress from input to the provided next_out and avail_out in the state.
|
||||
On return, state->x.have and state->x.next point to the just decompressed
|
||||
data. If the gzip stream completes, state->how is reset to LOOK to look for
|
||||
the next gzip stream or raw data, once state->x.have is depleted. Returns 0
|
||||
on success, -1 on failure. */
|
||||
local int gz_decomp(state)
|
||||
gz_statep state;
|
||||
{
|
||||
int ret = Z_OK;
|
||||
unsigned had;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* fill output buffer up to end of deflate stream */
|
||||
had = strm->avail_out;
|
||||
do {
|
||||
/* get more input for inflate() */
|
||||
if (strm->avail_in == 0 && gz_avail(state) == -1)
|
||||
return -1;
|
||||
if (strm->avail_in == 0) {
|
||||
gz_error(state, Z_BUF_ERROR, "unexpected end of file");
|
||||
break;
|
||||
}
|
||||
|
||||
/* decompress and handle errors */
|
||||
ret = inflate(strm, Z_NO_FLUSH);
|
||||
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
|
||||
gz_error(state, Z_STREAM_ERROR,
|
||||
"internal error: inflate stream corrupt");
|
||||
return -1;
|
||||
}
|
||||
if (ret == Z_MEM_ERROR) {
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
|
||||
gz_error(state, Z_DATA_ERROR,
|
||||
strm->msg == NULL ? "compressed data error" : strm->msg);
|
||||
return -1;
|
||||
}
|
||||
} while (strm->avail_out && ret != Z_STREAM_END);
|
||||
|
||||
/* update available output */
|
||||
state->x.have = had - strm->avail_out;
|
||||
state->x.next = strm->next_out - state->x.have;
|
||||
|
||||
/* if the gzip stream completed successfully, look for another */
|
||||
if (ret == Z_STREAM_END)
|
||||
state->how = LOOK;
|
||||
|
||||
/* good decompression */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
|
||||
Data is either copied from the input file or decompressed from the input
|
||||
file depending on state->how. If state->how is LOOK, then a gzip header is
|
||||
looked for to determine whether to copy or decompress. Returns -1 on error,
|
||||
otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
|
||||
end of the input file has been reached and all data has been processed. */
|
||||
local int gz_fetch(state)
|
||||
gz_statep state;
|
||||
{
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
do {
|
||||
switch(state->how) {
|
||||
case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
|
||||
if (gz_look(state) == -1)
|
||||
return -1;
|
||||
if (state->how == LOOK)
|
||||
return 0;
|
||||
break;
|
||||
case COPY: /* -> COPY */
|
||||
if (gz_load(state, state->out, state->size << 1, &(state->x.have))
|
||||
== -1)
|
||||
return -1;
|
||||
state->x.next = state->out;
|
||||
return 0;
|
||||
case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
|
||||
strm->avail_out = state->size << 1;
|
||||
strm->next_out = state->out;
|
||||
if (gz_decomp(state) == -1)
|
||||
return -1;
|
||||
}
|
||||
} while (state->x.have == 0 && (!state->eof || strm->avail_in));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
|
||||
local int gz_skip(state, len)
|
||||
gz_statep state;
|
||||
z_off64_t len;
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
/* skip over len bytes or reach end-of-file, whichever comes first */
|
||||
while (len)
|
||||
/* skip over whatever is in output buffer */
|
||||
if (state->x.have) {
|
||||
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
|
||||
(unsigned)len : state->x.have;
|
||||
state->x.have -= n;
|
||||
state->x.next += n;
|
||||
state->x.pos += n;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
/* output buffer empty -- return if we're at the end of the input */
|
||||
else if (state->eof && state->strm.avail_in == 0)
|
||||
break;
|
||||
|
||||
/* need more data to skip -- load up output buffer */
|
||||
else {
|
||||
/* get more output, looking for header if required */
|
||||
if (gz_fetch(state) == -1)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzread(file, buf, len)
|
||||
gzFile file;
|
||||
voidp buf;
|
||||
unsigned len;
|
||||
{
|
||||
unsigned got, n;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state->mode != GZ_READ ||
|
||||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* since an int is returned, make sure len fits in one, otherwise return
|
||||
with an error (this avoids the flaw in the interface) */
|
||||
if ((int)len < 0) {
|
||||
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if len is zero, avoid unnecessary operations */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* process a skip request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_skip(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get len bytes to buf, or less than len if at the end */
|
||||
got = 0;
|
||||
do {
|
||||
/* first just try copying data from the output buffer */
|
||||
if (state->x.have) {
|
||||
n = state->x.have > len ? len : state->x.have;
|
||||
memcpy(buf, state->x.next, n);
|
||||
state->x.next += n;
|
||||
state->x.have -= n;
|
||||
}
|
||||
|
||||
/* output buffer empty -- return if we're at the end of the input */
|
||||
else if (state->eof && strm->avail_in == 0) {
|
||||
state->past = 1; /* tried to read past end */
|
||||
break;
|
||||
}
|
||||
|
||||
/* need output data -- for small len or new stream load up our output
|
||||
buffer */
|
||||
else if (state->how == LOOK || len < (state->size << 1)) {
|
||||
/* get more output, looking for header if required */
|
||||
if (gz_fetch(state) == -1)
|
||||
return -1;
|
||||
continue; /* no progress yet -- go back to copy above */
|
||||
/* the copy above assures that we will leave with space in the
|
||||
output buffer, allowing at least one gzungetc() to succeed */
|
||||
}
|
||||
|
||||
/* large len -- read directly into user buffer */
|
||||
else if (state->how == COPY) { /* read directly */
|
||||
if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* large len -- decompress directly into user buffer */
|
||||
else { /* state->how == GZIP */
|
||||
strm->avail_out = len;
|
||||
strm->next_out = (unsigned char *)buf;
|
||||
if (gz_decomp(state) == -1)
|
||||
return -1;
|
||||
n = state->x.have;
|
||||
state->x.have = 0;
|
||||
}
|
||||
|
||||
/* update progress */
|
||||
len -= n;
|
||||
buf = (char *)buf + n;
|
||||
got += n;
|
||||
state->x.pos += n;
|
||||
} while (len);
|
||||
|
||||
/* return number of bytes read into user buffer (will fit in int) */
|
||||
return (int)got;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
#ifdef Z_PREFIX_SET
|
||||
# undef z_gzgetc
|
||||
#else
|
||||
# undef gzgetc
|
||||
#endif
|
||||
int ZEXPORT gzgetc(file)
|
||||
gzFile file;
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[1];
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state->mode != GZ_READ ||
|
||||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* try output buffer (no need to check for skip request) */
|
||||
if (state->x.have) {
|
||||
state->x.have--;
|
||||
state->x.pos++;
|
||||
return *(state->x.next)++;
|
||||
}
|
||||
|
||||
/* nothing there -- try gzread() */
|
||||
ret = gzread(file, buf, 1);
|
||||
return ret < 1 ? -1 : buf[0];
|
||||
}
|
||||
|
||||
int ZEXPORT gzgetc_(file)
|
||||
gzFile file;
|
||||
{
|
||||
return gzgetc(file);
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzungetc(c, file)
|
||||
int c;
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state->mode != GZ_READ ||
|
||||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
|
||||
return -1;
|
||||
|
||||
/* process a skip request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_skip(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* can't push EOF */
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
/* if output buffer empty, put byte at end (allows more pushing) */
|
||||
if (state->x.have == 0) {
|
||||
state->x.have = 1;
|
||||
state->x.next = state->out + (state->size << 1) - 1;
|
||||
state->x.next[0] = c;
|
||||
state->x.pos--;
|
||||
state->past = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* if no room, give up (must have already done a gzungetc()) */
|
||||
if (state->x.have == (state->size << 1)) {
|
||||
gz_error(state, Z_DATA_ERROR, "out of room to push characters");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* slide output data if needed and insert byte before existing data */
|
||||
if (state->x.next == state->out) {
|
||||
unsigned char *src = state->out + state->x.have;
|
||||
unsigned char *dest = state->out + (state->size << 1);
|
||||
while (src > state->out)
|
||||
*--dest = *--src;
|
||||
state->x.next = dest;
|
||||
}
|
||||
state->x.have++;
|
||||
state->x.next--;
|
||||
state->x.next[0] = c;
|
||||
state->x.pos--;
|
||||
state->past = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
char * ZEXPORT gzgets(file, buf, len)
|
||||
gzFile file;
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
unsigned left, n;
|
||||
char *str;
|
||||
unsigned char *eol;
|
||||
gz_statep state;
|
||||
|
||||
/* check parameters and get internal structure */
|
||||
if (file == NULL || buf == NULL || len < 1)
|
||||
return NULL;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading and that there's no (serious) error */
|
||||
if (state->mode != GZ_READ ||
|
||||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
|
||||
return NULL;
|
||||
|
||||
/* process a skip request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_skip(state, state->skip) == -1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy output bytes up to new line or len - 1, whichever comes first --
|
||||
append a terminating zero to the string (we don't check for a zero in
|
||||
the contents, let the user worry about that) */
|
||||
str = buf;
|
||||
left = (unsigned)len - 1;
|
||||
if (left) do {
|
||||
/* assure that something is in the output buffer */
|
||||
if (state->x.have == 0 && gz_fetch(state) == -1)
|
||||
return NULL; /* error */
|
||||
if (state->x.have == 0) { /* end of file */
|
||||
state->past = 1; /* read past end */
|
||||
break; /* return what we have */
|
||||
}
|
||||
|
||||
/* look for end-of-line in current output buffer */
|
||||
n = state->x.have > left ? left : state->x.have;
|
||||
eol = (unsigned char *)memchr(state->x.next, '\n', n);
|
||||
if (eol != NULL)
|
||||
n = (unsigned)(eol - state->x.next) + 1;
|
||||
|
||||
/* copy through end-of-line, or remainder if not found */
|
||||
memcpy(buf, state->x.next, n);
|
||||
state->x.have -= n;
|
||||
state->x.next += n;
|
||||
state->x.pos += n;
|
||||
left -= n;
|
||||
buf += n;
|
||||
} while (left && eol == NULL);
|
||||
|
||||
/* return terminated string, or if nothing, end of file */
|
||||
if (buf == str)
|
||||
return NULL;
|
||||
buf[0] = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzdirect(file)
|
||||
gzFile file;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* if the state is not known, but we can find out, then do so (this is
|
||||
mainly for right after a gzopen() or gzdopen()) */
|
||||
if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
|
||||
(void)gz_look(state);
|
||||
|
||||
/* return 1 if transparent, 0 if processing a gzip stream */
|
||||
return state->direct;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzclose_r(file)
|
||||
gzFile file;
|
||||
{
|
||||
int ret, err;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're reading */
|
||||
if (state->mode != GZ_READ)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* free memory and close file */
|
||||
if (state->size) {
|
||||
inflateEnd(&(state->strm));
|
||||
free(state->out);
|
||||
free(state->in);
|
||||
}
|
||||
err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
|
||||
gz_error(state, Z_OK, NULL);
|
||||
free(state->path);
|
||||
ret = close(state->fd);
|
||||
free(state);
|
||||
return ret ? Z_ERRNO : err;
|
||||
}
|
|
@ -0,0 +1,577 @@
|
|||
/* gzwrite.c -- zlib functions for writing gzip files
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "gzguts.h"
|
||||
|
||||
/* Local functions */
|
||||
local int gz_init OF((gz_statep));
|
||||
local int gz_comp OF((gz_statep, int));
|
||||
local int gz_zero OF((gz_statep, z_off64_t));
|
||||
|
||||
/* Initialize state for writing a gzip file. Mark initialization by setting
|
||||
state->size to non-zero. Return -1 on failure or 0 on success. */
|
||||
local int gz_init(state)
|
||||
gz_statep state;
|
||||
{
|
||||
int ret;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* allocate input buffer */
|
||||
state->in = (unsigned char *)malloc(state->want);
|
||||
if (state->in == NULL) {
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* only need output buffer and deflate state if compressing */
|
||||
if (!state->direct) {
|
||||
/* allocate output buffer */
|
||||
state->out = (unsigned char *)malloc(state->want);
|
||||
if (state->out == NULL) {
|
||||
free(state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* allocate deflate memory, set up for gzip compression */
|
||||
strm->zalloc = Z_NULL;
|
||||
strm->zfree = Z_NULL;
|
||||
strm->opaque = Z_NULL;
|
||||
ret = deflateInit2(strm, state->level, Z_DEFLATED,
|
||||
MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
|
||||
if (ret != Z_OK) {
|
||||
free(state->out);
|
||||
free(state->in);
|
||||
gz_error(state, Z_MEM_ERROR, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* mark state as initialized */
|
||||
state->size = state->want;
|
||||
|
||||
/* initialize write buffer if compressing */
|
||||
if (!state->direct) {
|
||||
strm->avail_out = state->size;
|
||||
strm->next_out = state->out;
|
||||
state->x.next = strm->next_out;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compress whatever is at avail_in and next_in and write to the output file.
|
||||
Return -1 if there is an error writing to the output file, otherwise 0.
|
||||
flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
|
||||
then the deflate() state is reset to start a new gzip stream. If gz->direct
|
||||
is true, then simply write to the output file without compressing, and
|
||||
ignore flush. */
|
||||
local int gz_comp(state, flush)
|
||||
gz_statep state;
|
||||
int flush;
|
||||
{
|
||||
int ret, got;
|
||||
unsigned have;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* allocate memory if this is the first time through */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return -1;
|
||||
|
||||
/* write directly if requested */
|
||||
if (state->direct) {
|
||||
got = write(state->fd, strm->next_in, strm->avail_in);
|
||||
if (got < 0 || (unsigned)got != strm->avail_in) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
strm->avail_in = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* run deflate() on provided input until it produces no more output */
|
||||
ret = Z_OK;
|
||||
do {
|
||||
/* write out current buffer contents if full, or if flushing, but if
|
||||
doing Z_FINISH then don't write until we get to Z_STREAM_END */
|
||||
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
|
||||
(flush != Z_FINISH || ret == Z_STREAM_END))) {
|
||||
have = (unsigned)(strm->next_out - state->x.next);
|
||||
if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
|
||||
(unsigned)got != have)) {
|
||||
gz_error(state, Z_ERRNO, zstrerror());
|
||||
return -1;
|
||||
}
|
||||
if (strm->avail_out == 0) {
|
||||
strm->avail_out = state->size;
|
||||
strm->next_out = state->out;
|
||||
}
|
||||
state->x.next = strm->next_out;
|
||||
}
|
||||
|
||||
/* compress */
|
||||
have = strm->avail_out;
|
||||
ret = deflate(strm, flush);
|
||||
if (ret == Z_STREAM_ERROR) {
|
||||
gz_error(state, Z_STREAM_ERROR,
|
||||
"internal error: deflate stream corrupt");
|
||||
return -1;
|
||||
}
|
||||
have -= strm->avail_out;
|
||||
} while (have);
|
||||
|
||||
/* if that completed a deflate stream, allow another to start */
|
||||
if (flush == Z_FINISH)
|
||||
deflateReset(strm);
|
||||
|
||||
/* all done, no errors */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compress len zeros to output. Return -1 on error, 0 on success. */
|
||||
local int gz_zero(state, len)
|
||||
gz_statep state;
|
||||
z_off64_t len;
|
||||
{
|
||||
int first;
|
||||
unsigned n;
|
||||
z_streamp strm = &(state->strm);
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return -1;
|
||||
|
||||
/* compress len zeros (len guaranteed > 0) */
|
||||
first = 1;
|
||||
while (len) {
|
||||
n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
|
||||
(unsigned)len : state->size;
|
||||
if (first) {
|
||||
memset(state->in, 0, n);
|
||||
first = 0;
|
||||
}
|
||||
strm->avail_in = n;
|
||||
strm->next_in = state->in;
|
||||
state->x.pos += n;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return -1;
|
||||
len -= n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzwrite(file, buf, len)
|
||||
gzFile file;
|
||||
voidpc buf;
|
||||
unsigned len;
|
||||
{
|
||||
unsigned put = len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return 0;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* since an int is returned, make sure len fits in one, otherwise return
|
||||
with an error (this avoids the flaw in the interface) */
|
||||
if ((int)len < 0) {
|
||||
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if len is zero, avoid unnecessary operations */
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
/* allocate memory if this is the first time through */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* for small len, copy to input buffer, otherwise compress directly */
|
||||
if (len < state->size) {
|
||||
/* copy to input buffer, compress when full */
|
||||
do {
|
||||
unsigned have, copy;
|
||||
|
||||
if (strm->avail_in == 0)
|
||||
strm->next_in = state->in;
|
||||
have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
|
||||
copy = state->size - have;
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
memcpy(state->in + have, buf, copy);
|
||||
strm->avail_in += copy;
|
||||
state->x.pos += copy;
|
||||
buf = (const char *)buf + copy;
|
||||
len -= copy;
|
||||
if (len && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
} while (len);
|
||||
}
|
||||
else {
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* directly compress user buffer to file */
|
||||
strm->avail_in = len;
|
||||
strm->next_in = (z_const Bytef *)buf;
|
||||
state->x.pos += len;
|
||||
if (gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* input was all buffered or compressed (put will fit in int) */
|
||||
return (int)put;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzputc(file, c)
|
||||
gzFile file;
|
||||
int c;
|
||||
{
|
||||
unsigned have;
|
||||
unsigned char buf[1];
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return -1;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* try writing to input buffer for speed (state->size == 0 if buffer not
|
||||
initialized) */
|
||||
if (state->size) {
|
||||
if (strm->avail_in == 0)
|
||||
strm->next_in = state->in;
|
||||
have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
|
||||
if (have < state->size) {
|
||||
state->in[have] = c;
|
||||
strm->avail_in++;
|
||||
state->x.pos++;
|
||||
return c & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* no room in buffer or not initialized, use gz_write() */
|
||||
buf[0] = c;
|
||||
if (gzwrite(file, buf, 1) != 1)
|
||||
return -1;
|
||||
return c & 0xff;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzputs(file, str)
|
||||
gzFile file;
|
||||
const char *str;
|
||||
{
|
||||
int ret;
|
||||
unsigned len;
|
||||
|
||||
/* write string */
|
||||
len = (unsigned)strlen(str);
|
||||
ret = gzwrite(file, str, len);
|
||||
return ret == 0 && len != 0 ? -1 : ret;
|
||||
}
|
||||
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
#include <stdarg.h>
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
|
||||
{
|
||||
int size, len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* make sure we have some buffer space */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* do the printf() into the input buffer, put length in len */
|
||||
size = (int)(state->size);
|
||||
state->in[size - 1] = 0;
|
||||
#ifdef NO_vsnprintf
|
||||
# ifdef HAS_vsprintf_void
|
||||
(void)vsprintf((char *)(state->in), format, va);
|
||||
for (len = 0; len < size; len++)
|
||||
if (state->in[len] == 0) break;
|
||||
# else
|
||||
len = vsprintf((char *)(state->in), format, va);
|
||||
# endif
|
||||
#else
|
||||
# ifdef HAS_vsnprintf_void
|
||||
(void)vsnprintf((char *)(state->in), size, format, va);
|
||||
len = strlen((char *)(state->in));
|
||||
# else
|
||||
len = vsnprintf((char *)(state->in), size, format, va);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* check that printf() results fit in buffer */
|
||||
if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
|
||||
return 0;
|
||||
|
||||
/* update buffer and position, defer compression until needed */
|
||||
strm->avail_in = (unsigned)len;
|
||||
strm->next_in = state->in;
|
||||
state->x.pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
int ret;
|
||||
|
||||
va_start(va, format);
|
||||
ret = gzvprintf(file, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else /* !STDC && !Z_HAVE_STDARG_H */
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
|
||||
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
gzFile file;
|
||||
const char *format;
|
||||
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
|
||||
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
|
||||
{
|
||||
int size, len;
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that can really pass pointer in ints */
|
||||
if (sizeof(int) != sizeof(void *))
|
||||
return 0;
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return 0;
|
||||
|
||||
/* make sure we have some buffer space */
|
||||
if (state->size == 0 && gz_init(state) == -1)
|
||||
return 0;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* consume whatever's left in the input buffer */
|
||||
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
|
||||
return 0;
|
||||
|
||||
/* do the printf() into the input buffer, put length in len */
|
||||
size = (int)(state->size);
|
||||
state->in[size - 1] = 0;
|
||||
#ifdef NO_snprintf
|
||||
# ifdef HAS_sprintf_void
|
||||
sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
for (len = 0; len < size; len++)
|
||||
if (state->in[len] == 0) break;
|
||||
# else
|
||||
len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
# endif
|
||||
#else
|
||||
# ifdef HAS_snprintf_void
|
||||
snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
|
||||
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
|
||||
len = strlen((char *)(state->in));
|
||||
# else
|
||||
len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
|
||||
a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
|
||||
a19, a20);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* check that printf() results fit in buffer */
|
||||
if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
|
||||
return 0;
|
||||
|
||||
/* update buffer and position, defer compression until needed */
|
||||
strm->avail_in = (unsigned)len;
|
||||
strm->next_in = state->in;
|
||||
state->x.pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzflush(file, flush)
|
||||
gzFile file;
|
||||
int flush;
|
||||
{
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check flush parameter */
|
||||
if (flush < 0 || flush > Z_FINISH)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* compress remaining data with requested flush */
|
||||
gz_comp(state, flush);
|
||||
return state->err;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzsetparams(file, level, strategy)
|
||||
gzFile file;
|
||||
int level;
|
||||
int strategy;
|
||||
{
|
||||
gz_statep state;
|
||||
z_streamp strm;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
strm = &(state->strm);
|
||||
|
||||
/* check that we're writing and that there's no error */
|
||||
if (state->mode != GZ_WRITE || state->err != Z_OK)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* if no change is requested, then do nothing */
|
||||
if (level == state->level && strategy == state->strategy)
|
||||
return Z_OK;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* change compression parameters for subsequent input */
|
||||
if (state->size) {
|
||||
/* flush previous input with previous parameters before changing */
|
||||
if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
|
||||
return state->err;
|
||||
deflateParams(strm, level, strategy);
|
||||
}
|
||||
state->level = level;
|
||||
state->strategy = strategy;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/* -- see zlib.h -- */
|
||||
int ZEXPORT gzclose_w(file)
|
||||
gzFile file;
|
||||
{
|
||||
int ret = Z_OK;
|
||||
gz_statep state;
|
||||
|
||||
/* get internal structure */
|
||||
if (file == NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (gz_statep)file;
|
||||
|
||||
/* check that we're writing */
|
||||
if (state->mode != GZ_WRITE)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check for seek request */
|
||||
if (state->seek) {
|
||||
state->seek = 0;
|
||||
if (gz_zero(state, state->skip) == -1)
|
||||
ret = state->err;
|
||||
}
|
||||
|
||||
/* flush, free memory, and close file */
|
||||
if (gz_comp(state, Z_FINISH) == -1)
|
||||
ret = state->err;
|
||||
if (state->size) {
|
||||
if (!state->direct) {
|
||||
(void)deflateEnd(&(state->strm));
|
||||
free(state->out);
|
||||
}
|
||||
free(state->in);
|
||||
}
|
||||
gz_error(state, Z_OK, NULL);
|
||||
free(state->path);
|
||||
if (close(state->fd) == -1)
|
||||
ret = Z_ERRNO;
|
||||
free(state);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,640 @@
|
|||
/* infback.c -- inflate using a call-back interface
|
||||
* Copyright (C) 1995-2011 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/*
|
||||
This code is largely copied from inflate.c. Normally either infback.o or
|
||||
inflate.o would be linked into an application--not both. The interface
|
||||
with inffast.c is retained so that optimized assembler-coded versions of
|
||||
inflate_fast() can be used with either inflate.c or infback.c.
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
/* function prototypes */
|
||||
local void fixedtables OF((struct inflate_state FAR *state));
|
||||
|
||||
/*
|
||||
strm provides memory allocation functions in zalloc and zfree, or
|
||||
Z_NULL to use the library memory allocation functions.
|
||||
|
||||
windowBits is in the range 8..15, and window is a user-supplied
|
||||
window and output buffer that is 2**windowBits bytes.
|
||||
*/
|
||||
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
|
||||
z_streamp strm;
|
||||
int windowBits;
|
||||
unsigned char FAR *window;
|
||||
const char *version;
|
||||
int stream_size;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
|
||||
stream_size != (int)(sizeof(z_stream)))
|
||||
return Z_VERSION_ERROR;
|
||||
if (strm == Z_NULL || window == Z_NULL ||
|
||||
windowBits < 8 || windowBits > 15)
|
||||
return Z_STREAM_ERROR;
|
||||
strm->msg = Z_NULL; /* in case we return an error */
|
||||
if (strm->zalloc == (alloc_func)0) {
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = (voidpf)0;
|
||||
#endif
|
||||
}
|
||||
if (strm->zfree == (free_func)0)
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zfree = zcfree;
|
||||
#endif
|
||||
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
|
||||
sizeof(struct inflate_state));
|
||||
if (state == Z_NULL) return Z_MEM_ERROR;
|
||||
Tracev((stderr, "inflate: allocated\n"));
|
||||
strm->state = (struct internal_state FAR *)state;
|
||||
state->dmax = 32768U;
|
||||
state->wbits = windowBits;
|
||||
state->wsize = 1U << windowBits;
|
||||
state->window = window;
|
||||
state->wnext = 0;
|
||||
state->whave = 0;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Return state with length and distance decoding tables and index sizes set to
|
||||
fixed code decoding. Normally this returns fixed tables from inffixed.h.
|
||||
If BUILDFIXED is defined, then instead this routine builds the tables the
|
||||
first time it's called, and returns those tables the first time and
|
||||
thereafter. This reduces the size of the code by about 2K bytes, in
|
||||
exchange for a little execution time. However, BUILDFIXED should not be
|
||||
used for threaded applications, since the rewriting of the tables and virgin
|
||||
may not be thread-safe.
|
||||
*/
|
||||
local void fixedtables(state)
|
||||
struct inflate_state FAR *state;
|
||||
{
|
||||
#ifdef BUILDFIXED
|
||||
static int virgin = 1;
|
||||
static code *lenfix, *distfix;
|
||||
static code fixed[544];
|
||||
|
||||
/* build fixed huffman tables if first call (may not be thread safe) */
|
||||
if (virgin) {
|
||||
unsigned sym, bits;
|
||||
static code *next;
|
||||
|
||||
/* literal/length table */
|
||||
sym = 0;
|
||||
while (sym < 144) state->lens[sym++] = 8;
|
||||
while (sym < 256) state->lens[sym++] = 9;
|
||||
while (sym < 280) state->lens[sym++] = 7;
|
||||
while (sym < 288) state->lens[sym++] = 8;
|
||||
next = fixed;
|
||||
lenfix = next;
|
||||
bits = 9;
|
||||
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
|
||||
|
||||
/* distance table */
|
||||
sym = 0;
|
||||
while (sym < 32) state->lens[sym++] = 5;
|
||||
distfix = next;
|
||||
bits = 5;
|
||||
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
|
||||
|
||||
/* do this just once */
|
||||
virgin = 0;
|
||||
}
|
||||
#else /* !BUILDFIXED */
|
||||
# include "inffixed.h"
|
||||
#endif /* BUILDFIXED */
|
||||
state->lencode = lenfix;
|
||||
state->lenbits = 9;
|
||||
state->distcode = distfix;
|
||||
state->distbits = 5;
|
||||
}
|
||||
|
||||
/* Macros for inflateBack(): */
|
||||
|
||||
/* Load returned state from inflate_fast() */
|
||||
#define LOAD() \
|
||||
do { \
|
||||
put = strm->next_out; \
|
||||
left = strm->avail_out; \
|
||||
next = strm->next_in; \
|
||||
have = strm->avail_in; \
|
||||
hold = state->hold; \
|
||||
bits = state->bits; \
|
||||
} while (0)
|
||||
|
||||
/* Set state from registers for inflate_fast() */
|
||||
#define RESTORE() \
|
||||
do { \
|
||||
strm->next_out = put; \
|
||||
strm->avail_out = left; \
|
||||
strm->next_in = next; \
|
||||
strm->avail_in = have; \
|
||||
state->hold = hold; \
|
||||
state->bits = bits; \
|
||||
} while (0)
|
||||
|
||||
/* Clear the input bit accumulator */
|
||||
#define INITBITS() \
|
||||
do { \
|
||||
hold = 0; \
|
||||
bits = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some input is available. If input is requested, but denied,
|
||||
then return a Z_BUF_ERROR from inflateBack(). */
|
||||
#define PULL() \
|
||||
do { \
|
||||
if (have == 0) { \
|
||||
have = in(in_desc, &next); \
|
||||
if (have == 0) { \
|
||||
next = Z_NULL; \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Get a byte of input into the bit accumulator, or return from inflateBack()
|
||||
with an error if there is no input available. */
|
||||
#define PULLBYTE() \
|
||||
do { \
|
||||
PULL(); \
|
||||
have--; \
|
||||
hold += (unsigned long)(*next++) << bits; \
|
||||
bits += 8; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that there are at least n bits in the bit accumulator. If there is
|
||||
not enough available input to do that, then return from inflateBack() with
|
||||
an error. */
|
||||
#define NEEDBITS(n) \
|
||||
do { \
|
||||
while (bits < (unsigned)(n)) \
|
||||
PULLBYTE(); \
|
||||
} while (0)
|
||||
|
||||
/* Return the low n bits of the bit accumulator (n < 16) */
|
||||
#define BITS(n) \
|
||||
((unsigned)hold & ((1U << (n)) - 1))
|
||||
|
||||
/* Remove n bits from the bit accumulator */
|
||||
#define DROPBITS(n) \
|
||||
do { \
|
||||
hold >>= (n); \
|
||||
bits -= (unsigned)(n); \
|
||||
} while (0)
|
||||
|
||||
/* Remove zero to seven bits as needed to go to a byte boundary */
|
||||
#define BYTEBITS() \
|
||||
do { \
|
||||
hold >>= bits & 7; \
|
||||
bits -= bits & 7; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some output space is available, by writing out the window
|
||||
if it's full. If the write fails, return from inflateBack() with a
|
||||
Z_BUF_ERROR. */
|
||||
#define ROOM() \
|
||||
do { \
|
||||
if (left == 0) { \
|
||||
put = state->window; \
|
||||
left = state->wsize; \
|
||||
state->whave = left; \
|
||||
if (out(out_desc, put, left)) { \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
strm provides the memory allocation functions and window buffer on input,
|
||||
and provides information on the unused input on return. For Z_DATA_ERROR
|
||||
returns, strm will also provide an error message.
|
||||
|
||||
in() and out() are the call-back input and output functions. When
|
||||
inflateBack() needs more input, it calls in(). When inflateBack() has
|
||||
filled the window with output, or when it completes with data in the
|
||||
window, it calls out() to write out the data. The application must not
|
||||
change the provided input until in() is called again or inflateBack()
|
||||
returns. The application must not change the window/output buffer until
|
||||
inflateBack() returns.
|
||||
|
||||
in() and out() are called with a descriptor parameter provided in the
|
||||
inflateBack() call. This parameter can be a structure that provides the
|
||||
information required to do the read or write, as well as accumulated
|
||||
information on the input and output such as totals and check values.
|
||||
|
||||
in() should return zero on failure. out() should return non-zero on
|
||||
failure. If either in() or out() fails, than inflateBack() returns a
|
||||
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
|
||||
was in() or out() that caused in the error. Otherwise, inflateBack()
|
||||
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
|
||||
error, or Z_MEM_ERROR if it could not allocate memory for the state.
|
||||
inflateBack() can also return Z_STREAM_ERROR if the input parameters
|
||||
are not correct, i.e. strm is Z_NULL or the state was not initialized.
|
||||
*/
|
||||
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
|
||||
z_streamp strm;
|
||||
in_func in;
|
||||
void FAR *in_desc;
|
||||
out_func out;
|
||||
void FAR *out_desc;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
z_const unsigned char FAR *next; /* next input */
|
||||
unsigned char FAR *put; /* next output */
|
||||
unsigned have, left; /* available input and output */
|
||||
unsigned long hold; /* bit buffer */
|
||||
unsigned bits; /* bits in bit buffer */
|
||||
unsigned copy; /* number of stored or match bytes to copy */
|
||||
unsigned char FAR *from; /* where to copy match bytes from */
|
||||
code here; /* current decoding table entry */
|
||||
code last; /* parent table entry */
|
||||
unsigned len; /* length to copy for repeats, bits to drop */
|
||||
int ret; /* return code */
|
||||
static const unsigned short order[19] = /* permutation of code lengths */
|
||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
/* Check that the strm exists and that the state was initialized */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
/* Reset the state */
|
||||
strm->msg = Z_NULL;
|
||||
state->mode = TYPE;
|
||||
state->last = 0;
|
||||
state->whave = 0;
|
||||
next = strm->next_in;
|
||||
have = next != Z_NULL ? strm->avail_in : 0;
|
||||
hold = 0;
|
||||
bits = 0;
|
||||
put = state->window;
|
||||
left = state->wsize;
|
||||
|
||||
/* Inflate until end of block marked as last */
|
||||
for (;;)
|
||||
switch (state->mode) {
|
||||
case TYPE:
|
||||
/* determine and dispatch block type */
|
||||
if (state->last) {
|
||||
BYTEBITS();
|
||||
state->mode = DONE;
|
||||
break;
|
||||
}
|
||||
NEEDBITS(3);
|
||||
state->last = BITS(1);
|
||||
DROPBITS(1);
|
||||
switch (BITS(2)) {
|
||||
case 0: /* stored block */
|
||||
Tracev((stderr, "inflate: stored block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = STORED;
|
||||
break;
|
||||
case 1: /* fixed block */
|
||||
fixedtables(state);
|
||||
Tracev((stderr, "inflate: fixed codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = LEN; /* decode codes */
|
||||
break;
|
||||
case 2: /* dynamic block */
|
||||
Tracev((stderr, "inflate: dynamic codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = TABLE;
|
||||
break;
|
||||
case 3:
|
||||
strm->msg = (char *)"invalid block type";
|
||||
state->mode = BAD;
|
||||
}
|
||||
DROPBITS(2);
|
||||
break;
|
||||
|
||||
case STORED:
|
||||
/* get and verify stored block length */
|
||||
BYTEBITS(); /* go to byte boundary */
|
||||
NEEDBITS(32);
|
||||
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
|
||||
strm->msg = (char *)"invalid stored block lengths";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->length = (unsigned)hold & 0xffff;
|
||||
Tracev((stderr, "inflate: stored length %u\n",
|
||||
state->length));
|
||||
INITBITS();
|
||||
|
||||
/* copy stored block from input to output */
|
||||
while (state->length != 0) {
|
||||
copy = state->length;
|
||||
PULL();
|
||||
ROOM();
|
||||
if (copy > have) copy = have;
|
||||
if (copy > left) copy = left;
|
||||
zmemcpy(put, next, copy);
|
||||
have -= copy;
|
||||
next += copy;
|
||||
left -= copy;
|
||||
put += copy;
|
||||
state->length -= copy;
|
||||
}
|
||||
Tracev((stderr, "inflate: stored end\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
|
||||
case TABLE:
|
||||
/* get dynamic table entries descriptor */
|
||||
NEEDBITS(14);
|
||||
state->nlen = BITS(5) + 257;
|
||||
DROPBITS(5);
|
||||
state->ndist = BITS(5) + 1;
|
||||
DROPBITS(5);
|
||||
state->ncode = BITS(4) + 4;
|
||||
DROPBITS(4);
|
||||
#ifndef PKZIP_BUG_WORKAROUND
|
||||
if (state->nlen > 286 || state->ndist > 30) {
|
||||
strm->msg = (char *)"too many length or distance symbols";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
Tracev((stderr, "inflate: table sizes ok\n"));
|
||||
|
||||
/* get code length code lengths (not a typo) */
|
||||
state->have = 0;
|
||||
while (state->have < state->ncode) {
|
||||
NEEDBITS(3);
|
||||
state->lens[order[state->have++]] = (unsigned short)BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
while (state->have < 19)
|
||||
state->lens[order[state->have++]] = 0;
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 7;
|
||||
ret = inflate_table(CODES, state->lens, 19, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid code lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: code lengths ok\n"));
|
||||
|
||||
/* get length and distance code code lengths */
|
||||
state->have = 0;
|
||||
while (state->have < state->nlen + state->ndist) {
|
||||
for (;;) {
|
||||
here = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (here.val < 16) {
|
||||
DROPBITS(here.bits);
|
||||
state->lens[state->have++] = here.val;
|
||||
}
|
||||
else {
|
||||
if (here.val == 16) {
|
||||
NEEDBITS(here.bits + 2);
|
||||
DROPBITS(here.bits);
|
||||
if (state->have == 0) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
len = (unsigned)(state->lens[state->have - 1]);
|
||||
copy = 3 + BITS(2);
|
||||
DROPBITS(2);
|
||||
}
|
||||
else if (here.val == 17) {
|
||||
NEEDBITS(here.bits + 3);
|
||||
DROPBITS(here.bits);
|
||||
len = 0;
|
||||
copy = 3 + BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
else {
|
||||
NEEDBITS(here.bits + 7);
|
||||
DROPBITS(here.bits);
|
||||
len = 0;
|
||||
copy = 11 + BITS(7);
|
||||
DROPBITS(7);
|
||||
}
|
||||
if (state->have + copy > state->nlen + state->ndist) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
while (copy--)
|
||||
state->lens[state->have++] = (unsigned short)len;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle error breaks in while */
|
||||
if (state->mode == BAD) break;
|
||||
|
||||
/* check for end-of-block code (better have one) */
|
||||
if (state->lens[256] == 0) {
|
||||
strm->msg = (char *)"invalid code -- missing end-of-block";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* build code tables -- note: do not change the lenbits or distbits
|
||||
values here (9 and 6) without reading the comments in inftrees.h
|
||||
concerning the ENOUGH constants, which depend on those values */
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 9;
|
||||
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid literal/lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->distcode = (code const FAR *)(state->next);
|
||||
state->distbits = 6;
|
||||
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
||||
&(state->next), &(state->distbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid distances set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: codes ok\n"));
|
||||
state->mode = LEN;
|
||||
|
||||
case LEN:
|
||||
/* use inflate_fast() if we have enough input and output */
|
||||
if (have >= 6 && left >= 258) {
|
||||
RESTORE();
|
||||
if (state->whave < state->wsize)
|
||||
state->whave = state->wsize - left;
|
||||
inflate_fast(strm, state->wsize);
|
||||
LOAD();
|
||||
break;
|
||||
}
|
||||
|
||||
/* get a literal, length, or end-of-block code */
|
||||
for (;;) {
|
||||
here = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (here.op && (here.op & 0xf0) == 0) {
|
||||
last = here;
|
||||
for (;;) {
|
||||
here = state->lencode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(here.bits);
|
||||
state->length = (unsigned)here.val;
|
||||
|
||||
/* process literal */
|
||||
if (here.op == 0) {
|
||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", here.val));
|
||||
ROOM();
|
||||
*put++ = (unsigned char)(state->length);
|
||||
left--;
|
||||
state->mode = LEN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* process end of block */
|
||||
if (here.op & 32) {
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* invalid code */
|
||||
if (here.op & 64) {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* length code -- get extra bits, if any */
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->length += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", state->length));
|
||||
|
||||
/* get distance code */
|
||||
for (;;) {
|
||||
here = state->distcode[BITS(state->distbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if ((here.op & 0xf0) == 0) {
|
||||
last = here;
|
||||
for (;;) {
|
||||
here = state->distcode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(here.bits);
|
||||
if (here.op & 64) {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->offset = (unsigned)here.val;
|
||||
|
||||
/* get distance extra bits, if any */
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->offset += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
if (state->offset > state->wsize - (state->whave < state->wsize ?
|
||||
left : 0)) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
||||
|
||||
/* copy match from window to output */
|
||||
do {
|
||||
ROOM();
|
||||
copy = state->wsize - state->offset;
|
||||
if (copy < left) {
|
||||
from = put + copy;
|
||||
copy = left - copy;
|
||||
}
|
||||
else {
|
||||
from = put - state->offset;
|
||||
copy = left;
|
||||
}
|
||||
if (copy > state->length) copy = state->length;
|
||||
state->length -= copy;
|
||||
left -= copy;
|
||||
do {
|
||||
*put++ = *from++;
|
||||
} while (--copy);
|
||||
} while (state->length != 0);
|
||||
break;
|
||||
|
||||
case DONE:
|
||||
/* inflate stream terminated properly -- write leftover output */
|
||||
ret = Z_STREAM_END;
|
||||
if (left < state->wsize) {
|
||||
if (out(out_desc, state->window, state->wsize - left))
|
||||
ret = Z_BUF_ERROR;
|
||||
}
|
||||
goto inf_leave;
|
||||
|
||||
case BAD:
|
||||
ret = Z_DATA_ERROR;
|
||||
goto inf_leave;
|
||||
|
||||
default: /* can't happen, but makes compilers happy */
|
||||
ret = Z_STREAM_ERROR;
|
||||
goto inf_leave;
|
||||
}
|
||||
|
||||
/* Return unused input */
|
||||
inf_leave:
|
||||
strm->next_in = next;
|
||||
strm->avail_in = have;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateBackEnd(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
|
||||
return Z_STREAM_ERROR;
|
||||
ZFREE(strm, strm->state);
|
||||
strm->state = Z_NULL;
|
||||
Tracev((stderr, "inflate: end\n"));
|
||||
return Z_OK;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/* inffast.c -- fast decoding
|
||||
* Copyright (C) 1995-2008, 2010 Mark Adler
|
||||
* Copyright (C) 1995-2008, 2010, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -69,8 +69,8 @@ z_streamp strm;
|
|||
unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *in; /* local strm->next_in */
|
||||
unsigned char FAR *last; /* while in < last, enough input available */
|
||||
z_const unsigned char FAR *in; /* local strm->next_in */
|
||||
z_const unsigned char FAR *last; /* have enough input while in < last */
|
||||
unsigned char FAR *out; /* local strm->next_out */
|
||||
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
|
||||
unsigned char FAR *end; /* while out < end, enough space available */
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
* Generated automatically by makefixed().
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It
|
||||
is part of the implementation of the compression library and
|
||||
is subject to change. Applications should only use zlib.h.
|
||||
/* WARNING: this file should *not* be used by applications.
|
||||
It is part of the implementation of this library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
static const code lenfix[512] = {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* inflate.c -- zlib decompression
|
||||
* Copyright (C) 1995-2010 Mark Adler
|
||||
* Copyright (C) 1995-2012 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -93,14 +93,15 @@
|
|||
|
||||
/* function prototypes */
|
||||
local void fixedtables OF((struct inflate_state FAR *state));
|
||||
local int updatewindow OF((z_streamp strm, unsigned out));
|
||||
local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
|
||||
unsigned copy));
|
||||
#ifdef BUILDFIXED
|
||||
void makefixed OF((void));
|
||||
#endif
|
||||
local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
|
||||
local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
|
||||
unsigned len));
|
||||
|
||||
int ZEXPORT inflateReset(strm)
|
||||
int ZEXPORT inflateResetKeep(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
@ -109,15 +110,13 @@ z_streamp strm;
|
|||
state = (struct inflate_state FAR *)strm->state;
|
||||
strm->total_in = strm->total_out = state->total = 0;
|
||||
strm->msg = Z_NULL;
|
||||
strm->adler = 1; /* to support ill-conceived Java test suite */
|
||||
if (state->wrap) /* to support ill-conceived Java test suite */
|
||||
strm->adler = state->wrap & 1;
|
||||
state->mode = HEAD;
|
||||
state->last = 0;
|
||||
state->havedict = 0;
|
||||
state->dmax = 32768U;
|
||||
state->head = Z_NULL;
|
||||
state->wsize = 0;
|
||||
state->whave = 0;
|
||||
state->wnext = 0;
|
||||
state->hold = 0;
|
||||
state->bits = 0;
|
||||
state->lencode = state->distcode = state->next = state->codes;
|
||||
|
@ -127,6 +126,19 @@ z_streamp strm;
|
|||
return Z_OK;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateReset(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
state->wsize = 0;
|
||||
state->whave = 0;
|
||||
state->wnext = 0;
|
||||
return inflateResetKeep(strm);
|
||||
}
|
||||
|
||||
int ZEXPORT inflateReset2(strm, windowBits)
|
||||
z_streamp strm;
|
||||
int windowBits;
|
||||
|
@ -180,10 +192,19 @@ int stream_size;
|
|||
if (strm == Z_NULL) return Z_STREAM_ERROR;
|
||||
strm->msg = Z_NULL; /* in case we return an error */
|
||||
if (strm->zalloc == (alloc_func)0) {
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = (voidpf)0;
|
||||
#endif
|
||||
}
|
||||
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
|
||||
if (strm->zfree == (free_func)0)
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zfree = zcfree;
|
||||
#endif
|
||||
state = (struct inflate_state FAR *)
|
||||
ZALLOC(strm, 1, sizeof(struct inflate_state));
|
||||
if (state == Z_NULL) return Z_MEM_ERROR;
|
||||
|
@ -321,8 +342,8 @@ void makefixed()
|
|||
low = 0;
|
||||
for (;;) {
|
||||
if ((low % 7) == 0) printf("\n ");
|
||||
printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
|
||||
state.lencode[low].val);
|
||||
printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
|
||||
state.lencode[low].bits, state.lencode[low].val);
|
||||
if (++low == size) break;
|
||||
putchar(',');
|
||||
}
|
||||
|
@ -355,12 +376,13 @@ void makefixed()
|
|||
output will fall in the output data, making match copies simpler and faster.
|
||||
The advantage may be dependent on the size of the processor's data caches.
|
||||
*/
|
||||
local int updatewindow(strm, out)
|
||||
local int updatewindow(strm, end, copy)
|
||||
z_streamp strm;
|
||||
unsigned out;
|
||||
const Bytef *end;
|
||||
unsigned copy;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned copy, dist;
|
||||
unsigned dist;
|
||||
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
|
@ -380,19 +402,18 @@ unsigned out;
|
|||
}
|
||||
|
||||
/* copy state->wsize or less output bytes into the circular window */
|
||||
copy = out - strm->avail_out;
|
||||
if (copy >= state->wsize) {
|
||||
zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
|
||||
zmemcpy(state->window, end - state->wsize, state->wsize);
|
||||
state->wnext = 0;
|
||||
state->whave = state->wsize;
|
||||
}
|
||||
else {
|
||||
dist = state->wsize - state->wnext;
|
||||
if (dist > copy) dist = copy;
|
||||
zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
|
||||
zmemcpy(state->window + state->wnext, end - copy, dist);
|
||||
copy -= dist;
|
||||
if (copy) {
|
||||
zmemcpy(state->window, strm->next_out - copy, copy);
|
||||
zmemcpy(state->window, end - copy, copy);
|
||||
state->wnext = copy;
|
||||
state->whave = state->wsize;
|
||||
}
|
||||
|
@ -499,11 +520,6 @@ unsigned out;
|
|||
bits -= bits & 7; \
|
||||
} while (0)
|
||||
|
||||
/* Reverse the bytes in a 32-bit value */
|
||||
#define REVERSE(q) \
|
||||
((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
|
||||
(((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
|
||||
|
||||
/*
|
||||
inflate() uses a state machine to process as much input data and generate as
|
||||
much output data as possible before returning. The state machine is
|
||||
|
@ -591,7 +607,7 @@ z_streamp strm;
|
|||
int flush;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *next; /* next input */
|
||||
z_const unsigned char FAR *next; /* next input */
|
||||
unsigned char FAR *put; /* next output */
|
||||
unsigned have, left; /* available input and output */
|
||||
unsigned long hold; /* bit buffer */
|
||||
|
@ -797,7 +813,7 @@ int flush;
|
|||
#endif
|
||||
case DICTID:
|
||||
NEEDBITS(32);
|
||||
strm->adler = state->check = REVERSE(hold);
|
||||
strm->adler = state->check = ZSWAP32(hold);
|
||||
INITBITS();
|
||||
state->mode = DICT;
|
||||
case DICT:
|
||||
|
@ -905,7 +921,7 @@ int flush;
|
|||
while (state->have < 19)
|
||||
state->lens[order[state->have++]] = 0;
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lencode = (const code FAR *)(state->next);
|
||||
state->lenbits = 7;
|
||||
ret = inflate_table(CODES, state->lens, 19, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
|
@ -925,7 +941,6 @@ int flush;
|
|||
PULLBYTE();
|
||||
}
|
||||
if (here.val < 16) {
|
||||
NEEDBITS(here.bits);
|
||||
DROPBITS(here.bits);
|
||||
state->lens[state->have++] = here.val;
|
||||
}
|
||||
|
@ -980,7 +995,7 @@ int flush;
|
|||
values here (9 and 6) without reading the comments in inftrees.h
|
||||
concerning the ENOUGH constants, which depend on those values */
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lencode = (const code FAR *)(state->next);
|
||||
state->lenbits = 9;
|
||||
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
|
@ -989,7 +1004,7 @@ int flush;
|
|||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->distcode = (code const FAR *)(state->next);
|
||||
state->distcode = (const code FAR *)(state->next);
|
||||
state->distbits = 6;
|
||||
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
||||
&(state->next), &(state->distbits), state->work);
|
||||
|
@ -1170,7 +1185,7 @@ int flush;
|
|||
#ifdef GUNZIP
|
||||
state->flags ? hold :
|
||||
#endif
|
||||
REVERSE(hold)) != state->check) {
|
||||
ZSWAP32(hold)) != state->check) {
|
||||
strm->msg = (char *)"incorrect data check";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
|
@ -1214,8 +1229,9 @@ int flush;
|
|||
*/
|
||||
inf_leave:
|
||||
RESTORE();
|
||||
if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
|
||||
if (updatewindow(strm, out)) {
|
||||
if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
|
||||
(state->mode < CHECK || flush != Z_FINISH)))
|
||||
if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
|
||||
state->mode = MEM;
|
||||
return Z_MEM_ERROR;
|
||||
}
|
||||
|
@ -1249,13 +1265,37 @@ z_streamp strm;
|
|||
return Z_OK;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
|
||||
z_streamp strm;
|
||||
Bytef *dictionary;
|
||||
uInt *dictLength;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
/* check state */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
/* copy dictionary */
|
||||
if (state->whave && dictionary != Z_NULL) {
|
||||
zmemcpy(dictionary, state->window + state->wnext,
|
||||
state->whave - state->wnext);
|
||||
zmemcpy(dictionary + state->whave - state->wnext,
|
||||
state->window, state->wnext);
|
||||
}
|
||||
if (dictLength != Z_NULL)
|
||||
*dictLength = state->whave;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
|
||||
z_streamp strm;
|
||||
const Bytef *dictionary;
|
||||
uInt dictLength;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned long id;
|
||||
unsigned long dictid;
|
||||
int ret;
|
||||
|
||||
/* check state */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
||||
|
@ -1263,29 +1303,21 @@ uInt dictLength;
|
|||
if (state->wrap != 0 && state->mode != DICT)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
/* check for correct dictionary id */
|
||||
/* check for correct dictionary identifier */
|
||||
if (state->mode == DICT) {
|
||||
id = adler32(0L, Z_NULL, 0);
|
||||
id = adler32(id, dictionary, dictLength);
|
||||
if (id != state->check)
|
||||
dictid = adler32(0L, Z_NULL, 0);
|
||||
dictid = adler32(dictid, dictionary, dictLength);
|
||||
if (dictid != state->check)
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* copy dictionary to window */
|
||||
if (updatewindow(strm, strm->avail_out)) {
|
||||
/* copy dictionary to window using updatewindow(), which will amend the
|
||||
existing dictionary if appropriate */
|
||||
ret = updatewindow(strm, dictionary + dictLength, dictLength);
|
||||
if (ret) {
|
||||
state->mode = MEM;
|
||||
return Z_MEM_ERROR;
|
||||
}
|
||||
if (dictLength > state->wsize) {
|
||||
zmemcpy(state->window, dictionary + dictLength - state->wsize,
|
||||
state->wsize);
|
||||
state->whave = state->wsize;
|
||||
}
|
||||
else {
|
||||
zmemcpy(state->window + state->wsize - dictLength, dictionary,
|
||||
dictLength);
|
||||
state->whave = dictLength;
|
||||
}
|
||||
state->havedict = 1;
|
||||
Tracev((stderr, "inflate: dictionary set\n"));
|
||||
return Z_OK;
|
||||
|
@ -1321,7 +1353,7 @@ gz_headerp head;
|
|||
*/
|
||||
local unsigned syncsearch(have, buf, len)
|
||||
unsigned FAR *have;
|
||||
unsigned char FAR *buf;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
unsigned got;
|
||||
|
@ -1433,8 +1465,8 @@ z_streamp source;
|
|||
}
|
||||
|
||||
/* copy state */
|
||||
zmemcpy(dest, source, sizeof(z_stream));
|
||||
zmemcpy(copy, state, sizeof(struct inflate_state));
|
||||
zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
|
||||
zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
|
||||
if (state->lencode >= state->codes &&
|
||||
state->lencode <= state->codes + ENOUGH - 1) {
|
||||
copy->lencode = copy->codes + (state->lencode - state->codes);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2010 Mark Adler
|
||||
* Copyright (C) 1995-2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
|||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
|
||||
" inflate 1.2.8 Copyright 1995-2013 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
|
@ -62,7 +62,7 @@ unsigned short FAR *work;
|
|||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
|
@ -208,8 +208,8 @@ unsigned short FAR *work;
|
|||
mask = used - 1; /* mask for comparing low */
|
||||
|
||||
/* check available table space */
|
||||
if ((type == LENS && used >= ENOUGH_LENS) ||
|
||||
(type == DISTS && used >= ENOUGH_DISTS))
|
||||
if ((type == LENS && used > ENOUGH_LENS) ||
|
||||
(type == DISTS && used > ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* process all codes and make table entries */
|
||||
|
@ -277,8 +277,8 @@ unsigned short FAR *work;
|
|||
|
||||
/* check for enough space */
|
||||
used += 1U << curr;
|
||||
if ((type == LENS && used >= ENOUGH_LENS) ||
|
||||
(type == DISTS && used >= ENOUGH_DISTS))
|
||||
if ((type == LENS && used > ENOUGH_LENS) ||
|
||||
(type == DISTS && used > ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* point entry in root table to sub-table */
|
||||
|
@ -289,38 +289,14 @@ unsigned short FAR *work;
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Fill in rest of table for incomplete codes. This loop is similar to the
|
||||
loop above in incrementing huff for table indices. It is assumed that
|
||||
len is equal to curr + drop, so there is no loop needed to increment
|
||||
through high index bits. When the current sub-table is filled, the loop
|
||||
drops back to the root table to fill in any remaining entries there.
|
||||
*/
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
here.val = (unsigned short)0;
|
||||
while (huff != 0) {
|
||||
/* when done with sub-table, drop back to root table */
|
||||
if (drop != 0 && (huff & mask) != low) {
|
||||
drop = 0;
|
||||
len = root;
|
||||
next = *table;
|
||||
here.bits = (unsigned char)len;
|
||||
}
|
||||
|
||||
/* put invalid code marker in table */
|
||||
next[huff >> drop] = here;
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
/* fill in remaining table entry if code is incomplete (guaranteed to have
|
||||
at most one remaining entry, since if the code is incomplete, the
|
||||
maximum code length that was allowed to get this far is one bit) */
|
||||
if (huff != 0) {
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
here.val = (unsigned short)0;
|
||||
next[huff] = here;
|
||||
}
|
||||
|
||||
/* set return parameters */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* trees.c -- output deflated data using Huffman coding
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly
|
||||
* Copyright (C) 1995-2012 Jean-loup Gailly
|
||||
* detect_data_type() function provided freely by Cosmin Truta, 2006
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
@ -74,11 +74,6 @@ local const uch bl_order[BL_CODES]
|
|||
* probability, to avoid transmitting the lengths for unused bit length codes.
|
||||
*/
|
||||
|
||||
#define Buf_size (8 * 2*sizeof(char))
|
||||
/* Number of bits used within bi_buf. (bi_buf might be implemented on
|
||||
* more than 16 bits on some systems.)
|
||||
*/
|
||||
|
||||
/* ===========================================================================
|
||||
* Local data. These are initialized only once.
|
||||
*/
|
||||
|
@ -151,8 +146,8 @@ local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
|
|||
local int build_bl_tree OF((deflate_state *s));
|
||||
local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
|
||||
int blcodes));
|
||||
local void compress_block OF((deflate_state *s, ct_data *ltree,
|
||||
ct_data *dtree));
|
||||
local void compress_block OF((deflate_state *s, const ct_data *ltree,
|
||||
const ct_data *dtree));
|
||||
local int detect_data_type OF((deflate_state *s));
|
||||
local unsigned bi_reverse OF((unsigned value, int length));
|
||||
local void bi_windup OF((deflate_state *s));
|
||||
|
@ -399,7 +394,6 @@ void ZLIB_INTERNAL _tr_init(s)
|
|||
|
||||
s->bi_buf = 0;
|
||||
s->bi_valid = 0;
|
||||
s->last_eob_len = 8; /* enough lookahead for inflate */
|
||||
#ifdef DEBUG
|
||||
s->compressed_len = 0L;
|
||||
s->bits_sent = 0L;
|
||||
|
@ -882,16 +876,18 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
|
|||
copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
|
||||
*/
|
||||
void ZLIB_INTERNAL _tr_flush_bits(s)
|
||||
deflate_state *s;
|
||||
{
|
||||
bi_flush(s);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Send one empty static block to give enough lookahead for inflate.
|
||||
* This takes 10 bits, of which 7 may remain in the bit buffer.
|
||||
* The current inflate code requires 9 bits of lookahead. If the
|
||||
* last two codes for the previous block (real code plus EOB) were coded
|
||||
* on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
|
||||
* the last real code. In this case we send two empty static blocks instead
|
||||
* of one. (There are no problems if the previous block is stored or fixed.)
|
||||
* To simplify the code, we assume the worst case of last real code encoded
|
||||
* on one bit only.
|
||||
*/
|
||||
void ZLIB_INTERNAL _tr_align(s)
|
||||
deflate_state *s;
|
||||
|
@ -902,20 +898,6 @@ void ZLIB_INTERNAL _tr_align(s)
|
|||
s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
|
||||
#endif
|
||||
bi_flush(s);
|
||||
/* Of the 10 bits for the empty block, we have already sent
|
||||
* (10 - bi_valid) bits. The lookahead for the last real code (before
|
||||
* the EOB of the previous block) was thus at least one plus the length
|
||||
* of the EOB plus what we have just sent of the empty static block.
|
||||
*/
|
||||
if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
|
||||
send_bits(s, STATIC_TREES<<1, 3);
|
||||
send_code(s, END_BLOCK, static_ltree);
|
||||
#ifdef DEBUG
|
||||
s->compressed_len += 10L;
|
||||
#endif
|
||||
bi_flush(s);
|
||||
}
|
||||
s->last_eob_len = 7;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
|
@ -990,7 +972,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
|
|||
} else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
|
||||
#endif
|
||||
send_bits(s, (STATIC_TREES<<1)+last, 3);
|
||||
compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
|
||||
compress_block(s, (const ct_data *)static_ltree,
|
||||
(const ct_data *)static_dtree);
|
||||
#ifdef DEBUG
|
||||
s->compressed_len += 3 + s->static_len;
|
||||
#endif
|
||||
|
@ -998,7 +981,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
|
|||
send_bits(s, (DYN_TREES<<1)+last, 3);
|
||||
send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
|
||||
max_blindex+1);
|
||||
compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
|
||||
compress_block(s, (const ct_data *)s->dyn_ltree,
|
||||
(const ct_data *)s->dyn_dtree);
|
||||
#ifdef DEBUG
|
||||
s->compressed_len += 3 + s->opt_len;
|
||||
#endif
|
||||
|
@ -1075,8 +1059,8 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
|
|||
*/
|
||||
local void compress_block(s, ltree, dtree)
|
||||
deflate_state *s;
|
||||
ct_data *ltree; /* literal tree */
|
||||
ct_data *dtree; /* distance tree */
|
||||
const ct_data *ltree; /* literal tree */
|
||||
const ct_data *dtree; /* distance tree */
|
||||
{
|
||||
unsigned dist; /* distance of matched string */
|
||||
int lc; /* match length or unmatched char (if dist == 0) */
|
||||
|
@ -1118,7 +1102,6 @@ local void compress_block(s, ltree, dtree)
|
|||
} while (lx < s->last_lit);
|
||||
|
||||
send_code(s, END_BLOCK, ltree);
|
||||
s->last_eob_len = ltree[END_BLOCK].Len;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
|
@ -1226,7 +1209,6 @@ local void copy_block(s, buf, len, header)
|
|||
int header; /* true if block header must be written */
|
||||
{
|
||||
bi_windup(s); /* align on byte boundary */
|
||||
s->last_eob_len = 8; /* enough lookahead for inflate */
|
||||
|
||||
if (header) {
|
||||
put_short(s, (ush)len);
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* uncompr.c -- decompress a memory buffer
|
||||
* Copyright (C) 1995-2003, 2010 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Decompresses the source buffer into the destination buffer. sourceLen is
|
||||
the byte length of the source buffer. Upon entry, destLen is the total
|
||||
size of the destination buffer, which must be large enough to hold the
|
||||
entire uncompressed data. (The size of the uncompressed data must have
|
||||
been saved previously by the compressor and transmitted to the decompressor
|
||||
by some mechanism outside the scope of this compression library.)
|
||||
Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||
buffer, or Z_DATA_ERROR if the input data was corrupted.
|
||||
*/
|
||||
int ZEXPORT uncompress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (z_const Bytef *)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
||||
err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
inflateEnd(&stream);
|
||||
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||
return Z_DATA_ERROR;
|
||||
return err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = inflateEnd(&stream);
|
||||
return err;
|
||||
}
|
|
@ -0,0 +1,397 @@
|
|||
|
||||
Frequently Asked Questions about ZLIB1.DLL
|
||||
|
||||
|
||||
This document describes the design, the rationale, and the usage
|
||||
of the official DLL build of zlib, named ZLIB1.DLL. If you have
|
||||
general questions about zlib, you should see the file "FAQ" found
|
||||
in the zlib distribution, or at the following location:
|
||||
http://www.gzip.org/zlib/zlib_faq.html
|
||||
|
||||
|
||||
1. What is ZLIB1.DLL, and how can I get it?
|
||||
|
||||
- ZLIB1.DLL is the official build of zlib as a DLL.
|
||||
(Please remark the character '1' in the name.)
|
||||
|
||||
Pointers to a precompiled ZLIB1.DLL can be found in the zlib
|
||||
web site at:
|
||||
http://www.zlib.net/
|
||||
|
||||
Applications that link to ZLIB1.DLL can rely on the following
|
||||
specification:
|
||||
|
||||
* The exported symbols are exclusively defined in the source
|
||||
files "zlib.h" and "zlib.def", found in an official zlib
|
||||
source distribution.
|
||||
* The symbols are exported by name, not by ordinal.
|
||||
* The exported names are undecorated.
|
||||
* The calling convention of functions is "C" (CDECL).
|
||||
* The ZLIB1.DLL binary is linked to MSVCRT.DLL.
|
||||
|
||||
The archive in which ZLIB1.DLL is bundled contains compiled
|
||||
test programs that must run with a valid build of ZLIB1.DLL.
|
||||
It is recommended to download the prebuilt DLL from the zlib
|
||||
web site, instead of building it yourself, to avoid potential
|
||||
incompatibilities that could be introduced by your compiler
|
||||
and build settings. If you do build the DLL yourself, please
|
||||
make sure that it complies with all the above requirements,
|
||||
and it runs with the precompiled test programs, bundled with
|
||||
the original ZLIB1.DLL distribution.
|
||||
|
||||
If, for any reason, you need to build an incompatible DLL,
|
||||
please use a different file name.
|
||||
|
||||
|
||||
2. Why did you change the name of the DLL to ZLIB1.DLL?
|
||||
What happened to the old ZLIB.DLL?
|
||||
|
||||
- The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required
|
||||
compilation settings that were incompatible to those used by
|
||||
a static build. The DLL settings were supposed to be enabled
|
||||
by defining the macro ZLIB_DLL, before including "zlib.h".
|
||||
Incorrect handling of this macro was silently accepted at
|
||||
build time, resulting in two major problems:
|
||||
|
||||
* ZLIB_DLL was missing from the old makefile. When building
|
||||
the DLL, not all people added it to the build options. In
|
||||
consequence, incompatible incarnations of ZLIB.DLL started
|
||||
to circulate around the net.
|
||||
|
||||
* When switching from using the static library to using the
|
||||
DLL, applications had to define the ZLIB_DLL macro and
|
||||
to recompile all the sources that contained calls to zlib
|
||||
functions. Failure to do so resulted in creating binaries
|
||||
that were unable to run with the official ZLIB.DLL build.
|
||||
|
||||
The only possible solution that we could foresee was to make
|
||||
a binary-incompatible change in the DLL interface, in order to
|
||||
remove the dependency on the ZLIB_DLL macro, and to release
|
||||
the new DLL under a different name.
|
||||
|
||||
We chose the name ZLIB1.DLL, where '1' indicates the major
|
||||
zlib version number. We hope that we will not have to break
|
||||
the binary compatibility again, at least not as long as the
|
||||
zlib-1.x series will last.
|
||||
|
||||
There is still a ZLIB_DLL macro, that can trigger a more
|
||||
efficient build and use of the DLL, but compatibility no
|
||||
longer dependents on it.
|
||||
|
||||
|
||||
3. Can I build ZLIB.DLL from the new zlib sources, and replace
|
||||
an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier?
|
||||
|
||||
- In principle, you can do it by assigning calling convention
|
||||
keywords to the macros ZEXPORT and ZEXPORTVA. In practice,
|
||||
it depends on what you mean by "an old ZLIB.DLL", because the
|
||||
old DLL exists in several mutually-incompatible versions.
|
||||
You have to find out first what kind of calling convention is
|
||||
being used in your particular ZLIB.DLL build, and to use the
|
||||
same one in the new build. If you don't know what this is all
|
||||
about, you might be better off if you would just leave the old
|
||||
DLL intact.
|
||||
|
||||
|
||||
4. Can I compile my application using the new zlib interface, and
|
||||
link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or
|
||||
earlier?
|
||||
|
||||
- The official answer is "no"; the real answer depends again on
|
||||
what kind of ZLIB.DLL you have. Even if you are lucky, this
|
||||
course of action is unreliable.
|
||||
|
||||
If you rebuild your application and you intend to use a newer
|
||||
version of zlib (post- 1.1.4), it is strongly recommended to
|
||||
link it to the new ZLIB1.DLL.
|
||||
|
||||
|
||||
5. Why are the zlib symbols exported by name, and not by ordinal?
|
||||
|
||||
- Although exporting symbols by ordinal is a little faster, it
|
||||
is risky. Any single glitch in the maintenance or use of the
|
||||
DEF file that contains the ordinals can result in incompatible
|
||||
builds and frustrating crashes. Simply put, the benefits of
|
||||
exporting symbols by ordinal do not justify the risks.
|
||||
|
||||
Technically, it should be possible to maintain ordinals in
|
||||
the DEF file, and still export the symbols by name. Ordinals
|
||||
exist in every DLL, and even if the dynamic linking performed
|
||||
at the DLL startup is searching for names, ordinals serve as
|
||||
hints, for a faster name lookup. However, if the DEF file
|
||||
contains ordinals, the Microsoft linker automatically builds
|
||||
an implib that will cause the executables linked to it to use
|
||||
those ordinals, and not the names. It is interesting to
|
||||
notice that the GNU linker for Win32 does not suffer from this
|
||||
problem.
|
||||
|
||||
It is possible to avoid the DEF file if the exported symbols
|
||||
are accompanied by a "__declspec(dllexport)" attribute in the
|
||||
source files. You can do this in zlib by predefining the
|
||||
ZLIB_DLL macro.
|
||||
|
||||
|
||||
6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling
|
||||
convention. Why not use the STDCALL convention?
|
||||
STDCALL is the standard convention in Win32, and I need it in
|
||||
my Visual Basic project!
|
||||
|
||||
(For readability, we use CDECL to refer to the convention
|
||||
triggered by the "__cdecl" keyword, STDCALL to refer to
|
||||
the convention triggered by "__stdcall", and FASTCALL to
|
||||
refer to the convention triggered by "__fastcall".)
|
||||
|
||||
- Most of the native Windows API functions (without varargs) use
|
||||
indeed the WINAPI convention (which translates to STDCALL in
|
||||
Win32), but the standard C functions use CDECL. If a user
|
||||
application is intrinsically tied to the Windows API (e.g.
|
||||
it calls native Windows API functions such as CreateFile()),
|
||||
sometimes it makes sense to decorate its own functions with
|
||||
WINAPI. But if ANSI C or POSIX portability is a goal (e.g.
|
||||
it calls standard C functions such as fopen()), it is not a
|
||||
sound decision to request the inclusion of <windows.h>, or to
|
||||
use non-ANSI constructs, for the sole purpose to make the user
|
||||
functions STDCALL-able.
|
||||
|
||||
The functionality offered by zlib is not in the category of
|
||||
"Windows functionality", but is more like "C functionality".
|
||||
|
||||
Technically, STDCALL is not bad; in fact, it is slightly
|
||||
faster than CDECL, and it works with variable-argument
|
||||
functions, just like CDECL. It is unfortunate that, in spite
|
||||
of using STDCALL in the Windows API, it is not the default
|
||||
convention used by the C compilers that run under Windows.
|
||||
The roots of the problem reside deep inside the unsafety of
|
||||
the K&R-style function prototypes, where the argument types
|
||||
are not specified; but that is another story for another day.
|
||||
|
||||
The remaining fact is that CDECL is the default convention.
|
||||
Even if an explicit convention is hard-coded into the function
|
||||
prototypes inside C headers, problems may appear. The
|
||||
necessity to expose the convention in users' callbacks is one
|
||||
of these problems.
|
||||
|
||||
The calling convention issues are also important when using
|
||||
zlib in other programming languages. Some of them, like Ada
|
||||
(GNAT) and Fortran (GNU G77), have C bindings implemented
|
||||
initially on Unix, and relying on the C calling convention.
|
||||
On the other hand, the pre- .NET versions of Microsoft Visual
|
||||
Basic require STDCALL, while Borland Delphi prefers, although
|
||||
it does not require, FASTCALL.
|
||||
|
||||
In fairness to all possible uses of zlib outside the C
|
||||
programming language, we choose the default "C" convention.
|
||||
Anyone interested in different bindings or conventions is
|
||||
encouraged to maintain specialized projects. The "contrib/"
|
||||
directory from the zlib distribution already holds a couple
|
||||
of foreign bindings, such as Ada, C++, and Delphi.
|
||||
|
||||
|
||||
7. I need a DLL for my Visual Basic project. What can I do?
|
||||
|
||||
- Define the ZLIB_WINAPI macro before including "zlib.h", when
|
||||
building both the DLL and the user application (except that
|
||||
you don't need to define anything when using the DLL in Visual
|
||||
Basic). The ZLIB_WINAPI macro will switch on the WINAPI
|
||||
(STDCALL) convention. The name of this DLL must be different
|
||||
than the official ZLIB1.DLL.
|
||||
|
||||
Gilles Vollant has contributed a build named ZLIBWAPI.DLL,
|
||||
with the ZLIB_WINAPI macro turned on, and with the minizip
|
||||
functionality built in. For more information, please read
|
||||
the notes inside "contrib/vstudio/readme.txt", found in the
|
||||
zlib distribution.
|
||||
|
||||
|
||||
8. I need to use zlib in my Microsoft .NET project. What can I
|
||||
do?
|
||||
|
||||
- Henrik Ravn has contributed a .NET wrapper around zlib. Look
|
||||
into contrib/dotzlib/, inside the zlib distribution.
|
||||
|
||||
|
||||
9. If my application uses ZLIB1.DLL, should I link it to
|
||||
MSVCRT.DLL? Why?
|
||||
|
||||
- It is not required, but it is recommended to link your
|
||||
application to MSVCRT.DLL, if it uses ZLIB1.DLL.
|
||||
|
||||
The executables (.EXE, .DLL, etc.) that are involved in the
|
||||
same process and are using the C run-time library (i.e. they
|
||||
are calling standard C functions), must link to the same
|
||||
library. There are several libraries in the Win32 system:
|
||||
CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc.
|
||||
Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that
|
||||
depend on it should also be linked to MSVCRT.DLL.
|
||||
|
||||
|
||||
10. Why are you saying that ZLIB1.DLL and my application should
|
||||
be linked to the same C run-time (CRT) library? I linked my
|
||||
application and my DLLs to different C libraries (e.g. my
|
||||
application to a static library, and my DLLs to MSVCRT.DLL),
|
||||
and everything works fine.
|
||||
|
||||
- If a user library invokes only pure Win32 API (accessible via
|
||||
<windows.h> and the related headers), its DLL build will work
|
||||
in any context. But if this library invokes standard C API,
|
||||
things get more complicated.
|
||||
|
||||
There is a single Win32 library in a Win32 system. Every
|
||||
function in this library resides in a single DLL module, that
|
||||
is safe to call from anywhere. On the other hand, there are
|
||||
multiple versions of the C library, and each of them has its
|
||||
own separate internal state. Standalone executables and user
|
||||
DLLs that call standard C functions must link to a C run-time
|
||||
(CRT) library, be it static or shared (DLL). Intermixing
|
||||
occurs when an executable (not necessarily standalone) and a
|
||||
DLL are linked to different CRTs, and both are running in the
|
||||
same process.
|
||||
|
||||
Intermixing multiple CRTs is possible, as long as their
|
||||
internal states are kept intact. The Microsoft Knowledge Base
|
||||
articles KB94248 "HOWTO: Use the C Run-Time" and KB140584
|
||||
"HOWTO: Link with the Correct C Run-Time (CRT) Library"
|
||||
mention the potential problems raised by intermixing.
|
||||
|
||||
If intermixing works for you, it's because your application
|
||||
and DLLs are avoiding the corruption of each of the CRTs'
|
||||
internal states, maybe by careful design, or maybe by fortune.
|
||||
|
||||
Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such
|
||||
as those provided by Borland, raises similar problems.
|
||||
|
||||
|
||||
11. Why are you linking ZLIB1.DLL to MSVCRT.DLL?
|
||||
|
||||
- MSVCRT.DLL exists on every Windows 95 with a new service pack
|
||||
installed, or with Microsoft Internet Explorer 4 or later, and
|
||||
on all other Windows 4.x or later (Windows 98, Windows NT 4,
|
||||
or later). It is freely distributable; if not present in the
|
||||
system, it can be downloaded from Microsoft or from other
|
||||
software provider for free.
|
||||
|
||||
The fact that MSVCRT.DLL does not exist on a virgin Windows 95
|
||||
is not so problematic. Windows 95 is scarcely found nowadays,
|
||||
Microsoft ended its support a long time ago, and many recent
|
||||
applications from various vendors, including Microsoft, do not
|
||||
even run on it. Furthermore, no serious user should run
|
||||
Windows 95 without a proper update installed.
|
||||
|
||||
|
||||
12. Why are you not linking ZLIB1.DLL to
|
||||
<<my favorite C run-time library>> ?
|
||||
|
||||
- We considered and abandoned the following alternatives:
|
||||
|
||||
* Linking ZLIB1.DLL to a static C library (LIBC.LIB, or
|
||||
LIBCMT.LIB) is not a good option. People are using the DLL
|
||||
mainly to save disk space. If you are linking your program
|
||||
to a static C library, you may as well consider linking zlib
|
||||
in statically, too.
|
||||
|
||||
* Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because
|
||||
CRTDLL.DLL is present on every Win32 installation.
|
||||
Unfortunately, it has a series of problems: it does not
|
||||
work properly with Microsoft's C++ libraries, it does not
|
||||
provide support for 64-bit file offsets, (and so on...),
|
||||
and Microsoft discontinued its support a long time ago.
|
||||
|
||||
* Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied
|
||||
with the Microsoft .NET platform, and Visual C++ 7.0/7.1,
|
||||
raises problems related to the status of ZLIB1.DLL as a
|
||||
system component. According to the Microsoft Knowledge Base
|
||||
article KB326922 "INFO: Redistribution of the Shared C
|
||||
Runtime Component in Visual C++ .NET", MSVCR70.DLL and
|
||||
MSVCR71.DLL are not supposed to function as system DLLs,
|
||||
because they may clash with MSVCRT.DLL. Instead, the
|
||||
application's installer is supposed to put these DLLs
|
||||
(if needed) in the application's private directory.
|
||||
If ZLIB1.DLL depends on a non-system runtime, it cannot
|
||||
function as a redistributable system component.
|
||||
|
||||
* Linking ZLIB1.DLL to non-Microsoft runtimes, such as
|
||||
Borland's, or Cygwin's, raises problems related to the
|
||||
reliable presence of these runtimes on Win32 systems.
|
||||
It's easier to let the DLL build of zlib up to the people
|
||||
who distribute these runtimes, and who may proceed as
|
||||
explained in the answer to Question 14.
|
||||
|
||||
|
||||
13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL,
|
||||
how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0
|
||||
(Visual Studio .NET) or newer?
|
||||
|
||||
- Due to the problems explained in the Microsoft Knowledge Base
|
||||
article KB326922 (see the previous answer), the C runtime that
|
||||
comes with the VC7 environment is no longer considered a
|
||||
system component. That is, it should not be assumed that this
|
||||
runtime exists, or may be installed in a system directory.
|
||||
Since ZLIB1.DLL is supposed to be a system component, it may
|
||||
not depend on a non-system component.
|
||||
|
||||
In order to link ZLIB1.DLL and your application to MSVCRT.DLL
|
||||
in VC7, you need the library of Visual C++ 6.0 or older. If
|
||||
you don't have this library at hand, it's probably best not to
|
||||
use ZLIB1.DLL.
|
||||
|
||||
We are hoping that, in the future, Microsoft will provide a
|
||||
way to build applications linked to a proper system runtime,
|
||||
from the Visual C++ environment. Until then, you have a
|
||||
couple of alternatives, such as linking zlib in statically.
|
||||
If your application requires dynamic linking, you may proceed
|
||||
as explained in the answer to Question 14.
|
||||
|
||||
|
||||
14. I need to link my own DLL build to a CRT different than
|
||||
MSVCRT.DLL. What can I do?
|
||||
|
||||
- Feel free to rebuild the DLL from the zlib sources, and link
|
||||
it the way you want. You should, however, clearly state that
|
||||
your build is unofficial. You should give it a different file
|
||||
name, and/or install it in a private directory that can be
|
||||
accessed by your application only, and is not visible to the
|
||||
others (i.e. it's neither in the PATH, nor in the SYSTEM or
|
||||
SYSTEM32 directories). Otherwise, your build may clash with
|
||||
applications that link to the official build.
|
||||
|
||||
For example, in Cygwin, zlib is linked to the Cygwin runtime
|
||||
CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL.
|
||||
|
||||
|
||||
15. May I include additional pieces of code that I find useful,
|
||||
link them in ZLIB1.DLL, and export them?
|
||||
|
||||
- No. A legitimate build of ZLIB1.DLL must not include code
|
||||
that does not originate from the official zlib source code.
|
||||
But you can make your own private DLL build, under a different
|
||||
file name, as suggested in the previous answer.
|
||||
|
||||
For example, zlib is a part of the VCL library, distributed
|
||||
with Borland Delphi and C++ Builder. The DLL build of VCL
|
||||
is a redistributable file, named VCLxx.DLL.
|
||||
|
||||
|
||||
16. May I remove some functionality out of ZLIB1.DLL, by enabling
|
||||
macros like NO_GZCOMPRESS or NO_GZIP at compile time?
|
||||
|
||||
- No. A legitimate build of ZLIB1.DLL must provide the complete
|
||||
zlib functionality, as implemented in the official zlib source
|
||||
code. But you can make your own private DLL build, under a
|
||||
different file name, as suggested in the previous answer.
|
||||
|
||||
|
||||
17. I made my own ZLIB1.DLL build. Can I test it for compliance?
|
||||
|
||||
- We prefer that you download the official DLL from the zlib
|
||||
web site. If you need something peculiar from this DLL, you
|
||||
can send your suggestion to the zlib mailing list.
|
||||
|
||||
However, in case you do rebuild the DLL yourself, you can run
|
||||
it with the test programs found in the DLL distribution.
|
||||
Running these test programs is not a guarantee of compliance,
|
||||
but a failure can imply a detected problem.
|
||||
|
||||
**
|
||||
|
||||
This document is written and maintained by
|
||||
Cosmin Truta <cosmint@cs.ubbcluj.ro>
|
|
@ -0,0 +1,110 @@
|
|||
# Makefile for zlib
|
||||
# Borland C++ for Win32
|
||||
#
|
||||
# Usage:
|
||||
# make -f win32/Makefile.bor
|
||||
# make -f win32/Makefile.bor LOCAL_ZLIB=-DASMV OBJA=match.obj OBJPA=+match.obj
|
||||
|
||||
# ------------ Borland C++ ------------
|
||||
|
||||
# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7)
|
||||
# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or
|
||||
# added to the declaration of LOC here:
|
||||
LOC = $(LOCAL_ZLIB)
|
||||
|
||||
CC = bcc32
|
||||
AS = bcc32
|
||||
LD = bcc32
|
||||
AR = tlib
|
||||
CFLAGS = -a -d -k- -O2 $(LOC)
|
||||
ASFLAGS = $(LOC)
|
||||
LDFLAGS = $(LOC)
|
||||
|
||||
|
||||
# variables
|
||||
ZLIB_LIB = zlib.lib
|
||||
|
||||
OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj
|
||||
OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj
|
||||
#OBJA =
|
||||
OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj
|
||||
OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj
|
||||
#OBJPA=
|
||||
|
||||
|
||||
# targets
|
||||
all: $(ZLIB_LIB) example.exe minigzip.exe
|
||||
|
||||
.c.obj:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
.asm.obj:
|
||||
$(AS) -c $(ASFLAGS) $<
|
||||
|
||||
adler32.obj: adler32.c zlib.h zconf.h
|
||||
|
||||
compress.obj: compress.c zlib.h zconf.h
|
||||
|
||||
crc32.obj: crc32.c zlib.h zconf.h crc32.h
|
||||
|
||||
deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h
|
||||
|
||||
gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h
|
||||
|
||||
gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h
|
||||
|
||||
gzread.obj: gzread.c zlib.h zconf.h gzguts.h
|
||||
|
||||
gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h
|
||||
|
||||
infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
|
||||
inffast.h inffixed.h
|
||||
|
||||
inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
|
||||
inffast.h
|
||||
|
||||
inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \
|
||||
inffast.h inffixed.h
|
||||
|
||||
inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h
|
||||
|
||||
trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h
|
||||
|
||||
uncompr.obj: uncompr.c zlib.h zconf.h
|
||||
|
||||
zutil.obj: zutil.c zutil.h zlib.h zconf.h
|
||||
|
||||
example.obj: test/example.c zlib.h zconf.h
|
||||
|
||||
minigzip.obj: test/minigzip.c zlib.h zconf.h
|
||||
|
||||
|
||||
# For the sake of the old Borland make,
|
||||
# the command line is cut to fit in the MS-DOS 128 byte limit:
|
||||
$(ZLIB_LIB): $(OBJ1) $(OBJ2) $(OBJA)
|
||||
-del $(ZLIB_LIB)
|
||||
$(AR) $(ZLIB_LIB) $(OBJP1)
|
||||
$(AR) $(ZLIB_LIB) $(OBJP2)
|
||||
$(AR) $(ZLIB_LIB) $(OBJPA)
|
||||
|
||||
|
||||
# testing
|
||||
test: example.exe minigzip.exe
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
example.exe: example.obj $(ZLIB_LIB)
|
||||
$(LD) $(LDFLAGS) example.obj $(ZLIB_LIB)
|
||||
|
||||
minigzip.exe: minigzip.obj $(ZLIB_LIB)
|
||||
$(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB)
|
||||
|
||||
|
||||
# cleanup
|
||||
clean:
|
||||
-del $(ZLIB_LIB)
|
||||
-del *.obj
|
||||
-del *.exe
|
||||
-del *.tds
|
||||
-del zlib.bak
|
||||
-del foo.gz
|
|
@ -0,0 +1,182 @@
|
|||
# Makefile for zlib, derived from Makefile.dj2.
|
||||
# Modified for mingw32 by C. Spieler, 6/16/98.
|
||||
# Updated for zlib 1.2.x by Christian Spieler and Cosmin Truta, Mar-2003.
|
||||
# Last updated: Mar 2012.
|
||||
# Tested under Cygwin and MinGW.
|
||||
|
||||
# Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
# To compile, or to compile and test, type from the top level zlib directory:
|
||||
#
|
||||
# make -fwin32/Makefile.gcc; make test testdll -fwin32/Makefile.gcc
|
||||
#
|
||||
# To use the asm code, type:
|
||||
# cp contrib/asm?86/match.S ./match.S
|
||||
# make LOC=-DASMV OBJA=match.o -fwin32/Makefile.gcc
|
||||
#
|
||||
# To install libz.a, zconf.h and zlib.h in the system directories, type:
|
||||
#
|
||||
# make install -fwin32/Makefile.gcc
|
||||
#
|
||||
# BINARY_PATH, INCLUDE_PATH and LIBRARY_PATH must be set.
|
||||
#
|
||||
# To install the shared lib, append SHARED_MODE=1 to the make command :
|
||||
#
|
||||
# make install -fwin32/Makefile.gcc SHARED_MODE=1
|
||||
|
||||
# Note:
|
||||
# If the platform is *not* MinGW (e.g. it is Cygwin or UWIN),
|
||||
# the DLL name should be changed from "zlib1.dll".
|
||||
|
||||
STATICLIB = libz.a
|
||||
SHAREDLIB = zlib1.dll
|
||||
IMPLIB = libz.dll.a
|
||||
|
||||
#
|
||||
# Set to 1 if shared object needs to be installed
|
||||
#
|
||||
SHARED_MODE=0
|
||||
|
||||
#LOC = -DASMV
|
||||
#LOC = -DDEBUG -g
|
||||
|
||||
PREFIX =
|
||||
CC = $(PREFIX)gcc
|
||||
CFLAGS = $(LOC) -O3 -Wall
|
||||
|
||||
AS = $(CC)
|
||||
ASFLAGS = $(LOC) -Wall
|
||||
|
||||
LD = $(CC)
|
||||
LDFLAGS = $(LOC)
|
||||
|
||||
AR = $(PREFIX)ar
|
||||
ARFLAGS = rcs
|
||||
|
||||
RC = $(PREFIX)windres
|
||||
RCFLAGS = --define GCC_WINDRES
|
||||
|
||||
STRIP = $(PREFIX)strip
|
||||
|
||||
CP = cp -fp
|
||||
# If GNU install is available, replace $(CP) with install.
|
||||
INSTALL = $(CP)
|
||||
RM = rm -f
|
||||
|
||||
prefix ?= /usr/local
|
||||
exec_prefix = $(prefix)
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \
|
||||
gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o
|
||||
OBJA =
|
||||
|
||||
all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) example.exe minigzip.exe example_d.exe minigzip_d.exe
|
||||
|
||||
test: example.exe minigzip.exe
|
||||
./example
|
||||
echo hello world | ./minigzip | ./minigzip -d
|
||||
|
||||
testdll: example_d.exe minigzip_d.exe
|
||||
./example_d
|
||||
echo hello world | ./minigzip_d | ./minigzip_d -d
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
.S.o:
|
||||
$(AS) $(ASFLAGS) -c -o $@ $<
|
||||
|
||||
$(STATICLIB): $(OBJS) $(OBJA)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS) $(OBJA)
|
||||
|
||||
$(IMPLIB): $(SHAREDLIB)
|
||||
|
||||
$(SHAREDLIB): win32/zlib.def $(OBJS) $(OBJA) zlibrc.o
|
||||
$(CC) -shared -Wl,--out-implib,$(IMPLIB) $(LDFLAGS) \
|
||||
-o $@ win32/zlib.def $(OBJS) $(OBJA) zlibrc.o
|
||||
$(STRIP) $@
|
||||
|
||||
example.exe: example.o $(STATICLIB)
|
||||
$(LD) $(LDFLAGS) -o $@ example.o $(STATICLIB)
|
||||
$(STRIP) $@
|
||||
|
||||
minigzip.exe: minigzip.o $(STATICLIB)
|
||||
$(LD) $(LDFLAGS) -o $@ minigzip.o $(STATICLIB)
|
||||
$(STRIP) $@
|
||||
|
||||
example_d.exe: example.o $(IMPLIB)
|
||||
$(LD) $(LDFLAGS) -o $@ example.o $(IMPLIB)
|
||||
$(STRIP) $@
|
||||
|
||||
minigzip_d.exe: minigzip.o $(IMPLIB)
|
||||
$(LD) $(LDFLAGS) -o $@ minigzip.o $(IMPLIB)
|
||||
$(STRIP) $@
|
||||
|
||||
example.o: test/example.c zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) -I. -c -o $@ test/example.c
|
||||
|
||||
minigzip.o: test/minigzip.c zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) -I. -c -o $@ test/minigzip.c
|
||||
|
||||
zlibrc.o: win32/zlib1.rc
|
||||
$(RC) $(RCFLAGS) -o $@ win32/zlib1.rc
|
||||
|
||||
.PHONY: install uninstall clean
|
||||
|
||||
install: zlib.h zconf.h $(STATICLIB) $(IMPLIB)
|
||||
@if test -z "$(DESTDIR)$(INCLUDE_PATH)" -o -z "$(DESTDIR)$(LIBRARY_PATH)" -o -z "$(DESTDIR)$(BINARY_PATH)"; then \
|
||||
echo INCLUDE_PATH, LIBRARY_PATH, and BINARY_PATH must be specified; \
|
||||
exit 1; \
|
||||
fi
|
||||
-@mkdir -p '$(DESTDIR)$(INCLUDE_PATH)'
|
||||
-@mkdir -p '$(DESTDIR)$(LIBRARY_PATH)' '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig
|
||||
-if [ "$(SHARED_MODE)" = "1" ]; then \
|
||||
mkdir -p '$(DESTDIR)$(BINARY_PATH)'; \
|
||||
$(INSTALL) $(SHAREDLIB) '$(DESTDIR)$(BINARY_PATH)'; \
|
||||
$(INSTALL) $(IMPLIB) '$(DESTDIR)$(LIBRARY_PATH)'; \
|
||||
fi
|
||||
-$(INSTALL) zlib.h '$(DESTDIR)$(INCLUDE_PATH)'
|
||||
-$(INSTALL) zconf.h '$(DESTDIR)$(INCLUDE_PATH)'
|
||||
-$(INSTALL) $(STATICLIB) '$(DESTDIR)$(LIBRARY_PATH)'
|
||||
sed \
|
||||
-e 's|@prefix@|${prefix}|g' \
|
||||
-e 's|@exec_prefix@|${exec_prefix}|g' \
|
||||
-e 's|@libdir@|$(LIBRARY_PATH)|g' \
|
||||
-e 's|@sharedlibdir@|$(LIBRARY_PATH)|g' \
|
||||
-e 's|@includedir@|$(INCLUDE_PATH)|g' \
|
||||
-e 's|@VERSION@|'`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' zlib.h`'|g' \
|
||||
zlib.pc.in > '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig/zlib.pc
|
||||
|
||||
uninstall:
|
||||
-if [ "$(SHARED_MODE)" = "1" ]; then \
|
||||
$(RM) '$(DESTDIR)$(BINARY_PATH)'/$(SHAREDLIB); \
|
||||
$(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(IMPLIB); \
|
||||
fi
|
||||
-$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zlib.h
|
||||
-$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zconf.h
|
||||
-$(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(STATICLIB)
|
||||
|
||||
clean:
|
||||
-$(RM) $(STATICLIB)
|
||||
-$(RM) $(SHAREDLIB)
|
||||
-$(RM) $(IMPLIB)
|
||||
-$(RM) *.o
|
||||
-$(RM) *.exe
|
||||
-$(RM) foo.gz
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
gzclose.o: zlib.h zconf.h gzguts.h
|
||||
gzlib.o: zlib.h zconf.h gzguts.h
|
||||
gzread.o: zlib.h zconf.h gzguts.h
|
||||
gzwrite.o: zlib.h zconf.h gzguts.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
|
@ -0,0 +1,163 @@
|
|||
# Makefile for zlib using Microsoft (Visual) C
|
||||
# zlib is copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler
|
||||
#
|
||||
# Usage:
|
||||
# nmake -f win32/Makefile.msc (standard build)
|
||||
# nmake -f win32/Makefile.msc LOC=-DFOO (nonstandard build)
|
||||
# nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" \
|
||||
# OBJA="inffas32.obj match686.obj" (use ASM code, x86)
|
||||
# nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -I." \
|
||||
# OBJA="inffasx64.obj gvmat64.obj inffas8664.obj" (use ASM code, x64)
|
||||
|
||||
# The toplevel directory of the source tree.
|
||||
#
|
||||
TOP = .
|
||||
|
||||
# optional build flags
|
||||
LOC =
|
||||
|
||||
# variables
|
||||
STATICLIB = zlib.lib
|
||||
SHAREDLIB = zlib1.dll
|
||||
IMPLIB = zdll.lib
|
||||
|
||||
CC = cl
|
||||
AS = ml
|
||||
LD = link
|
||||
AR = lib
|
||||
RC = rc
|
||||
CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC)
|
||||
WFLAGS = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
|
||||
ASFLAGS = -coff -Zi $(LOC)
|
||||
LDFLAGS = -nologo -debug -incremental:no -opt:ref
|
||||
ARFLAGS = -nologo
|
||||
RCFLAGS = /dWIN32 /r
|
||||
|
||||
OBJS = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj \
|
||||
gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj
|
||||
OBJA =
|
||||
|
||||
|
||||
# targets
|
||||
all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \
|
||||
example.exe minigzip.exe example_d.exe minigzip_d.exe
|
||||
|
||||
$(STATICLIB): $(OBJS) $(OBJA)
|
||||
$(AR) $(ARFLAGS) -out:$@ $(OBJS) $(OBJA)
|
||||
|
||||
$(IMPLIB): $(SHAREDLIB)
|
||||
|
||||
$(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) $(OBJA) zlib1.res
|
||||
$(LD) $(LDFLAGS) -def:$(TOP)/win32/zlib.def -dll -implib:$(IMPLIB) \
|
||||
-out:$@ -base:0x5A4C0000 $(OBJS) $(OBJA) zlib1.res
|
||||
if exist $@.manifest \
|
||||
mt -nologo -manifest $@.manifest -outputresource:$@;2
|
||||
|
||||
example.exe: example.obj $(STATICLIB)
|
||||
$(LD) $(LDFLAGS) example.obj $(STATICLIB)
|
||||
if exist $@.manifest \
|
||||
mt -nologo -manifest $@.manifest -outputresource:$@;1
|
||||
|
||||
minigzip.exe: minigzip.obj $(STATICLIB)
|
||||
$(LD) $(LDFLAGS) minigzip.obj $(STATICLIB)
|
||||
if exist $@.manifest \
|
||||
mt -nologo -manifest $@.manifest -outputresource:$@;1
|
||||
|
||||
example_d.exe: example.obj $(IMPLIB)
|
||||
$(LD) $(LDFLAGS) -out:$@ example.obj $(IMPLIB)
|
||||
if exist $@.manifest \
|
||||
mt -nologo -manifest $@.manifest -outputresource:$@;1
|
||||
|
||||
minigzip_d.exe: minigzip.obj $(IMPLIB)
|
||||
$(LD) $(LDFLAGS) -out:$@ minigzip.obj $(IMPLIB)
|
||||
if exist $@.manifest \
|
||||
mt -nologo -manifest $@.manifest -outputresource:$@;1
|
||||
|
||||
{$(TOP)}.c.obj:
|
||||
$(CC) -c $(WFLAGS) $(CFLAGS) $<
|
||||
|
||||
{$(TOP)/test}.c.obj:
|
||||
$(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $<
|
||||
|
||||
{$(TOP)/contrib/masmx64}.c.obj:
|
||||
$(CC) -c $(WFLAGS) $(CFLAGS) $<
|
||||
|
||||
{$(TOP)/contrib/masmx64}.asm.obj:
|
||||
$(AS) -c $(ASFLAGS) $<
|
||||
|
||||
{$(TOP)/contrib/masmx86}.asm.obj:
|
||||
$(AS) -c $(ASFLAGS) $<
|
||||
|
||||
adler32.obj: $(TOP)/adler32.c $(TOP)/zlib.h $(TOP)/zconf.h
|
||||
|
||||
compress.obj: $(TOP)/compress.c $(TOP)/zlib.h $(TOP)/zconf.h
|
||||
|
||||
crc32.obj: $(TOP)/crc32.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/crc32.h
|
||||
|
||||
deflate.obj: $(TOP)/deflate.c $(TOP)/deflate.h $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h
|
||||
|
||||
gzclose.obj: $(TOP)/gzclose.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
|
||||
|
||||
gzlib.obj: $(TOP)/gzlib.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
|
||||
|
||||
gzread.obj: $(TOP)/gzread.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
|
||||
|
||||
gzwrite.obj: $(TOP)/gzwrite.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h
|
||||
|
||||
infback.obj: $(TOP)/infback.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
|
||||
$(TOP)/inffast.h $(TOP)/inffixed.h
|
||||
|
||||
inffast.obj: $(TOP)/inffast.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
|
||||
$(TOP)/inffast.h
|
||||
|
||||
inflate.obj: $(TOP)/inflate.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \
|
||||
$(TOP)/inffast.h $(TOP)/inffixed.h
|
||||
|
||||
inftrees.obj: $(TOP)/inftrees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h
|
||||
|
||||
trees.obj: $(TOP)/trees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/deflate.h $(TOP)/trees.h
|
||||
|
||||
uncompr.obj: $(TOP)/uncompr.c $(TOP)/zlib.h $(TOP)/zconf.h
|
||||
|
||||
zutil.obj: $(TOP)/zutil.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h
|
||||
|
||||
gvmat64.obj: $(TOP)/contrib\masmx64\gvmat64.asm
|
||||
|
||||
inffasx64.obj: $(TOP)/contrib\masmx64\inffasx64.asm
|
||||
|
||||
inffas8664.obj: $(TOP)/contrib\masmx64\inffas8664.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h \
|
||||
$(TOP)/inftrees.h $(TOP)/inflate.h $(TOP)/inffast.h
|
||||
|
||||
inffas32.obj: $(TOP)/contrib\masmx86\inffas32.asm
|
||||
|
||||
match686.obj: $(TOP)/contrib\masmx86\match686.asm
|
||||
|
||||
example.obj: $(TOP)/test/example.c $(TOP)/zlib.h $(TOP)/zconf.h
|
||||
|
||||
minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zlib.h $(TOP)/zconf.h
|
||||
|
||||
zlib1.res: $(TOP)/win32/zlib1.rc
|
||||
$(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/zlib1.rc
|
||||
|
||||
# testing
|
||||
test: example.exe minigzip.exe
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
testdll: example_d.exe minigzip_d.exe
|
||||
example_d
|
||||
echo hello world | minigzip_d | minigzip_d -d
|
||||
|
||||
|
||||
# cleanup
|
||||
clean:
|
||||
-del $(STATICLIB)
|
||||
-del $(SHAREDLIB)
|
||||
-del $(IMPLIB)
|
||||
-del *.obj
|
||||
-del *.res
|
||||
-del *.exp
|
||||
-del *.exe
|
||||
-del *.pdb
|
||||
-del *.manifest
|
||||
-del foo.gz
|
|
@ -0,0 +1,103 @@
|
|||
ZLIB DATA COMPRESSION LIBRARY
|
||||
|
||||
zlib 1.2.8 is a general purpose data compression library. All the code is
|
||||
thread safe. The data format used by the zlib library is described by RFCs
|
||||
(Request for Comments) 1950 to 1952 in the files
|
||||
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
|
||||
and rfc1952.txt (gzip format).
|
||||
|
||||
All functions of the compression library are documented in the file zlib.h
|
||||
(volunteer to write man pages welcome, contact zlib@gzip.org). Two compiled
|
||||
examples are distributed in this package, example and minigzip. The example_d
|
||||
and minigzip_d flavors validate that the zlib1.dll file is working correctly.
|
||||
|
||||
Questions about zlib should be sent to <zlib@gzip.org>. The zlib home page
|
||||
is http://zlib.net/ . Before reporting a problem, please check this site to
|
||||
verify that you have the latest version of zlib; otherwise get the latest
|
||||
version and check whether the problem still exists or not.
|
||||
|
||||
PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html
|
||||
before asking for help.
|
||||
|
||||
|
||||
Manifest:
|
||||
|
||||
The package zlib-1.2.8-win32-x86.zip will contain the following files:
|
||||
|
||||
README-WIN32.txt This document
|
||||
ChangeLog Changes since previous zlib packages
|
||||
DLL_FAQ.txt Frequently asked questions about zlib1.dll
|
||||
zlib.3.pdf Documentation of this library in Adobe Acrobat format
|
||||
|
||||
example.exe A statically-bound example (using zlib.lib, not the dll)
|
||||
example.pdb Symbolic information for debugging example.exe
|
||||
|
||||
example_d.exe A zlib1.dll bound example (using zdll.lib)
|
||||
example_d.pdb Symbolic information for debugging example_d.exe
|
||||
|
||||
minigzip.exe A statically-bound test program (using zlib.lib, not the dll)
|
||||
minigzip.pdb Symbolic information for debugging minigzip.exe
|
||||
|
||||
minigzip_d.exe A zlib1.dll bound test program (using zdll.lib)
|
||||
minigzip_d.pdb Symbolic information for debugging minigzip_d.exe
|
||||
|
||||
zlib.h Install these files into the compilers' INCLUDE path to
|
||||
zconf.h compile programs which use zlib.lib or zdll.lib
|
||||
|
||||
zdll.lib Install these files into the compilers' LIB path if linking
|
||||
zdll.exp a compiled program to the zlib1.dll binary
|
||||
|
||||
zlib.lib Install these files into the compilers' LIB path to link zlib
|
||||
zlib.pdb into compiled programs, without zlib1.dll runtime dependency
|
||||
(zlib.pdb provides debugging info to the compile time linker)
|
||||
|
||||
zlib1.dll Install this binary shared library into the system PATH, or
|
||||
the program's runtime directory (where the .exe resides)
|
||||
zlib1.pdb Install in the same directory as zlib1.dll, in order to debug
|
||||
an application crash using WinDbg or similar tools.
|
||||
|
||||
All .pdb files above are entirely optional, but are very useful to a developer
|
||||
attempting to diagnose program misbehavior or a crash. Many additional
|
||||
important files for developers can be found in the zlib127.zip source package
|
||||
available from http://zlib.net/ - review that package's README file for details.
|
||||
|
||||
|
||||
Acknowledgments:
|
||||
|
||||
The deflate format used by zlib was defined by Phil Katz. The deflate and
|
||||
zlib specifications were written by L. Peter Deutsch. Thanks to all the
|
||||
people who reported problems and suggested various improvements in zlib; they
|
||||
are too numerous to cite here.
|
||||
|
||||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-2012 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
jloup@gzip.org madler@alumni.caltech.edu
|
||||
|
||||
If you use the zlib library in a product, we would appreciate *not* receiving
|
||||
lengthy legal documents to sign. The sources are provided for free but without
|
||||
warranty of any kind. The library has been entirely written by Jean-loup
|
||||
Gailly and Mark Adler; it does not include third-party code.
|
||||
|
||||
If you redistribute modified sources, we would appreciate that you include in
|
||||
the file ChangeLog history information documenting your changes. Please read
|
||||
the FAQ for more information on the distribution of modified source versions.
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
To build zlib using the Microsoft Visual C++ environment,
|
||||
use the appropriate project from the projects/ directory.
|
|
@ -0,0 +1,86 @@
|
|||
; zlib data compression library
|
||||
EXPORTS
|
||||
; basic functions
|
||||
zlibVersion
|
||||
deflate
|
||||
deflateEnd
|
||||
inflate
|
||||
inflateEnd
|
||||
; advanced functions
|
||||
deflateSetDictionary
|
||||
deflateCopy
|
||||
deflateReset
|
||||
deflateParams
|
||||
deflateTune
|
||||
deflateBound
|
||||
deflatePending
|
||||
deflatePrime
|
||||
deflateSetHeader
|
||||
inflateSetDictionary
|
||||
inflateGetDictionary
|
||||
inflateSync
|
||||
inflateCopy
|
||||
inflateReset
|
||||
inflateReset2
|
||||
inflatePrime
|
||||
inflateMark
|
||||
inflateGetHeader
|
||||
inflateBack
|
||||
inflateBackEnd
|
||||
zlibCompileFlags
|
||||
; utility functions
|
||||
compress
|
||||
compress2
|
||||
compressBound
|
||||
uncompress
|
||||
gzopen
|
||||
gzdopen
|
||||
gzbuffer
|
||||
gzsetparams
|
||||
gzread
|
||||
gzwrite
|
||||
gzprintf
|
||||
gzvprintf
|
||||
gzputs
|
||||
gzgets
|
||||
gzputc
|
||||
gzgetc
|
||||
gzungetc
|
||||
gzflush
|
||||
gzseek
|
||||
gzrewind
|
||||
gztell
|
||||
gzoffset
|
||||
gzeof
|
||||
gzdirect
|
||||
gzclose
|
||||
gzclose_r
|
||||
gzclose_w
|
||||
gzerror
|
||||
gzclearerr
|
||||
; large file functions
|
||||
gzopen64
|
||||
gzseek64
|
||||
gztell64
|
||||
gzoffset64
|
||||
adler32_combine64
|
||||
crc32_combine64
|
||||
; checksum functions
|
||||
adler32
|
||||
crc32
|
||||
adler32_combine
|
||||
crc32_combine
|
||||
; various hacks, don't look :)
|
||||
deflateInit_
|
||||
deflateInit2_
|
||||
inflateInit_
|
||||
inflateInit2_
|
||||
inflateBackInit_
|
||||
gzgetc_
|
||||
zError
|
||||
inflateSyncPoint
|
||||
get_crc_table
|
||||
inflateUndermine
|
||||
inflateResetKeep
|
||||
deflateResetKeep
|
||||
gzopen_w
|
|
@ -0,0 +1,40 @@
|
|||
#include <winver.h>
|
||||
#include "../zlib.h"
|
||||
|
||||
#ifdef GCC_WINDRES
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
#else
|
||||
VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
|
||||
#endif
|
||||
FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0
|
||||
PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 1
|
||||
#else
|
||||
FILEFLAGS 0
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0 // not used
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904E4"
|
||||
//language ID = U.S. English, char set = Windows, Multilingual
|
||||
BEGIN
|
||||
VALUE "FileDescription", "zlib data compression library\0"
|
||||
VALUE "FileVersion", ZLIB_VERSION "\0"
|
||||
VALUE "InternalName", "zlib1.dll\0"
|
||||
VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0"
|
||||
VALUE "OriginalFilename", "zlib1.dll\0"
|
||||
VALUE "ProductName", "zlib\0"
|
||||
VALUE "ProductVersion", ZLIB_VERSION "\0"
|
||||
VALUE "Comments", "For more information visit http://www.zlib.net/\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0409, 1252
|
||||
END
|
||||
END
|
|
@ -1,5 +1,5 @@
|
|||
/* zconf.h -- configuration of the zlib compression library
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly.
|
||||
* Copyright (C) 1995-2013 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
|||
|
||||
#ifndef ZCONF_H
|
||||
#define ZCONF_H
|
||||
#cmakedefine Z_PREFIX
|
||||
#cmakedefine Z_HAVE_UNISTD_H
|
||||
|
||||
/*
|
||||
* If you *really* need a unique prefix for all types and library functions,
|
||||
|
@ -15,11 +17,13 @@
|
|||
* this permanently in zconf.h using "./configure --zprefix".
|
||||
*/
|
||||
#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
|
||||
# define Z_PREFIX_SET
|
||||
|
||||
/* all linked symbols */
|
||||
# define _dist_code z__dist_code
|
||||
# define _length_code z__length_code
|
||||
# define _tr_align z__tr_align
|
||||
# define _tr_flush_bits z__tr_flush_bits
|
||||
# define _tr_flush_block z__tr_flush_block
|
||||
# define _tr_init z__tr_init
|
||||
# define _tr_stored_block z__tr_stored_block
|
||||
|
@ -27,9 +31,11 @@
|
|||
# define adler32 z_adler32
|
||||
# define adler32_combine z_adler32_combine
|
||||
# define adler32_combine64 z_adler32_combine64
|
||||
# define compress z_compress
|
||||
# define compress2 z_compress2
|
||||
# define compressBound z_compressBound
|
||||
# ifndef Z_SOLO
|
||||
# define compress z_compress
|
||||
# define compress2 z_compress2
|
||||
# define compressBound z_compressBound
|
||||
# endif
|
||||
# define crc32 z_crc32
|
||||
# define crc32_combine z_crc32_combine
|
||||
# define crc32_combine64 z_crc32_combine64
|
||||
|
@ -40,44 +46,53 @@
|
|||
# define deflateInit2_ z_deflateInit2_
|
||||
# define deflateInit_ z_deflateInit_
|
||||
# define deflateParams z_deflateParams
|
||||
# define deflatePending z_deflatePending
|
||||
# define deflatePrime z_deflatePrime
|
||||
# define deflateReset z_deflateReset
|
||||
# define deflateResetKeep z_deflateResetKeep
|
||||
# define deflateSetDictionary z_deflateSetDictionary
|
||||
# define deflateSetHeader z_deflateSetHeader
|
||||
# define deflateTune z_deflateTune
|
||||
# define deflate_copyright z_deflate_copyright
|
||||
# define get_crc_table z_get_crc_table
|
||||
# define gz_error z_gz_error
|
||||
# define gz_intmax z_gz_intmax
|
||||
# define gz_strwinerror z_gz_strwinerror
|
||||
# define gzbuffer z_gzbuffer
|
||||
# define gzclearerr z_gzclearerr
|
||||
# define gzclose z_gzclose
|
||||
# define gzclose_r z_gzclose_r
|
||||
# define gzclose_w z_gzclose_w
|
||||
# define gzdirect z_gzdirect
|
||||
# define gzdopen z_gzdopen
|
||||
# define gzeof z_gzeof
|
||||
# define gzerror z_gzerror
|
||||
# define gzflush z_gzflush
|
||||
# define gzgetc z_gzgetc
|
||||
# define gzgets z_gzgets
|
||||
# define gzoffset z_gzoffset
|
||||
# define gzoffset64 z_gzoffset64
|
||||
# define gzopen z_gzopen
|
||||
# define gzopen64 z_gzopen64
|
||||
# define gzprintf z_gzprintf
|
||||
# define gzputc z_gzputc
|
||||
# define gzputs z_gzputs
|
||||
# define gzread z_gzread
|
||||
# define gzrewind z_gzrewind
|
||||
# define gzseek z_gzseek
|
||||
# define gzseek64 z_gzseek64
|
||||
# define gzsetparams z_gzsetparams
|
||||
# define gztell z_gztell
|
||||
# define gztell64 z_gztell64
|
||||
# define gzungetc z_gzungetc
|
||||
# define gzwrite z_gzwrite
|
||||
# ifndef Z_SOLO
|
||||
# define gz_error z_gz_error
|
||||
# define gz_intmax z_gz_intmax
|
||||
# define gz_strwinerror z_gz_strwinerror
|
||||
# define gzbuffer z_gzbuffer
|
||||
# define gzclearerr z_gzclearerr
|
||||
# define gzclose z_gzclose
|
||||
# define gzclose_r z_gzclose_r
|
||||
# define gzclose_w z_gzclose_w
|
||||
# define gzdirect z_gzdirect
|
||||
# define gzdopen z_gzdopen
|
||||
# define gzeof z_gzeof
|
||||
# define gzerror z_gzerror
|
||||
# define gzflush z_gzflush
|
||||
# define gzgetc z_gzgetc
|
||||
# define gzgetc_ z_gzgetc_
|
||||
# define gzgets z_gzgets
|
||||
# define gzoffset z_gzoffset
|
||||
# define gzoffset64 z_gzoffset64
|
||||
# define gzopen z_gzopen
|
||||
# define gzopen64 z_gzopen64
|
||||
# ifdef _WIN32
|
||||
# define gzopen_w z_gzopen_w
|
||||
# endif
|
||||
# define gzprintf z_gzprintf
|
||||
# define gzvprintf z_gzvprintf
|
||||
# define gzputc z_gzputc
|
||||
# define gzputs z_gzputs
|
||||
# define gzread z_gzread
|
||||
# define gzrewind z_gzrewind
|
||||
# define gzseek z_gzseek
|
||||
# define gzseek64 z_gzseek64
|
||||
# define gzsetparams z_gzsetparams
|
||||
# define gztell z_gztell
|
||||
# define gztell64 z_gztell64
|
||||
# define gzungetc z_gzungetc
|
||||
# define gzwrite z_gzwrite
|
||||
# endif
|
||||
# define inflate z_inflate
|
||||
# define inflateBack z_inflateBack
|
||||
# define inflateBackEnd z_inflateBackEnd
|
||||
|
@ -92,16 +107,22 @@
|
|||
# define inflateReset z_inflateReset
|
||||
# define inflateReset2 z_inflateReset2
|
||||
# define inflateSetDictionary z_inflateSetDictionary
|
||||
# define inflateGetDictionary z_inflateGetDictionary
|
||||
# define inflateSync z_inflateSync
|
||||
# define inflateSyncPoint z_inflateSyncPoint
|
||||
# define inflateUndermine z_inflateUndermine
|
||||
# define inflateResetKeep z_inflateResetKeep
|
||||
# define inflate_copyright z_inflate_copyright
|
||||
# define inflate_fast z_inflate_fast
|
||||
# define inflate_table z_inflate_table
|
||||
# define uncompress z_uncompress
|
||||
# ifndef Z_SOLO
|
||||
# define uncompress z_uncompress
|
||||
# endif
|
||||
# define zError z_zError
|
||||
# define zcalloc z_zcalloc
|
||||
# define zcfree z_zcfree
|
||||
# ifndef Z_SOLO
|
||||
# define zcalloc z_zcalloc
|
||||
# define zcfree z_zcfree
|
||||
# endif
|
||||
# define zlibCompileFlags z_zlibCompileFlags
|
||||
# define zlibVersion z_zlibVersion
|
||||
|
||||
|
@ -111,7 +132,9 @@
|
|||
# define alloc_func z_alloc_func
|
||||
# define charf z_charf
|
||||
# define free_func z_free_func
|
||||
# define gzFile z_gzFile
|
||||
# ifndef Z_SOLO
|
||||
# define gzFile z_gzFile
|
||||
# endif
|
||||
# define gz_header z_gz_header
|
||||
# define gz_headerp z_gz_headerp
|
||||
# define in_func z_in_func
|
||||
|
@ -197,6 +220,12 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(ZLIB_CONST) && !defined(z_const)
|
||||
# define z_const const
|
||||
#else
|
||||
# define z_const
|
||||
#endif
|
||||
|
||||
/* Some Mac compilers merge all .h files incorrectly: */
|
||||
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
|
||||
# define NO_DUMMY_DECL
|
||||
|
@ -243,6 +272,14 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef Z_ARG /* function prototypes for stdarg */
|
||||
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
# define Z_ARG(args) args
|
||||
# else
|
||||
# define Z_ARG(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The following definitions for FAR are needed only for MSDOS mixed
|
||||
* model programming (small or medium model with some far allocations).
|
||||
* This was tested only with MSC; for other MSDOS compilers you may have
|
||||
|
@ -356,12 +393,47 @@ typedef uLong FAR uLongf;
|
|||
typedef Byte *voidp;
|
||||
#endif
|
||||
|
||||
#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
|
||||
# include <limits.h>
|
||||
# if (UINT_MAX == 0xffffffffUL)
|
||||
# define Z_U4 unsigned
|
||||
# elif (ULONG_MAX == 0xffffffffUL)
|
||||
# define Z_U4 unsigned long
|
||||
# elif (USHRT_MAX == 0xffffffffUL)
|
||||
# define Z_U4 unsigned short
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef Z_U4
|
||||
typedef Z_U4 z_crc_t;
|
||||
#else
|
||||
typedef unsigned long z_crc_t;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
|
||||
# define Z_HAVE_UNISTD_H
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
|
||||
# define Z_HAVE_STDARG_H
|
||||
#endif
|
||||
|
||||
#ifdef STDC
|
||||
# include <sys/types.h> /* for off_t */
|
||||
# ifndef Z_SOLO
|
||||
# include <sys/types.h> /* for off_t */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
# ifndef Z_SOLO
|
||||
# include <stdarg.h> /* for va_list */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef Z_SOLO
|
||||
# include <stddef.h> /* for wchar_t */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
|
||||
|
@ -370,21 +442,38 @@ typedef uLong FAR uLongf;
|
|||
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
|
||||
* equivalently requesting no 64-bit operations
|
||||
*/
|
||||
#if -_LARGEFILE64_SOURCE - -1 == 1
|
||||
#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
|
||||
# undef _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
|
||||
# include <unistd.h> /* for SEEK_* and off_t */
|
||||
# ifdef VMS
|
||||
# include <unixio.h> /* for off_t */
|
||||
# endif
|
||||
# ifndef z_off_t
|
||||
# define z_off_t off_t
|
||||
#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
|
||||
# define Z_HAVE_UNISTD_H
|
||||
#endif
|
||||
#ifndef Z_SOLO
|
||||
# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
|
||||
# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
|
||||
# ifdef VMS
|
||||
# include <unixio.h> /* for off_t */
|
||||
# endif
|
||||
# ifndef z_off_t
|
||||
# define z_off_t off_t
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
|
||||
# define Z_LFS64
|
||||
#endif
|
||||
|
||||
#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
|
||||
# define Z_LARGE64
|
||||
#endif
|
||||
|
||||
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
|
||||
# define Z_WANT64
|
||||
#endif
|
||||
|
||||
#if !defined(SEEK_SET) && !defined(Z_SOLO)
|
||||
# define SEEK_SET 0 /* Seek from beginning of file. */
|
||||
# define SEEK_CUR 1 /* Seek from current position. */
|
||||
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
|
||||
|
@ -394,18 +483,14 @@ typedef uLong FAR uLongf;
|
|||
# define z_off_t long
|
||||
#endif
|
||||
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
#if !defined(_WIN32) && defined(Z_LARGE64)
|
||||
# define z_off64_t off64_t
|
||||
#else
|
||||
# define z_off64_t z_off_t
|
||||
#endif
|
||||
|
||||
#if defined(__OS400__)
|
||||
# define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
#if defined(__MVS__)
|
||||
# define NO_vsnprintf
|
||||
# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
|
||||
# define z_off64_t __int64
|
||||
# else
|
||||
# define z_off64_t z_off_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* MVS linker does not support external names larger than 8 bytes */
|
|
@ -1,7 +1,7 @@
|
|||
/* zlib.h -- interface of the 'zlib' general purpose compression library
|
||||
version 1.2.5, April 19th, 2010
|
||||
version 1.2.8, April 28th, 2013
|
||||
|
||||
Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
|
||||
Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -24,8 +24,8 @@
|
|||
|
||||
|
||||
The data format used by the zlib library is described by RFCs (Request for
|
||||
Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
|
||||
(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
|
||||
Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
|
||||
(zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
|
||||
*/
|
||||
|
||||
#ifndef ZLIB_H
|
||||
|
@ -37,11 +37,11 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ZLIB_VERSION "1.2.5"
|
||||
#define ZLIB_VERNUM 0x1250
|
||||
#define ZLIB_VERSION "1.2.8"
|
||||
#define ZLIB_VERNUM 0x1280
|
||||
#define ZLIB_VER_MAJOR 1
|
||||
#define ZLIB_VER_MINOR 2
|
||||
#define ZLIB_VER_REVISION 5
|
||||
#define ZLIB_VER_REVISION 8
|
||||
#define ZLIB_VER_SUBREVISION 0
|
||||
|
||||
/*
|
||||
|
@ -83,15 +83,15 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address));
|
|||
struct internal_state;
|
||||
|
||||
typedef struct z_stream_s {
|
||||
Bytef *next_in; /* next input byte */
|
||||
z_const Bytef *next_in; /* next input byte */
|
||||
uInt avail_in; /* number of bytes available at next_in */
|
||||
uLong total_in; /* total nb of input bytes read so far */
|
||||
uLong total_in; /* total number of input bytes read so far */
|
||||
|
||||
Bytef *next_out; /* next output byte should be put there */
|
||||
uInt avail_out; /* remaining free space at next_out */
|
||||
uLong total_out; /* total nb of bytes output so far */
|
||||
uLong total_out; /* total number of bytes output so far */
|
||||
|
||||
char *msg; /* last error message, NULL if no error */
|
||||
z_const char *msg; /* last error message, NULL if no error */
|
||||
struct internal_state FAR *state; /* not visible by applications */
|
||||
|
||||
alloc_func zalloc; /* used to allocate the internal state */
|
||||
|
@ -327,8 +327,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
|
|||
|
||||
Z_FINISH can be used immediately after deflateInit if all the compression
|
||||
is to be done in a single step. In this case, avail_out must be at least the
|
||||
value returned by deflateBound (see below). If deflate does not return
|
||||
Z_STREAM_END, then it must be called again as described above.
|
||||
value returned by deflateBound (see below). Then deflate is guaranteed to
|
||||
return Z_STREAM_END. If not enough output space is provided, deflate will
|
||||
not return Z_STREAM_END, and it must be called again as described above.
|
||||
|
||||
deflate() sets strm->adler to the adler32 checksum of all input read
|
||||
so far (that is, total_in bytes).
|
||||
|
@ -451,23 +452,29 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
|
|||
error. However if all decompression is to be performed in a single step (a
|
||||
single call of inflate), the parameter flush should be set to Z_FINISH. In
|
||||
this case all pending input is processed and all pending output is flushed;
|
||||
avail_out must be large enough to hold all the uncompressed data. (The size
|
||||
of the uncompressed data may have been saved by the compressor for this
|
||||
purpose.) The next operation on this stream must be inflateEnd to deallocate
|
||||
the decompression state. The use of Z_FINISH is never required, but can be
|
||||
used to inform inflate that a faster approach may be used for the single
|
||||
inflate() call.
|
||||
avail_out must be large enough to hold all of the uncompressed data for the
|
||||
operation to complete. (The size of the uncompressed data may have been
|
||||
saved by the compressor for this purpose.) The use of Z_FINISH is not
|
||||
required to perform an inflation in one step. However it may be used to
|
||||
inform inflate that a faster approach can be used for the single inflate()
|
||||
call. Z_FINISH also informs inflate to not maintain a sliding window if the
|
||||
stream completes, which reduces inflate's memory footprint. If the stream
|
||||
does not complete, either because not all of the stream is provided or not
|
||||
enough output space is provided, then a sliding window will be allocated and
|
||||
inflate() can be called again to continue the operation as if Z_NO_FLUSH had
|
||||
been used.
|
||||
|
||||
In this implementation, inflate() always flushes as much output as
|
||||
possible to the output buffer, and always uses the faster approach on the
|
||||
first call. So the only effect of the flush parameter in this implementation
|
||||
is on the return value of inflate(), as noted below, or when it returns early
|
||||
because Z_BLOCK or Z_TREES is used.
|
||||
first call. So the effects of the flush parameter in this implementation are
|
||||
on the return value of inflate() as noted below, when inflate() returns early
|
||||
when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
|
||||
memory for a sliding window when Z_FINISH is used.
|
||||
|
||||
If a preset dictionary is needed after this call (see inflateSetDictionary
|
||||
below), inflate sets strm->adler to the adler32 checksum of the dictionary
|
||||
below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
|
||||
chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
|
||||
strm->adler to the adler32 checksum of all output produced so far (that is,
|
||||
strm->adler to the Adler-32 checksum of all output produced so far (that is,
|
||||
total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
|
||||
below. At the end of the stream, inflate() checks that its computed adler32
|
||||
checksum is equal to that saved by the compressor and returns Z_STREAM_END
|
||||
|
@ -478,7 +485,9 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
|
|||
initializing with inflateInit2(). Any information contained in the gzip
|
||||
header is not retained, so applications that need that information should
|
||||
instead use raw inflate, see inflateInit2() below, or inflateBack() and
|
||||
perform their own processing of the gzip header and trailer.
|
||||
perform their own processing of the gzip header and trailer. When processing
|
||||
gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
|
||||
producted so far. The CRC-32 is checked against the gzip trailer.
|
||||
|
||||
inflate() returns Z_OK if some progress has been made (more input processed
|
||||
or more output produced), Z_STREAM_END if the end of the compressed data has
|
||||
|
@ -580,10 +589,15 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
|
|||
uInt dictLength));
|
||||
/*
|
||||
Initializes the compression dictionary from the given byte sequence
|
||||
without producing any compressed output. This function must be called
|
||||
immediately after deflateInit, deflateInit2 or deflateReset, before any call
|
||||
of deflate. The compressor and decompressor must use exactly the same
|
||||
dictionary (see inflateSetDictionary).
|
||||
without producing any compressed output. When using the zlib format, this
|
||||
function must be called immediately after deflateInit, deflateInit2 or
|
||||
deflateReset, and before any call of deflate. When doing raw deflate, this
|
||||
function must be called either before any call of deflate, or immediately
|
||||
after the completion of a deflate block, i.e. after all input has been
|
||||
consumed and all output has been delivered when using any of the flush
|
||||
options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
|
||||
compressor and decompressor must use exactly the same dictionary (see
|
||||
inflateSetDictionary).
|
||||
|
||||
The dictionary should consist of strings (byte sequences) that are likely
|
||||
to be encountered later in the data to be compressed, with the most commonly
|
||||
|
@ -610,8 +624,8 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
|
|||
deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
|
||||
parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
|
||||
inconsistent (for example if deflate has already been called for this stream
|
||||
or if the compression method is bsort). deflateSetDictionary does not
|
||||
perform any compression: this will be done by deflate().
|
||||
or if not at a block boundary for raw deflate). deflateSetDictionary does
|
||||
not perform any compression: this will be done by deflate().
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
|
||||
|
@ -688,9 +702,29 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
|
|||
deflation of sourceLen bytes. It must be called after deflateInit() or
|
||||
deflateInit2(), and after deflateSetHeader(), if used. This would be used
|
||||
to allocate an output buffer for deflation in a single pass, and so would be
|
||||
called before deflate().
|
||||
called before deflate(). If that first deflate() call is provided the
|
||||
sourceLen input bytes, an output buffer allocated to the size returned by
|
||||
deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
|
||||
to return Z_STREAM_END. Note that it is possible for the compressed size to
|
||||
be larger than the value returned by deflateBound() if flush options other
|
||||
than Z_FINISH or Z_NO_FLUSH are used.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
|
||||
unsigned *pending,
|
||||
int *bits));
|
||||
/*
|
||||
deflatePending() returns the number of bytes and bits of output that have
|
||||
been generated, but not yet provided in the available output. The bytes not
|
||||
provided would be due to the available output space having being consumed.
|
||||
The number of bits of output not provided are between 0 and 7, where they
|
||||
await more bits to join them in order to fill out a full byte. If pending
|
||||
or bits are Z_NULL, then those values are not set.
|
||||
|
||||
deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
|
||||
stream state was inconsistent.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
|
||||
int bits,
|
||||
int value));
|
||||
|
@ -703,8 +737,9 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
|
|||
than or equal to 16, and that many of the least significant bits of value
|
||||
will be inserted in the output.
|
||||
|
||||
deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
|
||||
stream state was inconsistent.
|
||||
deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
|
||||
room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
|
||||
source stream state was inconsistent.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
|
||||
|
@ -790,10 +825,11 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
|
|||
if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
|
||||
can be determined from the adler32 value returned by that call of inflate.
|
||||
The compressor and decompressor must use exactly the same dictionary (see
|
||||
deflateSetDictionary). For raw inflate, this function can be called
|
||||
immediately after inflateInit2() or inflateReset() and before any call of
|
||||
inflate() to set the dictionary. The application must insure that the
|
||||
dictionary that was used for compression is provided.
|
||||
deflateSetDictionary). For raw inflate, this function can be called at any
|
||||
time to set the dictionary. If the provided dictionary is smaller than the
|
||||
window and there is already data in the window, then the provided dictionary
|
||||
will amend what's there. The application must insure that the dictionary
|
||||
that was used for compression is provided.
|
||||
|
||||
inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
|
||||
parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
|
||||
|
@ -803,19 +839,38 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
|
|||
inflate().
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
|
||||
Bytef *dictionary,
|
||||
uInt *dictLength));
|
||||
/*
|
||||
Returns the sliding dictionary being maintained by inflate. dictLength is
|
||||
set to the number of bytes in the dictionary, and that many bytes are copied
|
||||
to dictionary. dictionary must have enough space, where 32768 bytes is
|
||||
always enough. If inflateGetDictionary() is called with dictionary equal to
|
||||
Z_NULL, then only the dictionary length is returned, and nothing is copied.
|
||||
Similary, if dictLength is Z_NULL, then it is not set.
|
||||
|
||||
inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
|
||||
stream state is inconsistent.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
|
||||
/*
|
||||
Skips invalid compressed data until a full flush point (see above the
|
||||
description of deflate with Z_FULL_FLUSH) can be found, or until all
|
||||
Skips invalid compressed data until a possible full flush point (see above
|
||||
for the description of deflate with Z_FULL_FLUSH) can be found, or until all
|
||||
available input is skipped. No output is provided.
|
||||
|
||||
inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
|
||||
if no more input was provided, Z_DATA_ERROR if no flush point has been
|
||||
found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the
|
||||
success case, the application may save the current current value of total_in
|
||||
which indicates where valid compressed data was found. In the error case,
|
||||
the application may repeatedly call inflateSync, providing more input each
|
||||
time, until success or end of the input data.
|
||||
inflateSync searches for a 00 00 FF FF pattern in the compressed data.
|
||||
All full flush points have this pattern, but not all occurrences of this
|
||||
pattern are full flush points.
|
||||
|
||||
inflateSync returns Z_OK if a possible full flush point has been found,
|
||||
Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
|
||||
has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
|
||||
In the success case, the application may save the current current value of
|
||||
total_in which indicates where valid compressed data was found. In the
|
||||
error case, the application may repeatedly call inflateSync, providing more
|
||||
input each time, until success or end of the input data.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
|
||||
|
@ -962,12 +1017,13 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
|
|||
See inflateBack() for the usage of these routines.
|
||||
|
||||
inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
|
||||
the paramaters are invalid, Z_MEM_ERROR if the internal state could not be
|
||||
the parameters are invalid, Z_MEM_ERROR if the internal state could not be
|
||||
allocated, or Z_VERSION_ERROR if the version of the library does not match
|
||||
the version of the header file.
|
||||
*/
|
||||
|
||||
typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
|
||||
typedef unsigned (*in_func) OF((void FAR *,
|
||||
z_const unsigned char FAR * FAR *));
|
||||
typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
|
||||
|
||||
ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
|
||||
|
@ -975,11 +1031,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
|
|||
out_func out, void FAR *out_desc));
|
||||
/*
|
||||
inflateBack() does a raw inflate with a single call using a call-back
|
||||
interface for input and output. This is more efficient than inflate() for
|
||||
file i/o applications in that it avoids copying between the output and the
|
||||
sliding window by simply making the window itself the output buffer. This
|
||||
function trusts the application to not change the output buffer passed by
|
||||
the output function, at least until inflateBack() returns.
|
||||
interface for input and output. This is potentially more efficient than
|
||||
inflate() for file i/o applications, in that it avoids copying between the
|
||||
output and the sliding window by simply making the window itself the output
|
||||
buffer. inflate() can be faster on modern CPUs when used with large
|
||||
buffers. inflateBack() trusts the application to not change the output
|
||||
buffer passed by the output function, at least until inflateBack() returns.
|
||||
|
||||
inflateBackInit() must be called first to allocate the internal state
|
||||
and to initialize the state with the user-provided window buffer.
|
||||
|
@ -1088,6 +1145,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
|
|||
27-31: 0 (reserved)
|
||||
*/
|
||||
|
||||
#ifndef Z_SOLO
|
||||
|
||||
/* utility functions */
|
||||
|
||||
|
@ -1149,10 +1207,11 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
|
|||
|
||||
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||
buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
|
||||
buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
|
||||
the case where there is not enough room, uncompress() will fill the output
|
||||
buffer with the uncompressed data up to that point.
|
||||
*/
|
||||
|
||||
|
||||
/* gzip file access functions */
|
||||
|
||||
/*
|
||||
|
@ -1162,7 +1221,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
|
|||
wrapper, documented in RFC 1952, wrapped around a deflate stream.
|
||||
*/
|
||||
|
||||
typedef voidp gzFile; /* opaque gzip file descriptor */
|
||||
typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
|
||||
|
||||
/*
|
||||
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
|
||||
|
@ -1172,13 +1231,28 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
|
|||
a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
|
||||
compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
|
||||
for fixed code compression as in "wb9F". (See the description of
|
||||
deflateInit2 for more information about the strategy parameter.) Also "a"
|
||||
can be used instead of "w" to request that the gzip stream that will be
|
||||
written be appended to the file. "+" will result in an error, since reading
|
||||
and writing to the same gzip file is not supported.
|
||||
deflateInit2 for more information about the strategy parameter.) 'T' will
|
||||
request transparent writing or appending with no compression and not using
|
||||
the gzip format.
|
||||
|
||||
"a" can be used instead of "w" to request that the gzip stream that will
|
||||
be written be appended to the file. "+" will result in an error, since
|
||||
reading and writing to the same gzip file is not supported. The addition of
|
||||
"x" when writing will create the file exclusively, which fails if the file
|
||||
already exists. On systems that support it, the addition of "e" when
|
||||
reading or writing will set the flag to close the file on an execve() call.
|
||||
|
||||
These functions, as well as gzip, will read and decode a sequence of gzip
|
||||
streams in a file. The append function of gzopen() can be used to create
|
||||
such a file. (Also see gzflush() for another way to do this.) When
|
||||
appending, gzopen does not test whether the file begins with a gzip stream,
|
||||
nor does it look for the end of the gzip streams to begin appending. gzopen
|
||||
will simply append a gzip stream to the existing file.
|
||||
|
||||
gzopen can be used to read a file which is not in gzip format; in this
|
||||
case gzread will directly read from the file without decompression.
|
||||
case gzread will directly read from the file without decompression. When
|
||||
reading, this will be detected automatically by looking for the magic two-
|
||||
byte gzip header.
|
||||
|
||||
gzopen returns NULL if the file could not be opened, if there was
|
||||
insufficient memory to allocate the gzFile state, or if an invalid mode was
|
||||
|
@ -1197,7 +1271,11 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
|
|||
descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
|
||||
fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
|
||||
mode);. The duplicated descriptor should be saved to avoid a leak, since
|
||||
gzdopen does not close fd if it fails.
|
||||
gzdopen does not close fd if it fails. If you are using fileno() to get the
|
||||
file descriptor from a FILE *, then you will have to use dup() to avoid
|
||||
double-close()ing the file descriptor. Both gzclose() and fclose() will
|
||||
close the associated file descriptor, so they need to have different file
|
||||
descriptors.
|
||||
|
||||
gzdopen returns NULL if there was insufficient memory to allocate the
|
||||
gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
|
||||
|
@ -1235,14 +1313,26 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
|
|||
ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
|
||||
/*
|
||||
Reads the given number of uncompressed bytes from the compressed file. If
|
||||
the input file was not in gzip format, gzread copies the given number of
|
||||
bytes into the buffer.
|
||||
the input file is not in gzip format, gzread copies the given number of
|
||||
bytes into the buffer directly from the file.
|
||||
|
||||
After reaching the end of a gzip stream in the input, gzread will continue
|
||||
to read, looking for another gzip stream, or failing that, reading the rest
|
||||
of the input file directly without decompression. The entire input file
|
||||
will be read if gzread is called until it returns less than the requested
|
||||
len.
|
||||
to read, looking for another gzip stream. Any number of gzip streams may be
|
||||
concatenated in the input file, and will all be decompressed by gzread().
|
||||
If something other than a gzip stream is encountered after a gzip stream,
|
||||
that remaining trailing garbage is ignored (and no error is returned).
|
||||
|
||||
gzread can be used to read a gzip file that is being concurrently written.
|
||||
Upon reaching the end of the input, gzread will return with the available
|
||||
data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
|
||||
gzclearerr can be used to clear the end of file indicator in order to permit
|
||||
gzread to be tried again. Z_OK indicates that a gzip stream was completed
|
||||
on the last gzread. Z_BUF_ERROR indicates that the input file ended in the
|
||||
middle of a gzip stream. Note that gzread does not return -1 in the event
|
||||
of an incomplete gzip stream. This error is deferred until gzclose(), which
|
||||
will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
|
||||
stream. Alternatively, gzerror can be used before gzclose to detect this
|
||||
case.
|
||||
|
||||
gzread returns the number of uncompressed bytes actually read, less than
|
||||
len for end of file, or -1 for error.
|
||||
|
@ -1256,7 +1346,7 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
|
|||
error.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
|
||||
ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
|
||||
/*
|
||||
Converts, formats, and writes the arguments to the compressed file under
|
||||
control of the format string, as in fprintf. gzprintf returns the number of
|
||||
|
@ -1301,7 +1391,10 @@ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
|
|||
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
|
||||
/*
|
||||
Reads one byte from the compressed file. gzgetc returns this byte or -1
|
||||
in case of end of file or error.
|
||||
in case of end of file or error. This is implemented as a macro for speed.
|
||||
As such, it does not do all of the checking the other functions do. I.e.
|
||||
it does not check to see if file is NULL, nor whether the structure file
|
||||
points to has been clobbered or not.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
|
||||
|
@ -1397,9 +1490,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
|
|||
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
|
||||
/*
|
||||
Returns true (1) if file is being copied directly while reading, or false
|
||||
(0) if file is a gzip stream being decompressed. This state can change from
|
||||
false to true while reading the input file if the end of a gzip stream is
|
||||
reached, but is followed by data that is not another gzip stream.
|
||||
(0) if file is a gzip stream being decompressed.
|
||||
|
||||
If the input file is empty, gzdirect() will return true, since the input
|
||||
does not contain a gzip stream.
|
||||
|
@ -1408,6 +1499,13 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
|
|||
cause buffers to be allocated to allow reading the file to determine if it
|
||||
is a gzip file. Therefore if gzbuffer() is used, it should be called before
|
||||
gzdirect().
|
||||
|
||||
When writing, gzdirect() returns true (1) if transparent writing was
|
||||
requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
|
||||
gzdirect() is not needed when writing. Transparent writing must be
|
||||
explicitly requested, so the application already knows the answer. When
|
||||
linking statically, using gzdirect() will include all of the zlib code for
|
||||
gzip file reading and decompression, which may not be desired.)
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
|
||||
|
@ -1419,7 +1517,8 @@ ZEXTERN int ZEXPORT gzclose OF((gzFile file));
|
|||
must not be called more than once on the same allocation.
|
||||
|
||||
gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
|
||||
file operation error, or Z_OK on success.
|
||||
file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
|
||||
last read ended in the middle of a gzip stream, or Z_OK on success.
|
||||
*/
|
||||
|
||||
ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
|
||||
|
@ -1457,6 +1556,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
|
|||
file that is being written concurrently.
|
||||
*/
|
||||
|
||||
#endif /* !Z_SOLO */
|
||||
|
||||
/* checksum functions */
|
||||
|
||||
|
@ -1492,16 +1592,17 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
|
|||
Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
|
||||
and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
|
||||
each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
|
||||
seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
|
||||
seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
|
||||
that the z_off_t type (like off_t) is a signed integer. If len2 is
|
||||
negative, the result has no meaning or utility.
|
||||
*/
|
||||
|
||||
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
|
||||
/*
|
||||
Update a running CRC-32 with the bytes buf[0..len-1] and return the
|
||||
updated CRC-32. If buf is Z_NULL, this function returns the required
|
||||
initial value for the for the crc. Pre- and post-conditioning (one's
|
||||
complement) is performed within this function so it shouldn't be done by the
|
||||
application.
|
||||
initial value for the crc. Pre- and post-conditioning (one's complement) is
|
||||
performed within this function so it shouldn't be done by the application.
|
||||
|
||||
Usage example:
|
||||
|
||||
|
@ -1544,17 +1645,42 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
|
|||
const char *version,
|
||||
int stream_size));
|
||||
#define deflateInit(strm, level) \
|
||||
deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
|
||||
deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
|
||||
#define inflateInit(strm) \
|
||||
inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
|
||||
inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
|
||||
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
|
||||
deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
|
||||
(strategy), ZLIB_VERSION, sizeof(z_stream))
|
||||
(strategy), ZLIB_VERSION, (int)sizeof(z_stream))
|
||||
#define inflateInit2(strm, windowBits) \
|
||||
inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
|
||||
inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
|
||||
(int)sizeof(z_stream))
|
||||
#define inflateBackInit(strm, windowBits, window) \
|
||||
inflateBackInit_((strm), (windowBits), (window), \
|
||||
ZLIB_VERSION, sizeof(z_stream))
|
||||
ZLIB_VERSION, (int)sizeof(z_stream))
|
||||
|
||||
#ifndef Z_SOLO
|
||||
|
||||
/* gzgetc() macro and its supporting function and exposed data structure. Note
|
||||
* that the real internal state is much larger than the exposed structure.
|
||||
* This abbreviated structure exposes just enough for the gzgetc() macro. The
|
||||
* user should not mess with these exposed elements, since their names or
|
||||
* behavior could change in the future, perhaps even capriciously. They can
|
||||
* only be used by the gzgetc() macro. You have been warned.
|
||||
*/
|
||||
struct gzFile_s {
|
||||
unsigned have;
|
||||
unsigned char *next;
|
||||
z_off64_t pos;
|
||||
};
|
||||
ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
|
||||
#ifdef Z_PREFIX_SET
|
||||
# undef z_gzgetc
|
||||
# define z_gzgetc(g) \
|
||||
((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
|
||||
#else
|
||||
# define gzgetc(g) \
|
||||
((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
|
||||
#endif
|
||||
|
||||
/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
|
||||
* change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
|
||||
|
@ -1562,7 +1688,7 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
|
|||
* functions are changed to 64 bits) -- in case these are set on systems
|
||||
* without large file support, _LFS64_LARGEFILE must also be true
|
||||
*/
|
||||
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
|
||||
#ifdef Z_LARGE64
|
||||
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
|
||||
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
|
||||
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
|
||||
|
@ -1571,14 +1697,23 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
|
|||
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
|
||||
#endif
|
||||
|
||||
#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0
|
||||
# define gzopen gzopen64
|
||||
# define gzseek gzseek64
|
||||
# define gztell gztell64
|
||||
# define gzoffset gzoffset64
|
||||
# define adler32_combine adler32_combine64
|
||||
# define crc32_combine crc32_combine64
|
||||
# ifdef _LARGEFILE64_SOURCE
|
||||
#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
|
||||
# ifdef Z_PREFIX_SET
|
||||
# define z_gzopen z_gzopen64
|
||||
# define z_gzseek z_gzseek64
|
||||
# define z_gztell z_gztell64
|
||||
# define z_gzoffset z_gzoffset64
|
||||
# define z_adler32_combine z_adler32_combine64
|
||||
# define z_crc32_combine z_crc32_combine64
|
||||
# else
|
||||
# define gzopen gzopen64
|
||||
# define gzseek gzseek64
|
||||
# define gztell gztell64
|
||||
# define gzoffset gzoffset64
|
||||
# define adler32_combine adler32_combine64
|
||||
# define crc32_combine crc32_combine64
|
||||
# endif
|
||||
# ifndef Z_LARGE64
|
||||
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
|
||||
ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
|
||||
ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
|
||||
|
@ -1595,6 +1730,13 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
|
|||
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
|
||||
#endif
|
||||
|
||||
#else /* Z_SOLO */
|
||||
|
||||
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
|
||||
|
||||
#endif /* !Z_SOLO */
|
||||
|
||||
/* hack for buggy compilers */
|
||||
#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
|
||||
struct internal_state {int dummy;};
|
||||
|
@ -1603,8 +1745,21 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
|
|||
/* undocumented functions */
|
||||
ZEXTERN const char * ZEXPORT zError OF((int));
|
||||
ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp));
|
||||
ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
|
||||
ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void));
|
||||
ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int));
|
||||
ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
|
||||
ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
|
||||
#if defined(_WIN32) && !defined(Z_SOLO)
|
||||
ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
|
||||
const char *mode));
|
||||
#endif
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
# ifndef Z_SOLO
|
||||
ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file,
|
||||
const char *format,
|
||||
va_list va));
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
||||
libdir=@INSTALL_LIB_DIR@
|
||||
sharedlibdir=@INSTALL_LIB_DIR@
|
||||
includedir=@INSTALL_INC_DIR@
|
||||
|
||||
Name: zlib
|
||||
Description: zlib compression library
|
||||
Version: @VERSION@
|
||||
|
||||
Requires:
|
||||
Libs: -L${libdir} -L${sharedlibdir} -lz
|
||||
Cflags: -I${includedir}
|
|
@ -1,17 +1,20 @@
|
|||
/* zutil.c -- target dependent utility functions for the compression library
|
||||
* Copyright (C) 1995-2005, 2010 Jean-loup Gailly.
|
||||
* Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zutil.h"
|
||||
#ifndef Z_SOLO
|
||||
# include "gzguts.h"
|
||||
#endif
|
||||
|
||||
#ifndef NO_DUMMY_DECL
|
||||
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||
#endif
|
||||
|
||||
const char * const z_errmsg[10] = {
|
||||
z_const char * const z_errmsg[10] = {
|
||||
"need dictionary", /* Z_NEED_DICT 2 */
|
||||
"stream end", /* Z_STREAM_END 1 */
|
||||
"", /* Z_OK 0 */
|
||||
|
@ -85,27 +88,27 @@ uLong ZEXPORT zlibCompileFlags()
|
|||
#ifdef FASTEST
|
||||
flags += 1L << 21;
|
||||
#endif
|
||||
#ifdef STDC
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
# ifdef NO_vsnprintf
|
||||
flags += 1L << 25;
|
||||
flags += 1L << 25;
|
||||
# ifdef HAS_vsprintf_void
|
||||
flags += 1L << 26;
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_vsnprintf_void
|
||||
flags += 1L << 26;
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
flags += 1L << 24;
|
||||
flags += 1L << 24;
|
||||
# ifdef NO_snprintf
|
||||
flags += 1L << 25;
|
||||
flags += 1L << 25;
|
||||
# ifdef HAS_sprintf_void
|
||||
flags += 1L << 26;
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_snprintf_void
|
||||
flags += 1L << 26;
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
@ -181,6 +184,7 @@ void ZLIB_INTERNAL zmemzero(dest, len)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef Z_SOLO
|
||||
|
||||
#ifdef SYS16BIT
|
||||
|
||||
|
@ -316,3 +320,5 @@ void ZLIB_INTERNAL zcfree (opaque, ptr)
|
|||
}
|
||||
|
||||
#endif /* MY_ZCALLOC */
|
||||
|
||||
#endif /* !Z_SOLO */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* zutil.h -- internal interface and configuration of the compression library
|
||||
* Copyright (C) 1995-2010 Jean-loup Gailly.
|
||||
* Copyright (C) 1995-2013 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
|||
#ifndef ZUTIL_H
|
||||
#define ZUTIL_H
|
||||
|
||||
#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
# define ZLIB_INTERNAL
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef STDC
|
||||
#if defined(STDC) && !defined(Z_SOLO)
|
||||
# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
|
||||
# include <stddef.h>
|
||||
# endif
|
||||
|
@ -29,6 +29,10 @@
|
|||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef Z_SOLO
|
||||
typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
|
@ -40,13 +44,13 @@ typedef unsigned short ush;
|
|||
typedef ush FAR ushf;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
/* (size given to avoid silly warnings with Visual C++) */
|
||||
|
||||
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
|
||||
|
||||
#define ERR_RETURN(strm,err) \
|
||||
return (strm->msg = (char*)ERR_MSG(err), (err))
|
||||
return (strm->msg = ERR_MSG(err), (err))
|
||||
/* To be used only when the state is known to be valid */
|
||||
|
||||
/* common constants */
|
||||
|
@ -78,16 +82,18 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
|
||||
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
|
||||
# define OS_CODE 0x00
|
||||
# if defined(__TURBOC__) || defined(__BORLANDC__)
|
||||
# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
|
||||
/* Allow compilation with ANSI keywords only enabled */
|
||||
void _Cdecl farfree( void *block );
|
||||
void *_Cdecl farmalloc( unsigned long nbytes );
|
||||
# else
|
||||
# include <alloc.h>
|
||||
# ifndef Z_SOLO
|
||||
# if defined(__TURBOC__) || defined(__BORLANDC__)
|
||||
# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
|
||||
/* Allow compilation with ANSI keywords only enabled */
|
||||
void _Cdecl farfree( void *block );
|
||||
void *_Cdecl farmalloc( unsigned long nbytes );
|
||||
# else
|
||||
# include <alloc.h>
|
||||
# endif
|
||||
# else /* MSC or DJGPP */
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
# else /* MSC or DJGPP */
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -107,18 +113,20 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
|
||||
#ifdef OS2
|
||||
# define OS_CODE 0x06
|
||||
# ifdef M_I86
|
||||
# if defined(M_I86) && !defined(Z_SOLO)
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MACOS) || defined(TARGET_OS_MAC)
|
||||
# define OS_CODE 0x07
|
||||
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
|
||||
# include <unix.h> /* for fdopen */
|
||||
# else
|
||||
# ifndef fdopen
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# ifndef Z_SOLO
|
||||
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
|
||||
# include <unix.h> /* for fdopen */
|
||||
# else
|
||||
# ifndef fdopen
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
@ -153,14 +161,15 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
#if defined(__BORLANDC__) && !defined(MSDOS)
|
||||
#pragma warn -8004
|
||||
#pragma warn -8008
|
||||
#pragma warn -8066
|
||||
#endif
|
||||
|
||||
/* provide prototypes for these when building zlib without LFS */
|
||||
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
|
||||
#if !defined(_WIN32) && \
|
||||
(!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
|
||||
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
|
||||
#endif
|
||||
|
@ -177,42 +186,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
|
||||
/* functions */
|
||||
|
||||
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__CYGWIN__)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
# ifdef MSDOS
|
||||
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
|
||||
but for now we just assume it doesn't. */
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __TURBOC__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef WIN32
|
||||
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
|
||||
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
|
||||
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __SASC
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
#ifdef VMS
|
||||
# define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
#if defined(pyr)
|
||||
#if defined(pyr) || defined(Z_SOLO)
|
||||
# define NO_MEMCPY
|
||||
#endif
|
||||
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
|
||||
|
@ -261,14 +235,19 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
|||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
|
||||
voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
|
||||
unsigned size));
|
||||
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
|
||||
#ifndef Z_SOLO
|
||||
voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
|
||||
unsigned size));
|
||||
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
|
||||
#endif
|
||||
|
||||
#define ZALLOC(strm, items, size) \
|
||||
(*((strm)->zalloc))((strm)->opaque, (items), (size))
|
||||
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
|
||||
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
|
||||
|
||||
/* Reverse the bytes in a 32-bit value */
|
||||
#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
|
||||
(((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
|
||||
|
||||
#endif /* ZUTIL_H */
|
||||
|
|
|
@ -191,7 +191,7 @@ can use a comfortable installer from <a href="http://www.boost-consulting.com/pr
|
|||
http://www.boost-consulting.com/products/free</a>. Choose the appropriate version of boost for your runtime of choice.
|
||||
|
||||
<b>If you don't want to use boost</b>, you can build against our <i>"Boost-Workaround"</i>. It consists of very small
|
||||
implementations of the various boost utility classes used. However, you'll loose functionality (e.g. threading) by doing this.
|
||||
implementations of the various boost utility classes used. However, you'll lose functionality (e.g. threading) by doing this.
|
||||
So, if you can use boost, you should use boost. Otherwise, See the @link use_noboost NoBoost-Section @endlink
|
||||
later on this page for the details of the workaround.
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
# pragma pack(push,1)
|
||||
# define PACK_STRUCT
|
||||
#elif defined( __GNUC__ )
|
||||
# define PACK_STRUCT __attribute__((packed))
|
||||
# define PACK_STRUCT __attribute__((gcc_struct, __packed__))
|
||||
#else
|
||||
# error Compiler not supported
|
||||
#endif
|
||||
|
|
|
@ -168,7 +168,9 @@ public:
|
|||
* @return the exported data or NULL in case of error.
|
||||
* @note If the Exporter instance did already hold a blob from
|
||||
* a previous call to #ExportToBlob, it will be disposed.
|
||||
* Any IO handlers set via #SetIOHandler are ignored here.*/
|
||||
* Any IO handlers set via #SetIOHandler are ignored here.
|
||||
* @note Use aiCopyScene() to get a modifiable copy of a previously
|
||||
* imported scene. */
|
||||
const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u );
|
||||
inline const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u );
|
||||
|
||||
|
@ -196,8 +198,16 @@ public:
|
|||
* redundant as exporters would apply them anyhow. A good example
|
||||
* is triangulation - whilst you can enforce it by specifying
|
||||
* the #aiProcess_Triangulate flag, most export formats support only
|
||||
* triangulate data so they would run the step even if it wasn't requested.
|
||||
* @return AI_SUCCESS if everything was fine. */
|
||||
* triangulate data so they would run the step even if it wasn't requested.
|
||||
*
|
||||
* If assimp detects that the input scene was directly taken from the importer side of
|
||||
* the library (i.e. not copied using aiCopyScene and potetially modified afterwards),
|
||||
* any postprocessing steps already applied to the scene will not be applied again, unless
|
||||
* they show non-idempotent behaviour (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
|
||||
* #aiProcess_FlipWindingOrder).
|
||||
* @return AI_SUCCESS if everything was fine.
|
||||
* @note Use aiCopyScene() to get a modifiable copy of a previously
|
||||
* imported scene.*/
|
||||
aiReturn Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing = 0u);
|
||||
inline aiReturn Export( const aiScene* pScene, const std::string& pFormatId, const std::string& pPath, unsigned int pPreprocessing = 0u);
|
||||
|
||||
|
|
|
@ -95,16 +95,22 @@ ASSIMP_API const C_STRUCT aiExportFormatDesc* aiGetExportFormatDescription( size
|
|||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
/** Create a modifyable copy of a scene.
|
||||
/** Create a modifiable copy of a scene.
|
||||
* This is useful to import files via Assimp, change their topology and
|
||||
* export them again. Since the scene returned by the various importer functions
|
||||
* is const, a modifyable copy is needed.
|
||||
* is const, a modifiable copy is needed.
|
||||
* @param pIn Valid scene to be copied
|
||||
* @param pOut Receives a modifyable copy of the scene.
|
||||
* @param pOut Receives a modifyable copy of the scene. Use aiFreeScene() to
|
||||
* delete it again.
|
||||
*/
|
||||
ASSIMP_API void aiCopyScene(const C_STRUCT aiScene* pIn,
|
||||
C_STRUCT aiScene** pOut);
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
/** Frees a scene copy created using aiCopyScene() */
|
||||
ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn);
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
/** Exports the given scene to a chosen file format and writes the result file(s) to disk.
|
||||
* @param pScene The scene to export. Stays in possession of the caller, is not changed by the function.
|
||||
|
@ -137,7 +143,15 @@ ASSIMP_API void aiCopyScene(const C_STRUCT aiScene* pIn,
|
|||
* is triangulation - whilst you can enforce it by specifying
|
||||
* the #aiProcess_Triangulate flag, most export formats support only
|
||||
* triangulate data so they would run the step anyway.
|
||||
*
|
||||
* If assimp detects that the input scene was directly taken from the importer side of
|
||||
* the library (i.e. not copied using aiCopyScene and potetially modified afterwards),
|
||||
* any postprocessing steps already applied to the scene will not be applied again, unless
|
||||
* they show non-idempotent behaviour (#aiProcess_MakeLeftHanded, #aiProcess_FlipUVs and
|
||||
* #aiProcess_FlipWindingOrder).
|
||||
* @return a status code indicating the result of the export
|
||||
* @note Use aiCopyScene() to get a modifiable copy of a previously
|
||||
* imported scene.
|
||||
*/
|
||||
ASSIMP_API aiReturn aiExportScene( const C_STRUCT aiScene* pScene,
|
||||
const char* pFormatId,
|
||||
|
@ -157,6 +171,8 @@ ASSIMP_API aiReturn aiExportScene( const C_STRUCT aiScene* pScene,
|
|||
* @param pPreprocessing Please see the documentation for #aiExportScene
|
||||
* @return a status code indicating the result of the export
|
||||
* @note Include <aiFileIO.h> for the definition of #aiFileIO.
|
||||
* @note Use aiCopyScene() to get a modifiable copy of a previously
|
||||
* imported scene.
|
||||
*/
|
||||
ASSIMP_API aiReturn aiExportSceneEx( const C_STRUCT aiScene* pScene,
|
||||
const char* pFormatId,
|
||||
|
|
|
@ -841,4 +841,6 @@ enum aiComponent
|
|||
*/
|
||||
#define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION"
|
||||
|
||||
#endif // !! AI_CONFIG_H_INC
|
||||
#define AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION "IMPORT_COLLADA_IGNORE_UP_DIRECTION"
|
||||
|
||||
#endif // !! AI_CONFIG_H_INC
|
||||
|
|
|
@ -162,6 +162,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
# define AI_FORCE_INLINE inline
|
||||
#endif // (defined _MSC_VER)
|
||||
|
||||
#ifdef __clang__
|
||||
# define AI_WONT_RETURN_SUFFIX __attribute__((analyzer_noreturn))
|
||||
#else
|
||||
# define AI_WONT_RETURN_SUFFIX
|
||||
#endif // (defined __clang__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* No explicit 'struct' and 'enum' tags for C++, this keeps showing up
|
||||
* in doxydocs.
|
||||
|
|
|
@ -691,6 +691,12 @@ public:
|
|||
aiReturn Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx, Type* pOut, unsigned int* pMax) const;
|
||||
|
||||
aiReturn Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx, int* pOut, unsigned int* pMax) const;
|
||||
|
||||
aiReturn Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx, float* pOut, unsigned int* pMax) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** @brief Retrieve a Type value with a specific key
|
||||
* from the material
|
||||
|
@ -705,6 +711,25 @@ public:
|
|||
aiReturn Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx,Type& pOut) const;
|
||||
|
||||
|
||||
aiReturn Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx, int& pOut) const;
|
||||
|
||||
aiReturn Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx, float& pOut) const;
|
||||
|
||||
aiReturn Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx, aiString& pOut) const;
|
||||
|
||||
aiReturn Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx, aiColor3D& pOut) const;
|
||||
|
||||
aiReturn Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx, aiColor4D& pOut) const;
|
||||
|
||||
aiReturn Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx, aiUVTransform& pOut) const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Get the number of textures for a particular texture type.
|
||||
* @param type Texture type to check for
|
||||
|
@ -797,6 +822,42 @@ public:
|
|||
unsigned int type = 0,
|
||||
unsigned int index = 0);
|
||||
|
||||
aiReturn AddProperty (const aiVector3D* pInput,
|
||||
unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type = 0,
|
||||
unsigned int index = 0);
|
||||
|
||||
aiReturn AddProperty (const aiColor3D* pInput,
|
||||
unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type = 0,
|
||||
unsigned int index = 0);
|
||||
|
||||
aiReturn AddProperty (const aiColor4D* pInput,
|
||||
unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type = 0,
|
||||
unsigned int index = 0);
|
||||
|
||||
aiReturn AddProperty (const int* pInput,
|
||||
unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type = 0,
|
||||
unsigned int index = 0);
|
||||
|
||||
aiReturn AddProperty (const float* pInput,
|
||||
unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type = 0,
|
||||
unsigned int index = 0);
|
||||
|
||||
aiReturn AddProperty (const aiUVTransform* pInput,
|
||||
unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type = 0,
|
||||
unsigned int index = 0);
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
/** @brief Remove a given key from the list.
|
||||
*
|
||||
|
|
|
@ -89,7 +89,7 @@ inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
|||
}
|
||||
|
||||
iNum = std::min((size_t)iNum,prop->mDataLength / sizeof(Type));
|
||||
memcpy(pOut,prop->mData,iNum * sizeof(Type));
|
||||
::memcpy(pOut,prop->mData,iNum * sizeof(Type));
|
||||
if (pMax) {
|
||||
*pMax = iNum;
|
||||
}
|
||||
|
@ -115,51 +115,45 @@ inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
|||
return AI_FAILURE;
|
||||
}
|
||||
|
||||
memcpy(&pOut,prop->mData,sizeof(Type));
|
||||
::memcpy(&pOut,prop->mData,sizeof(Type));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
template <>
|
||||
inline aiReturn aiMaterial::Get<float>(const char* pKey,unsigned int type,
|
||||
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx,float* pOut,
|
||||
unsigned int* pMax) const
|
||||
{
|
||||
return ::aiGetMaterialFloatArray(this,pKey,type,idx,pOut,pMax);
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
template <>
|
||||
inline aiReturn aiMaterial::Get<int>(const char* pKey,unsigned int type,
|
||||
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx,int* pOut,
|
||||
unsigned int* pMax) const
|
||||
{
|
||||
return ::aiGetMaterialIntegerArray(this,pKey,type,idx,pOut,pMax);
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
template <>
|
||||
inline aiReturn aiMaterial::Get<float>(const char* pKey,unsigned int type,
|
||||
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx,float& pOut) const
|
||||
{
|
||||
return aiGetMaterialFloat(this,pKey,type,idx,&pOut);
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
template <>
|
||||
inline aiReturn aiMaterial::Get<int>(const char* pKey,unsigned int type,
|
||||
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx,int& pOut) const
|
||||
{
|
||||
return aiGetMaterialInteger(this,pKey,type,idx,&pOut);
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
template <>
|
||||
inline aiReturn aiMaterial::Get<aiColor4D>(const char* pKey,unsigned int type,
|
||||
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx,aiColor4D& pOut) const
|
||||
{
|
||||
return aiGetMaterialColor(this,pKey,type,idx,&pOut);
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
template <>
|
||||
inline aiReturn aiMaterial::Get<aiColor3D>(const char* pKey,unsigned int type,
|
||||
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx,aiColor3D& pOut) const
|
||||
{
|
||||
aiColor4D c;
|
||||
|
@ -168,8 +162,7 @@ inline aiReturn aiMaterial::Get<aiColor3D>(const char* pKey,unsigned int type,
|
|||
return ret;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
template <>
|
||||
inline aiReturn aiMaterial::Get<aiString>(const char* pKey,unsigned int type,
|
||||
inline aiReturn aiMaterial::Get(const char* pKey,unsigned int type,
|
||||
unsigned int idx,aiString& pOut) const
|
||||
{
|
||||
return aiGetMaterialString(this,pKey,type,idx,&pOut);
|
||||
|
@ -189,9 +182,88 @@ aiReturn aiMaterial::AddProperty (const TYPE* pInput,
|
|||
pKey,type,index,aiPTI_Buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
inline aiReturn aiMaterial::AddProperty(const float* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
unsigned int index)
|
||||
{
|
||||
return AddBinaryProperty((const void*)pInput,
|
||||
pNumValues * sizeof(float),
|
||||
pKey,type,index,aiPTI_Float);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
inline aiReturn aiMaterial::AddProperty(const aiUVTransform* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
unsigned int index)
|
||||
{
|
||||
return AddBinaryProperty((const void*)pInput,
|
||||
pNumValues * sizeof(aiUVTransform),
|
||||
pKey,type,index,aiPTI_Float);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
inline aiReturn aiMaterial::AddProperty(const aiColor4D* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
unsigned int index)
|
||||
{
|
||||
return AddBinaryProperty((const void*)pInput,
|
||||
pNumValues * sizeof(aiColor4D),
|
||||
pKey,type,index,aiPTI_Float);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
inline aiReturn aiMaterial::AddProperty(const aiColor3D* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
unsigned int index)
|
||||
{
|
||||
return AddBinaryProperty((const void*)pInput,
|
||||
pNumValues * sizeof(aiColor3D),
|
||||
pKey,type,index,aiPTI_Float);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
inline aiReturn aiMaterial::AddProperty(const aiVector3D* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
unsigned int index)
|
||||
{
|
||||
return AddBinaryProperty((const void*)pInput,
|
||||
pNumValues * sizeof(aiVector3D),
|
||||
pKey,type,index,aiPTI_Float);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
inline aiReturn aiMaterial::AddProperty(const int* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
unsigned int index)
|
||||
{
|
||||
return AddBinaryProperty((const void*)pInput,
|
||||
pNumValues * sizeof(int),
|
||||
pKey,type,index,aiPTI_Integer);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// The template specializations below are for backwards compatibility.
|
||||
// The recommended way to add material properties is using the non-template
|
||||
// overloads.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
template<>
|
||||
inline aiReturn aiMaterial::AddProperty<float> (const float* pInput,
|
||||
inline aiReturn aiMaterial::AddProperty<float>(const float* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
|
@ -204,7 +276,7 @@ inline aiReturn aiMaterial::AddProperty<float> (const float* pInput,
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
template<>
|
||||
inline aiReturn aiMaterial::AddProperty<aiUVTransform> (const aiUVTransform* pInput,
|
||||
inline aiReturn aiMaterial::AddProperty<aiUVTransform>(const aiUVTransform* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
|
@ -217,7 +289,7 @@ inline aiReturn aiMaterial::AddProperty<aiUVTransform> (const aiUVTransform* pIn
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
template<>
|
||||
inline aiReturn aiMaterial::AddProperty<aiColor4D> (const aiColor4D* pInput,
|
||||
inline aiReturn aiMaterial::AddProperty<aiColor4D>(const aiColor4D* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
|
@ -230,7 +302,7 @@ inline aiReturn aiMaterial::AddProperty<aiColor4D> (const aiColor4D* pInput,
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
template<>
|
||||
inline aiReturn aiMaterial::AddProperty<aiColor3D> (const aiColor3D* pInput,
|
||||
inline aiReturn aiMaterial::AddProperty<aiColor3D>(const aiColor3D* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
|
@ -243,7 +315,7 @@ inline aiReturn aiMaterial::AddProperty<aiColor3D> (const aiColor3D* pInput,
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
template<>
|
||||
inline aiReturn aiMaterial::AddProperty<aiVector3D> (const aiVector3D* pInput,
|
||||
inline aiReturn aiMaterial::AddProperty<aiVector3D>(const aiVector3D* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
|
@ -256,7 +328,7 @@ inline aiReturn aiMaterial::AddProperty<aiVector3D> (const aiVector3D* pInput,
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
template<>
|
||||
inline aiReturn aiMaterial::AddProperty<int> (const int* pInput,
|
||||
inline aiReturn aiMaterial::AddProperty<int>(const int* pInput,
|
||||
const unsigned int pNumValues,
|
||||
const char* pKey,
|
||||
unsigned int type,
|
||||
|
|
|
@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <memory.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
// Our compile configuration
|
||||
|
|
|
@ -57,18 +57,33 @@ def make_tuple(ai_obj, type = None):
|
|||
|
||||
return res
|
||||
|
||||
# It is faster and more correct to have an init function for each assimp class
|
||||
def _init_face(aiFace):
|
||||
aiFace.indices = [aiFace.mIndices[i] for i in range(aiFace.mNumIndices)]
|
||||
|
||||
assimp_struct_inits = \
|
||||
{ structs.Face : _init_face }
|
||||
|
||||
def call_init(obj, caller = None):
|
||||
# init children
|
||||
if helper.hasattr_silent(obj, '_init'):
|
||||
obj._init(parent = caller)
|
||||
|
||||
# pointers
|
||||
elif helper.hasattr_silent(obj, 'contents'):
|
||||
if helper.hasattr_silent(obj.contents, '_init'):
|
||||
obj.contents._init(target = obj, parent = caller)
|
||||
|
||||
|
||||
if helper.hasattr_silent(obj,'contents'): #pointer
|
||||
_init(obj.contents, obj, caller)
|
||||
else:
|
||||
_init(obj,parent=caller)
|
||||
|
||||
def _is_init_type(obj):
|
||||
if helper.hasattr_silent(obj,'contents'): #pointer
|
||||
return _is_init_type(obj[0])
|
||||
# null-pointer case that arises when we reach a mesh attribute
|
||||
# like mBitangents which use mNumVertices rather than mNumBitangents
|
||||
# so it breaks the 'is iterable' check.
|
||||
# Basically:
|
||||
# FIXME!
|
||||
elif not bool(obj):
|
||||
return False
|
||||
tname = obj.__class__.__name__
|
||||
return not (tname[:2] == 'c_' or tname == 'Structure' \
|
||||
or tname == 'POINTER') and not isinstance(obj,int)
|
||||
|
||||
def _init(self, target = None, parent = None):
|
||||
"""
|
||||
Custom initialize() for C structs, adds safely accessable member functionality.
|
||||
|
@ -76,29 +91,35 @@ def _init(self, target = None, parent = None):
|
|||
:param target: set the object which receive the added methods. Useful when manipulating
|
||||
pointers, to skip the intermediate 'contents' deferencing.
|
||||
"""
|
||||
if helper.hasattr_silent(self, '_is_init'):
|
||||
return self
|
||||
self._is_init = True
|
||||
|
||||
if not target:
|
||||
target = self
|
||||
|
||||
for m in dir(self):
|
||||
|
||||
name = m[1:].lower()
|
||||
|
||||
dirself = dir(self)
|
||||
for m in dirself:
|
||||
|
||||
if m.startswith("_"):
|
||||
continue
|
||||
|
||||
obj = getattr(self, m)
|
||||
|
||||
if m.startswith('mNum'):
|
||||
if 'm' + m[4:] in dir(self):
|
||||
if 'm' + m[4:] in dirself:
|
||||
continue # will be processed later on
|
||||
else:
|
||||
name = m[1:].lower()
|
||||
|
||||
obj = getattr(self, m)
|
||||
setattr(target, name, obj)
|
||||
continue
|
||||
|
||||
if m == 'mName':
|
||||
obj = self.mName
|
||||
target.name = str(obj.data.decode("utf-8"))
|
||||
target.__class__.__repr__ = lambda x: str(x.__class__) + "(" + x.name + ")"
|
||||
target.__class__.__str__ = lambda x: x.name
|
||||
continue
|
||||
|
||||
name = m[1:].lower()
|
||||
|
||||
obj = getattr(self, m)
|
||||
|
||||
# Create tuples
|
||||
if isinstance(obj, assimp_structs_as_tuple):
|
||||
|
@ -106,14 +127,6 @@ def _init(self, target = None, parent = None):
|
|||
logger.debug(str(self) + ": Added array " + str(getattr(target, name)) + " as self." + name.lower())
|
||||
continue
|
||||
|
||||
|
||||
if isinstance(obj, structs.String):
|
||||
setattr(target, 'name', obj.data.decode("utf-8"))
|
||||
setattr(target.__class__, '__repr__', lambda x: str(x.__class__) + "(" + x.name + ")")
|
||||
setattr(target.__class__, '__str__', lambda x: x.name)
|
||||
continue
|
||||
|
||||
|
||||
if m.startswith('m'):
|
||||
|
||||
if name == "parent":
|
||||
|
@ -150,8 +163,15 @@ def _init(self, target = None, parent = None):
|
|||
logger.debug(str(self) + ": Added list of " + str(obj) + " " + name + " as self." + name + " (type: " + str(type(obj)) + ")")
|
||||
|
||||
# initialize array elements
|
||||
for e in getattr(target, name):
|
||||
call_init(e, caller = target)
|
||||
try:
|
||||
init = assimp_struct_inits[type(obj[0])]
|
||||
except KeyError:
|
||||
if _is_init_type(obj[0]):
|
||||
for e in getattr(target, name):
|
||||
call_init(e, target)
|
||||
else:
|
||||
for e in getattr(target, name):
|
||||
init(e)
|
||||
|
||||
|
||||
except IndexError:
|
||||
|
@ -174,8 +194,9 @@ def _init(self, target = None, parent = None):
|
|||
|
||||
setattr(target, name, obj)
|
||||
logger.debug("Added " + name + " as self." + name + " (type: " + str(type(obj)) + ")")
|
||||
|
||||
call_init(obj, caller = target)
|
||||
|
||||
if _is_init_type(obj):
|
||||
call_init(obj, target)
|
||||
|
||||
|
||||
|
||||
|
@ -189,16 +210,6 @@ def _init(self, target = None, parent = None):
|
|||
|
||||
return self
|
||||
|
||||
|
||||
"""
|
||||
Python magic to add the _init() function to all C struct classes.
|
||||
"""
|
||||
for struct in dir(structs):
|
||||
if not (struct.startswith('_') or struct.startswith('c_') or struct == "Structure" or struct == "POINTER") and not isinstance(getattr(structs, struct),int):
|
||||
|
||||
setattr(getattr(structs, struct), '_init', _init)
|
||||
|
||||
|
||||
class AssimpLib(object):
|
||||
"""
|
||||
Assimp-Singleton
|
||||
|
@ -281,7 +292,7 @@ def load(filename, processing=0):
|
|||
#Uhhh, something went wrong!
|
||||
raise AssimpError("could not import file: %s" % filename)
|
||||
|
||||
scene = model.contents._init()
|
||||
scene = _init(model.contents)
|
||||
|
||||
recur_pythonize(scene.rootnode, scene)
|
||||
|
||||
|
@ -313,7 +324,7 @@ def _finalize_mesh(mesh, target):
|
|||
data = numpy.array([make_tuple(getattr(mesh, name)[i]) for i in range(nb_vertices)], dtype=numpy.float32)
|
||||
setattr(target, name[1:].lower(), data)
|
||||
else:
|
||||
setattr(target, name[1:].lower(), [])
|
||||
setattr(target, name[1:].lower(), numpy.array([], dtype="float32"))
|
||||
|
||||
def fillarray(name):
|
||||
mAttr = getattr(mesh, name)
|
||||
|
@ -336,6 +347,27 @@ def _finalize_mesh(mesh, target):
|
|||
faces = numpy.array([f.indices for f in target.faces], dtype=numpy.int32)
|
||||
setattr(target, 'faces', faces)
|
||||
|
||||
|
||||
class PropertyGetter(dict):
|
||||
def __getitem__(self, key):
|
||||
semantic = 0
|
||||
if isinstance(key, tuple):
|
||||
key, semantic = key
|
||||
|
||||
return dict.__getitem__(self, (key, semantic))
|
||||
|
||||
def keys(self):
|
||||
for k in dict.keys(self):
|
||||
yield k[0]
|
||||
|
||||
def __iter__(self):
|
||||
return self.keys()
|
||||
|
||||
def items(self):
|
||||
for k, v in dict.items(self):
|
||||
yield k[0], v
|
||||
|
||||
|
||||
def _get_properties(properties, length):
|
||||
"""
|
||||
Convenience Function to get the material properties as a dict
|
||||
|
@ -346,7 +378,7 @@ def _get_properties(properties, length):
|
|||
for p in [properties[i] for i in range(length)]:
|
||||
#the name
|
||||
p = p.contents
|
||||
key = str(p.mKey.data.decode("utf-8")).split('.')[1]
|
||||
key = (str(p.mKey.data.decode("utf-8")).split('.')[1], p.mSemantic)
|
||||
|
||||
#the data
|
||||
from ctypes import POINTER, cast, c_int, c_float, sizeof
|
||||
|
@ -366,7 +398,7 @@ def _get_properties(properties, length):
|
|||
|
||||
result[key] = value
|
||||
|
||||
return result
|
||||
return PropertyGetter(result)
|
||||
|
||||
def decompose_matrix(matrix):
|
||||
if not isinstance(matrix, structs.Matrix4x4):
|
||||
|
|
|
@ -30,7 +30,11 @@ if os.name=='posix':
|
|||
|
||||
elif os.name=='nt':
|
||||
ext_whitelist.append('.dll')
|
||||
|
||||
path_dirs = os.environ['PATH'].split(';')
|
||||
for dir_candidate in path_dirs:
|
||||
if 'assimp' in dir_candidate.lower():
|
||||
additional_dirs.append(dir_candidate)
|
||||
|
||||
#print(additional_dirs)
|
||||
def vec2tuple(x):
|
||||
""" Converts a VECTOR3D to a Tuple """
|
||||
|
|
|
@ -10,6 +10,7 @@ import logging
|
|||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
import pyassimp
|
||||
import pyassimp.postprocess
|
||||
|
||||
def recur_node(node,level = 0):
|
||||
print(" " + "\t" * level + "- " + str(node))
|
||||
|
@ -19,7 +20,7 @@ def recur_node(node,level = 0):
|
|||
|
||||
def main(filename=None):
|
||||
|
||||
scene = pyassimp.load(filename)
|
||||
scene = pyassimp.load(filename, pyassimp.postprocess.aiProcess_Triangulate)
|
||||
|
||||
#the model we load
|
||||
print("MODEL:" + filename)
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <OpenGL/OpenGL.h>
|
||||
#import "aiColor4D.h"
|
||||
#import "aiVector3D.h"
|
||||
#import "aiVector2D.h"
|
||||
#import "aiMatrix4x4.h"
|
||||
#import "color4.h"
|
||||
#import "vector3.h"
|
||||
#import "vector2.h"
|
||||
#import "matrix4x4.h"
|
||||
|
||||
/* workflow:
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue