mirror of
https://github.com/love2d/megasource.git
synced 2026-08-27 07:50:58 +02:00
Update PhysFS to 3.0.0.
This commit is contained in:
+1
-1
@@ -139,7 +139,7 @@ endif()
|
|||||||
|
|
||||||
|
|
||||||
set(MEGA_ZLIB_VER "1.2.8")
|
set(MEGA_ZLIB_VER "1.2.8")
|
||||||
set(MEGA_PHYSFS_VER "2.0.3")
|
set(MEGA_PHYSFS_VER "3.0.0")
|
||||||
set(MEGA_LUA51_VER "5.1.5")
|
set(MEGA_LUA51_VER "5.1.5")
|
||||||
set(MEGA_LUAJIT_VER "2.0.5")
|
set(MEGA_LUAJIT_VER "2.0.5")
|
||||||
set(MEGA_LIBOGG_VER "1.3.2")
|
set(MEGA_LIBOGG_VER "1.3.2")
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
repo: 7672c9962ce627edaaa67ff54fe4ad8f9a46dc2b
|
|
||||||
node: f94eec5e90540889a42c34a27931b8266f4af52c
|
|
||||||
branch: stable-2.0
|
|
||||||
latesttag: release-2.0.3
|
|
||||||
latesttagdistance: 1
|
|
||||||
@@ -1,411 +0,0 @@
|
|||||||
# PhysicsFS; a portable, flexible file i/o abstraction.
|
|
||||||
# Copyright (C) 2007 Ryan C. Gordon.
|
|
||||||
#
|
|
||||||
# Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
|
|
||||||
|
|
||||||
PROJECT(PhysicsFS)
|
|
||||||
SET(PHYSFS_VERSION 2.0.3)
|
|
||||||
|
|
||||||
# Increment this if/when we break backwards compatibility.
|
|
||||||
SET(PHYSFS_SOVERSION 1)
|
|
||||||
|
|
||||||
# I hate that they define "WIN32" ... we're about to move to Win64...I hope!
|
|
||||||
IF(WIN32 AND NOT WINDOWS)
|
|
||||||
SET(WINDOWS TRUE)
|
|
||||||
ENDIF(WIN32 AND NOT WINDOWS)
|
|
||||||
|
|
||||||
# Bleh, let's do it for "APPLE" too.
|
|
||||||
IF(APPLE AND NOT MACOSX)
|
|
||||||
SET(MACOSX TRUE)
|
|
||||||
ENDIF(APPLE AND NOT MACOSX)
|
|
||||||
|
|
||||||
# For now, Haiku and BeOS are the same, as far as the build system cares.
|
|
||||||
IF(HAIKU AND NOT BEOS)
|
|
||||||
SET(BEOS TRUE)
|
|
||||||
ENDIF(HAIKU AND NOT BEOS)
|
|
||||||
|
|
||||||
INCLUDE(CheckIncludeFile)
|
|
||||||
INCLUDE(CheckLibraryExists)
|
|
||||||
INCLUDE(CheckCSourceCompiles)
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(.)
|
|
||||||
#INCLUDE_DIRECTORIES(platform)
|
|
||||||
#INCLUDE_DIRECTORIES(archivers)
|
|
||||||
|
|
||||||
IF(MACOSX)
|
|
||||||
# Fallback to older OS X on PowerPC to support wider range of systems...
|
|
||||||
IF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
|
|
||||||
ADD_DEFINITIONS(-DMAC_OS_X_VERSION_MIN_REQUIRED=1020)
|
|
||||||
SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -mmacosx-version-min=10.2")
|
|
||||||
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
|
|
||||||
|
|
||||||
# Need these everywhere...
|
|
||||||
ADD_DEFINITIONS(-fno-common)
|
|
||||||
SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -framework Carbon -framework IOKit")
|
|
||||||
ENDIF(MACOSX)
|
|
||||||
|
|
||||||
# Add some gcc-specific command lines.
|
|
||||||
IF(CMAKE_COMPILER_IS_GNUCC)
|
|
||||||
# Always build with debug symbols...you can strip it later.
|
|
||||||
ADD_DEFINITIONS(-g -pipe -Werror -fsigned-char)
|
|
||||||
|
|
||||||
# Stupid BeOS generates warnings in the system headers.
|
|
||||||
IF(NOT BEOS)
|
|
||||||
ADD_DEFINITIONS(-Wall)
|
|
||||||
ENDIF(NOT BEOS)
|
|
||||||
|
|
||||||
CHECK_C_SOURCE_COMPILES("
|
|
||||||
#if ((defined(__GNUC__)) && (__GNUC__ >= 4))
|
|
||||||
int main(int argc, char **argv) { int is_gcc4 = 1; return 0; }
|
|
||||||
#else
|
|
||||||
#error This is not gcc4.
|
|
||||||
#endif
|
|
||||||
" PHYSFS_IS_GCC4)
|
|
||||||
|
|
||||||
IF(PHYSFS_IS_GCC4)
|
|
||||||
# Not supported on several operating systems at this time.
|
|
||||||
IF(NOT OS2 AND NOT SOLARIS AND NOT WINDOWS)
|
|
||||||
ADD_DEFINITIONS(-fvisibility=hidden)
|
|
||||||
ENDIF(NOT OS2 AND NOT SOLARIS AND NOT WINDOWS)
|
|
||||||
ENDIF(PHYSFS_IS_GCC4)
|
|
||||||
ENDIF(CMAKE_COMPILER_IS_GNUCC)
|
|
||||||
|
|
||||||
IF(MSVC)
|
|
||||||
# VS.NET 8.0 got really really anal about strcpy, etc, which even if we
|
|
||||||
# cleaned up our code, zlib, etc still use...so disable the warning.
|
|
||||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS=1)
|
|
||||||
ENDIF(MSVC)
|
|
||||||
|
|
||||||
# Basic chunks of source code ...
|
|
||||||
|
|
||||||
SET(ZLIB_SRCS
|
|
||||||
zlib123/adler32.c
|
|
||||||
zlib123/compress.c
|
|
||||||
zlib123/crc32.c
|
|
||||||
zlib123/deflate.c
|
|
||||||
zlib123/gzio.c
|
|
||||||
zlib123/infback.c
|
|
||||||
zlib123/inffast.c
|
|
||||||
zlib123/inflate.c
|
|
||||||
zlib123/inftrees.c
|
|
||||||
zlib123/trees.c
|
|
||||||
zlib123/uncompr.c
|
|
||||||
zlib123/zutil.c
|
|
||||||
)
|
|
||||||
|
|
||||||
SET(LZMA_SRCS
|
|
||||||
lzma/C/7zCrc.c
|
|
||||||
lzma/C/Archive/7z/7zBuffer.c
|
|
||||||
lzma/C/Archive/7z/7zDecode.c
|
|
||||||
lzma/C/Archive/7z/7zExtract.c
|
|
||||||
lzma/C/Archive/7z/7zHeader.c
|
|
||||||
lzma/C/Archive/7z/7zIn.c
|
|
||||||
lzma/C/Archive/7z/7zItem.c
|
|
||||||
lzma/C/Archive/7z/7zMethodID.c
|
|
||||||
lzma/C/Compress/Branch/BranchX86.c
|
|
||||||
lzma/C/Compress/Branch/BranchX86_2.c
|
|
||||||
lzma/C/Compress/Lzma/LzmaDecode.c
|
|
||||||
)
|
|
||||||
|
|
||||||
IF(BEOS)
|
|
||||||
# We add this explicitly, since we don't want CMake to think this
|
|
||||||
# is a C++ project unless we're on BeOS.
|
|
||||||
SET(PHYSFS_BEOS_SRCS platform/beos.cpp)
|
|
||||||
FIND_LIBRARY(BE_LIBRARY be)
|
|
||||||
FIND_LIBRARY(ROOT_LIBRARY root)
|
|
||||||
SET(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${BE_LIBRARY} ${ROOT_LIBRARY})
|
|
||||||
ENDIF(BEOS)
|
|
||||||
|
|
||||||
# Almost everything is "compiled" here, but things that don't apply to the
|
|
||||||
# build are #ifdef'd out. This is to make it easy to embed PhysicsFS into
|
|
||||||
# another project or bring up a new build system: just compile all the source
|
|
||||||
# code and #define the things you want.
|
|
||||||
SET(PHYSFS_SRCS
|
|
||||||
physfs.c
|
|
||||||
physfs_byteorder.c
|
|
||||||
physfs_unicode.c
|
|
||||||
platform/os2.c
|
|
||||||
platform/pocketpc.c
|
|
||||||
platform/posix.c
|
|
||||||
platform/unix.c
|
|
||||||
platform/macosx.c
|
|
||||||
platform/windows.c
|
|
||||||
archivers/dir.c
|
|
||||||
archivers/grp.c
|
|
||||||
archivers/hog.c
|
|
||||||
archivers/lzma.c
|
|
||||||
archivers/mvl.c
|
|
||||||
archivers/qpak.c
|
|
||||||
archivers/wad.c
|
|
||||||
archivers/zip.c
|
|
||||||
${PHYSFS_BEOS_SRCS}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# platform layers ...
|
|
||||||
|
|
||||||
IF(UNIX)
|
|
||||||
IF(BEOS)
|
|
||||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
|
||||||
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
|
|
||||||
SET(HAVE_PTHREAD_H TRUE)
|
|
||||||
ELSE(BEOS)
|
|
||||||
# !!! FIXME
|
|
||||||
# AC_DEFINE([PHYSFS_HAVE_LLSEEK], 1, [define if we have llseek])
|
|
||||||
CHECK_INCLUDE_FILE(sys/ucred.h HAVE_UCRED_H)
|
|
||||||
IF(HAVE_UCRED_H)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_HAVE_SYS_UCRED_H=1)
|
|
||||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
|
||||||
ENDIF(HAVE_UCRED_H)
|
|
||||||
|
|
||||||
CHECK_INCLUDE_FILE(mntent.h HAVE_MNTENT_H)
|
|
||||||
IF(HAVE_MNTENT_H)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_HAVE_MNTENT_H=1)
|
|
||||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
|
||||||
ENDIF(HAVE_MNTENT_H)
|
|
||||||
|
|
||||||
CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
|
|
||||||
IF(HAVE_PTHREAD_H)
|
|
||||||
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
|
|
||||||
ENDIF(HAVE_PTHREAD_H)
|
|
||||||
ENDIF(BEOS)
|
|
||||||
ENDIF(UNIX)
|
|
||||||
|
|
||||||
IF(WINDOWS)
|
|
||||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
|
||||||
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
|
|
||||||
ENDIF(WINDOWS)
|
|
||||||
|
|
||||||
IF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_NO_CDROM_SUPPORT=1)
|
|
||||||
MESSAGE(WARNING " ***")
|
|
||||||
MESSAGE(WARNING " *** There is no CD-ROM support in this build!")
|
|
||||||
MESSAGE(WARNING " *** PhysicsFS will just pretend there are no discs.")
|
|
||||||
MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
|
|
||||||
MESSAGE(WARNING " *** but is this what you REALLY wanted?")
|
|
||||||
MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
|
|
||||||
MESSAGE(WARNING " ***")
|
|
||||||
ENDIF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
|
|
||||||
|
|
||||||
IF(PHYSFS_HAVE_THREAD_SUPPORT)
|
|
||||||
ADD_DEFINITIONS(-D_REENTRANT -D_THREAD_SAFE)
|
|
||||||
ELSE(PHYSFS_HAVE_THREAD_SUPPORT)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_NO_THREAD_SUPPORT=1)
|
|
||||||
MESSAGE(WARNING " ***")
|
|
||||||
MESSAGE(WARNING " *** There is no thread support in this build!")
|
|
||||||
MESSAGE(WARNING " *** PhysicsFS will NOT be reentrant!")
|
|
||||||
MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
|
|
||||||
MESSAGE(WARNING " *** but is this what you REALLY wanted?")
|
|
||||||
MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
|
|
||||||
MESSAGE(WARNING " ***")
|
|
||||||
ENDIF(PHYSFS_HAVE_THREAD_SUPPORT)
|
|
||||||
|
|
||||||
CHECK_INCLUDE_FILE(assert.h HAVE_ASSERT_H)
|
|
||||||
IF(HAVE_ASSERT_H)
|
|
||||||
ADD_DEFINITIONS(-DHAVE_ASSERT_H=1)
|
|
||||||
ENDIF(HAVE_ASSERT_H)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Archivers ...
|
|
||||||
|
|
||||||
OPTION(PHYSFS_ARCHIVE_ZIP "Enable ZIP support" TRUE)
|
|
||||||
IF(PHYSFS_ARCHIVE_ZIP)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_ZIP=1)
|
|
||||||
SET(PHYSFS_NEED_ZLIB TRUE)
|
|
||||||
ENDIF(PHYSFS_ARCHIVE_ZIP)
|
|
||||||
|
|
||||||
OPTION(PHYSFS_ARCHIVE_7Z "Enable 7zip support" TRUE)
|
|
||||||
IF(PHYSFS_ARCHIVE_7Z)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_7Z=1)
|
|
||||||
# !!! FIXME: rename to 7z.c?
|
|
||||||
SET(PHYSFS_SRCS ${PHYSFS_SRCS} ${LZMA_SRCS})
|
|
||||||
ENDIF(PHYSFS_ARCHIVE_7Z)
|
|
||||||
|
|
||||||
OPTION(PHYSFS_ARCHIVE_GRP "Enable Build Engine GRP support" TRUE)
|
|
||||||
IF(PHYSFS_ARCHIVE_GRP)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_GRP=1)
|
|
||||||
ENDIF(PHYSFS_ARCHIVE_GRP)
|
|
||||||
|
|
||||||
OPTION(PHYSFS_ARCHIVE_WAD "Enable Doom WAD support" TRUE)
|
|
||||||
IF(PHYSFS_ARCHIVE_WAD)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_WAD=1)
|
|
||||||
ENDIF(PHYSFS_ARCHIVE_WAD)
|
|
||||||
|
|
||||||
OPTION(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" TRUE)
|
|
||||||
IF(PHYSFS_ARCHIVE_HOG)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_HOG=1)
|
|
||||||
ENDIF(PHYSFS_ARCHIVE_HOG)
|
|
||||||
|
|
||||||
OPTION(PHYSFS_ARCHIVE_MVL "Enable Descent I/II MVL support" TRUE)
|
|
||||||
IF(PHYSFS_ARCHIVE_MVL)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_MVL=1)
|
|
||||||
ENDIF(PHYSFS_ARCHIVE_MVL)
|
|
||||||
|
|
||||||
OPTION(PHYSFS_ARCHIVE_QPAK "Enable Quake I/II QPAK support" TRUE)
|
|
||||||
IF(PHYSFS_ARCHIVE_QPAK)
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_QPAK=1)
|
|
||||||
ENDIF(PHYSFS_ARCHIVE_QPAK)
|
|
||||||
|
|
||||||
|
|
||||||
# See if some archiver required zlib, and see about using system version.
|
|
||||||
|
|
||||||
IF(PHYSFS_NEED_ZLIB)
|
|
||||||
FIND_PACKAGE(ZLIB)
|
|
||||||
|
|
||||||
IF(ZLIB_FOUND)
|
|
||||||
OPTION(PHYSFS_INTERNAL_ZLIB "Link own zlib instead of system library" FALSE)
|
|
||||||
ELSE(HAVE_SYSTEM_ZLIB)
|
|
||||||
SET(PHYSFS_INTERNAL_ZLIB TRUE)
|
|
||||||
ENDIF(ZLIB_FOUND)
|
|
||||||
|
|
||||||
IF(PHYSFS_INTERNAL_ZLIB)
|
|
||||||
INCLUDE_DIRECTORIES(zlib123)
|
|
||||||
ADD_DEFINITIONS(-DZ_PREFIX=1)
|
|
||||||
SET(PHYSFS_SRCS ${PHYSFS_SRCS} ${ZLIB_SRCS})
|
|
||||||
ELSE(PHYSFS_INTERNAL_ZLIB)
|
|
||||||
SET(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${ZLIB_LIBRARY})
|
|
||||||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
|
|
||||||
ENDIF(PHYSFS_INTERNAL_ZLIB)
|
|
||||||
ENDIF(PHYSFS_NEED_ZLIB)
|
|
||||||
|
|
||||||
OPTION(PHYSFS_BUILD_STATIC "Build static library" TRUE)
|
|
||||||
IF(PHYSFS_BUILD_STATIC)
|
|
||||||
ADD_LIBRARY(physfs-static STATIC ${PHYSFS_SRCS})
|
|
||||||
SET_TARGET_PROPERTIES(physfs-static PROPERTIES OUTPUT_NAME "physfs")
|
|
||||||
TARGET_LINK_LIBRARIES(physfs-static ${OPTIONAL_LIBRARY_LIBS})
|
|
||||||
TARGET_INCLUDE_DIRECTORIES(physfs-static PUBLIC .)
|
|
||||||
SET(PHYSFS_LIB_TARGET physfs-static)
|
|
||||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs-static")
|
|
||||||
ENDIF(PHYSFS_BUILD_STATIC)
|
|
||||||
|
|
||||||
OPTION(PHYSFS_BUILD_SHARED "Build shared library" FALSE)
|
|
||||||
IF(PHYSFS_BUILD_SHARED)
|
|
||||||
ADD_LIBRARY(physfs SHARED ${PHYSFS_SRCS})
|
|
||||||
SET_TARGET_PROPERTIES(physfs PROPERTIES VERSION ${PHYSFS_VERSION})
|
|
||||||
SET_TARGET_PROPERTIES(physfs PROPERTIES SOVERSION ${PHYSFS_SOVERSION})
|
|
||||||
TARGET_LINK_LIBRARIES(physfs ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
|
|
||||||
TARGET_INCLUDE_DIRECTORIES(physfs PUBLIC .)
|
|
||||||
SET(PHYSFS_LIB_TARGET physfs)
|
|
||||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
|
|
||||||
ENDIF(PHYSFS_BUILD_SHARED)
|
|
||||||
|
|
||||||
IF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
|
|
||||||
MESSAGE(FATAL "Both shared and static libraries are disabled!")
|
|
||||||
ENDIF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
|
|
||||||
|
|
||||||
# CMake FAQ says I need this...
|
|
||||||
IF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
|
|
||||||
SET_TARGET_PROPERTIES(physfs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
|
||||||
SET_TARGET_PROPERTIES(physfs-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
|
||||||
ENDIF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
|
|
||||||
|
|
||||||
OPTION(PHYSFS_BUILD_TEST "Build stdio test program." FALSE)
|
|
||||||
MARK_AS_ADVANCED(PHYSFS_BUILD_TEST)
|
|
||||||
IF(PHYSFS_BUILD_TEST)
|
|
||||||
FIND_PATH(READLINE_H readline/readline.h)
|
|
||||||
FIND_PATH(HISTORY_H readline/history.h)
|
|
||||||
IF(READLINE_H AND HISTORY_H)
|
|
||||||
FIND_LIBRARY(CURSES_LIBRARY NAMES curses ncurses)
|
|
||||||
SET(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
|
|
||||||
FIND_LIBRARY(READLINE_LIBRARY readline)
|
|
||||||
IF(READLINE_LIBRARY)
|
|
||||||
SET(HAVE_SYSTEM_READLINE TRUE)
|
|
||||||
SET(TEST_PHYSFS_LIBS ${TEST_PHYSFS_LIBS} ${READLINE_LIBRARY} ${CURSES_LIBRARY})
|
|
||||||
INCLUDE_DIRECTORIES(${READLINE_H} ${HISTORY_H})
|
|
||||||
ADD_DEFINITIONS(-DPHYSFS_HAVE_READLINE=1)
|
|
||||||
ENDIF(READLINE_LIBRARY)
|
|
||||||
ENDIF(READLINE_H AND HISTORY_H)
|
|
||||||
ADD_EXECUTABLE(test_physfs test/test_physfs.c)
|
|
||||||
TARGET_LINK_LIBRARIES(test_physfs ${PHYSFS_LIB_TARGET} ${TEST_PHYSFS_LIBS} ${OTHER_LDFLAGS})
|
|
||||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";test_physfs")
|
|
||||||
ENDIF(PHYSFS_BUILD_TEST)
|
|
||||||
|
|
||||||
OPTION(PHYSFS_BUILD_WX_TEST "Build wxWidgets test program." FALSE)
|
|
||||||
MARK_AS_ADVANCED(PHYSFS_BUILD_WX_TEST)
|
|
||||||
IF(PHYSFS_BUILD_WX_TEST)
|
|
||||||
SET(wxWidgets_USE_LIBS base core adv)
|
|
||||||
SET(wxWidgets_INCLUDE_DIRS_NO_SYSTEM 1)
|
|
||||||
FIND_PACKAGE(wxWidgets)
|
|
||||||
IF(wxWidgets_FOUND)
|
|
||||||
INCLUDE(${wxWidgets_USE_FILE})
|
|
||||||
ADD_EXECUTABLE(wxtest_physfs test/wxtest_physfs.cpp)
|
|
||||||
SET_SOURCE_FILES_PROPERTIES(test/wxtest_physfs.cpp COMPILE_FLAGS ${wxWidgets_CXX_FLAGS})
|
|
||||||
TARGET_LINK_LIBRARIES(wxtest_physfs ${PHYSFS_LIB_TARGET} ${wxWidgets_LIBRARIES} ${OTHER_LDFLAGS})
|
|
||||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";wxtest_physfs")
|
|
||||||
ELSE(wxWidgets_FOUND)
|
|
||||||
MESSAGE(STATUS "wxWidgets not found. Disabling wx test app.")
|
|
||||||
SET(PHYSFS_BUILD_WX_TEST FALSE)
|
|
||||||
ENDIF(wxWidgets_FOUND)
|
|
||||||
ENDIF(PHYSFS_BUILD_WX_TEST)
|
|
||||||
|
|
||||||
# Disabled in megasource.
|
|
||||||
#INSTALL(TARGETS ${PHYSFS_INSTALL_TARGETS}
|
|
||||||
# RUNTIME DESTINATION bin
|
|
||||||
# LIBRARY DESTINATION lib${LIB_SUFFIX}
|
|
||||||
# ARCHIVE DESTINATION lib${LIB_SUFFIX})
|
|
||||||
#INSTALL(FILES physfs.h DESTINATION include)
|
|
||||||
|
|
||||||
FIND_PACKAGE(Doxygen)
|
|
||||||
IF(DOXYGEN_FOUND)
|
|
||||||
SET(PHYSFS_OUTPUT_DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
|
|
||||||
CONFIGURE_FILE(
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile"
|
|
||||||
"${PHYSFS_OUTPUT_DOXYFILE}"
|
|
||||||
COPYONLY
|
|
||||||
)
|
|
||||||
FILE(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "\n\n# Below auto-generated by cmake...\n\n")
|
|
||||||
FILE(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "PROJECT_NUMBER = ${PHYSFS_VERSION}\n")
|
|
||||||
FILE(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "OUTPUT_DIRECTORY = ${CMAKE_CURRENT_BINARY_DIR}/docs\n")
|
|
||||||
FILE(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "\n# End auto-generated section.\n\n")
|
|
||||||
|
|
||||||
ADD_CUSTOM_TARGET(
|
|
||||||
docs
|
|
||||||
${DOXYGEN_EXECUTABLE} "${PHYSFS_OUTPUT_DOXYFILE}"
|
|
||||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
COMMENT "Building documentation in 'docs' directory..."
|
|
||||||
)
|
|
||||||
ELSE(DOXYGEN_FOUND)
|
|
||||||
MESSAGE(STATUS "Doxygen not found. You won't be able to build documentation.")
|
|
||||||
ENDIF(DOXYGEN_FOUND)
|
|
||||||
|
|
||||||
IF(UNIX)
|
|
||||||
SET(PHYSFS_TARBALL "${CMAKE_CURRENT_SOURCE_DIR}/../physfs-${PHYSFS_VERSION}.tar.bz2")
|
|
||||||
ADD_CUSTOM_TARGET(
|
|
||||||
dist
|
|
||||||
hg archive -t tbz2 "${PHYSFS_TARBALL}"
|
|
||||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
COMMENT "Building source tarball '${PHYSFS_TARBALL}'..."
|
|
||||||
)
|
|
||||||
ENDIF(UNIX)
|
|
||||||
|
|
||||||
MACRO(MESSAGE_BOOL_OPTION _NAME _VALUE)
|
|
||||||
IF(${_VALUE})
|
|
||||||
MESSAGE(STATUS " ${_NAME}: enabled")
|
|
||||||
ELSE(${_VALUE})
|
|
||||||
MESSAGE(STATUS " ${_NAME}: disabled")
|
|
||||||
ENDIF(${_VALUE})
|
|
||||||
ENDMACRO(MESSAGE_BOOL_OPTION)
|
|
||||||
|
|
||||||
MESSAGE(STATUS "PhysicsFS will build with the following options:")
|
|
||||||
MESSAGE_BOOL_OPTION("ZIP support" PHYSFS_ARCHIVE_ZIP)
|
|
||||||
MESSAGE_BOOL_OPTION("7zip support" PHYSFS_ARCHIVE_7Z)
|
|
||||||
MESSAGE_BOOL_OPTION("GRP support" PHYSFS_ARCHIVE_GRP)
|
|
||||||
MESSAGE_BOOL_OPTION("WAD support" PHYSFS_ARCHIVE_WAD)
|
|
||||||
MESSAGE_BOOL_OPTION("HOG support" PHYSFS_ARCHIVE_HOG)
|
|
||||||
MESSAGE_BOOL_OPTION("MVL support" PHYSFS_ARCHIVE_MVL)
|
|
||||||
MESSAGE_BOOL_OPTION("QPAK support" PHYSFS_ARCHIVE_QPAK)
|
|
||||||
MESSAGE_BOOL_OPTION("CD-ROM drive support" PHYSFS_HAVE_CDROM_SUPPORT)
|
|
||||||
MESSAGE_BOOL_OPTION("Thread safety" PHYSFS_HAVE_THREAD_SUPPORT)
|
|
||||||
MESSAGE_BOOL_OPTION("Build own zlib" PHYSFS_INTERNAL_ZLIB)
|
|
||||||
MESSAGE_BOOL_OPTION("Build static library" PHYSFS_BUILD_STATIC)
|
|
||||||
MESSAGE_BOOL_OPTION("Build shared library" PHYSFS_BUILD_SHARED)
|
|
||||||
MESSAGE_BOOL_OPTION("Build wxWidgets test program" PHYSFS_BUILD_WX_TEST)
|
|
||||||
MESSAGE_BOOL_OPTION("Build stdio test program" PHYSFS_BUILD_TEST)
|
|
||||||
IF(PHYSFS_BUILD_TEST)
|
|
||||||
MESSAGE_BOOL_OPTION(" Use readline in test program" HAVE_SYSTEM_READLINE)
|
|
||||||
ENDIF(PHYSFS_BUILD_TEST)
|
|
||||||
|
|
||||||
# end of CMakeLists.txt ...
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
|
|
||||||
The latest PhysicsFS information and releases can be found at:
|
|
||||||
http://icculus.org/physfs/
|
|
||||||
|
|
||||||
Building is (ahem) very easy.
|
|
||||||
|
|
||||||
|
|
||||||
ALL PLATFORMS:
|
|
||||||
|
|
||||||
Please understand your rights and mine: read the text file LICENSE.txt in the
|
|
||||||
root of the source tree. If you can't abide by it, delete this source tree
|
|
||||||
now. The license is extremely liberal, even to closed-source, commercial
|
|
||||||
applications.
|
|
||||||
|
|
||||||
If you've got Doxygen (http://www.doxygen.org/) installed, you can run it
|
|
||||||
without any command line arguments in the root of the source tree to generate
|
|
||||||
the API reference (or build the "docs" target from your build system). This
|
|
||||||
is optional. You can browse the API docs online here:
|
|
||||||
|
|
||||||
http://icculus.org/physfs/docs/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
UNIX:
|
|
||||||
|
|
||||||
You will need CMake (http://www.cmake.org/) 2.4 or later installed.
|
|
||||||
|
|
||||||
Make a directory, wherever you like. This will be your build directory.
|
|
||||||
|
|
||||||
Chdir to your build directory. Run "cmake /where/i/unpacked/physfs" to
|
|
||||||
generate Makefiles. You can then run "ccmake ." and customize the build,
|
|
||||||
but the defaults are probably okay. You can have CMake generate KDevelop
|
|
||||||
project files if you prefer these.
|
|
||||||
|
|
||||||
Run "make". PhysicsFS will now build.
|
|
||||||
|
|
||||||
As root, run "make install".
|
|
||||||
If you get sick of the library, run "xargs rm < install_manifest.txt" as root
|
|
||||||
and it will remove all traces of the library from the system paths.
|
|
||||||
|
|
||||||
Once you are satisfied, you can delete the build directory.
|
|
||||||
|
|
||||||
Primary Unix development is done with GNU/Linux, but PhysicsFS is known to
|
|
||||||
work out of the box with several flavors of Unix. It it doesn't work, patches
|
|
||||||
to get it running can be sent to icculus@icculus.org.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BeOS, Zeta, and Haiku:
|
|
||||||
|
|
||||||
Use the "Unix" instructions, above. The CMake port to BeOS is fairly new at
|
|
||||||
the time of this writing, but it works. You can get a build of CMake from
|
|
||||||
bebits.com or build it yourself from source from cmake.org.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Windows:
|
|
||||||
|
|
||||||
If building with Cygwin, mingw32, MSYS, or something else that uses the GNU
|
|
||||||
toolchain, follow the Unix instructions, above.
|
|
||||||
|
|
||||||
If you want to use Visual Studio, nmake, or the Platform SDK, you will need
|
|
||||||
CMake (http://www.cmake.org/) 2.4 or later installed. Point CMake at the
|
|
||||||
CMakeLists.txt file in the root of the source directory and hit the
|
|
||||||
"Configure" button. After telling it what type of compiler you are targeting
|
|
||||||
(Borland, Visual Studio, etc), CMake will process for while and then give you
|
|
||||||
a list of options you can change (what archivers you want to support, etc).
|
|
||||||
If you aren't sure, the defaults are probably fine. Hit the "Configure"
|
|
||||||
button again, then "OK" once configuration has completed with options that
|
|
||||||
match your liking. Now project files for your favorite programming
|
|
||||||
environment will be generated for you in the directory you specified.
|
|
||||||
Go there and use them to build PhysicsFS.
|
|
||||||
|
|
||||||
PhysicsFS will only link directly against system libraries that have existed
|
|
||||||
since Windows 95 and Windows NT 3.51. If there's a newer API we want to use,
|
|
||||||
we try to dynamically load it at runtime and fallback to a reasonable
|
|
||||||
behaviour when we can't find it...this is used for Unicode support and
|
|
||||||
locating user-specific directories, etc.
|
|
||||||
|
|
||||||
PhysicsFS has not been tested on 64-bit Windows, but probably works. There is
|
|
||||||
no 16-bit Windows support at all. Reports of success and problems can go to
|
|
||||||
Ryan at icculus@icculus.org ...
|
|
||||||
|
|
||||||
If someone is willing to maintain prebuilt PhysicsFS DLLs, I'd like to hear
|
|
||||||
from you; send an email to icculus@icculus.org ...
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PocketPC/WindowsCE:
|
|
||||||
|
|
||||||
Code exists for PocketPC support, and there are shipping titles that used
|
|
||||||
PhysicsFS 1.0 on PocketPC...but it isn't tested in 2.0, and is probably
|
|
||||||
broken with the new build system. Please send patches.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MAC OS 8/9:
|
|
||||||
|
|
||||||
Classic Mac OS support has been dropped in PhysicsFS 2.0. Apple hasn't updated
|
|
||||||
pre-OSX versions in more than a decade at this point, none of the hardware
|
|
||||||
they've shipped will boot it for almost as many years, and finding
|
|
||||||
developer tools for it is becoming almost impossible. As the switch to Intel
|
|
||||||
hardware has removed the "Classic" emulation environment, it was time to
|
|
||||||
remove support from PhysicsFS. That being said, the PhysicsFS 1.0 branch can
|
|
||||||
still target back to Mac OS 8.5, so you can use that if you need support for
|
|
||||||
this legacy OS. We still very much support Mac OS X, though: see below.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MAC OS X:
|
|
||||||
|
|
||||||
You will need CMake (http://www.cmake.org/) 2.4 or later installed.
|
|
||||||
|
|
||||||
You can either generate a Unix makefile with CMake, or generate an Xcode
|
|
||||||
project, whichever makes you more comfortable.
|
|
||||||
|
|
||||||
PowerPC and Intel Macs should both be supported.
|
|
||||||
|
|
||||||
If someone is willing to maintain prebuilt PhysicsFS Shared Libraries for
|
|
||||||
Mac OS X, I'd like to hear from you; send an email to icculus@icculus.org.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OS/2:
|
|
||||||
|
|
||||||
You need Innotek GCC and libc installed (or kLIBC). I tried this on a stock
|
|
||||||
Warp 4 install, no fixpaks. You need to install link386.exe (Selective
|
|
||||||
Install, "link object modules" option). Once klibc and GCC are installed
|
|
||||||
correctly, unpack the source to PhysicsFS and run the script
|
|
||||||
file "makeos2.cmd". I know this isn't ideal, but I wanted to have this build
|
|
||||||
without users having to hunt down a "make" program.
|
|
||||||
|
|
||||||
Someone please port CMake to OS/2. Ideally I'd like to be able to target
|
|
||||||
Innotek GCC and OpenWatcom with CMake.
|
|
||||||
|
|
||||||
If someone is willing to maintain prebuilt PhysicsFS Shared Libraries for
|
|
||||||
OS/2, I'd like to hear from you; send an email to icculus@icculus.org.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OTHER PLATFORMS:
|
|
||||||
|
|
||||||
Many Unix-like platforms might "just work" with CMake. Some of these platforms
|
|
||||||
are known to have worked at one time, but have not been heavily tested, if
|
|
||||||
tested at all. PhysicsFS is, as far as we know, 64-bit and byteorder clean,
|
|
||||||
and is known to compile on several compilers across many platforms. To
|
|
||||||
implement a new platform or archiver, please read the heavily-commented
|
|
||||||
physfs_internal.h and look in the platform/ and archiver/ directories for
|
|
||||||
examples.
|
|
||||||
|
|
||||||
--ryan. (icculus@icculus.org)
|
|
||||||
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
Stuff that needs to be done and wishlist:
|
|
||||||
|
|
||||||
These are in no particular order.
|
|
||||||
Some might be dupes, some might be done already.
|
|
||||||
|
|
||||||
UNICODE:
|
|
||||||
- OS/2: Codepages. No full Unicode in the filesystem, but we can probably make
|
|
||||||
a conversion effort.
|
|
||||||
|
|
||||||
|
|
||||||
Stuff:
|
|
||||||
- Other archivers: perhaps tar(.gz|.bz2), RPM, ARJ, etc. These are less
|
|
||||||
important, since streaming archives aren't of much value to games (which
|
|
||||||
is why zipfiles are king: random access), but it could have uses for, say,
|
|
||||||
an installer/updater.
|
|
||||||
- Reduce malloc() pressure all over the place. We fragment memory like mad.
|
|
||||||
- profile string list interpolation.
|
|
||||||
- We have two different ways to find dir entries in zip.c.
|
|
||||||
- Do symlinks in zip archiver work when they point to dirs?
|
|
||||||
- Enable more warnings?
|
|
||||||
- Use __cdecl in physfs.h?
|
|
||||||
- Look for FIXMEs (many marked with "!!!" in comments).
|
|
||||||
- Find some way to relax or remove the security model for external tools.
|
|
||||||
- OSX shouldn't use ~/.app for userdir.
|
|
||||||
- fscanf and fprintf support in extras dir.
|
|
||||||
- Why do we call it openArchive and dirClose?
|
|
||||||
- Sanity check byte order at runtime.
|
|
||||||
- Memory locking?
|
|
||||||
- Find a better name than dvoid and fvoid.
|
|
||||||
- Can windows.c and pocketpc.c get merged?
|
|
||||||
- There's so much cut-and-paste between archivers...can this be reduced?
|
|
||||||
- General code audit.
|
|
||||||
- Multiple write dirs with mount points?
|
|
||||||
- Deprecate PHYSFS_setSaneConfig and move it to extras?
|
|
||||||
- Why is physfsrwops.c cut-and-pasted into the ruby bindings?
|
|
||||||
- Replace code from SDL...
|
|
||||||
- Should file enumeration return an error or set error state?
|
|
||||||
- Need "getmountpoint" command in test_physfs.c ...
|
|
||||||
- Look for calloc() calls that aren't going through the allocation hooks.
|
|
||||||
- Write up a simple HOWTO on embedding physicsfs in another project.
|
|
||||||
- Archivers need abstracted i/o to read from memory or files (archives in archives?)
|
|
||||||
- Probably other stuff. Requests and recommendations are welcome.
|
|
||||||
|
|
||||||
// end of TODO.txt ...
|
|
||||||
|
|
||||||
@@ -1,283 +0,0 @@
|
|||||||
/*
|
|
||||||
* Standard directory I/O support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "physfs.h"
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
static PHYSFS_sint64 DIR_read(fvoid *opaque, void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
PHYSFS_sint64 retval;
|
|
||||||
retval = __PHYSFS_platformRead(opaque, buffer, objSize, objCount);
|
|
||||||
return(retval);
|
|
||||||
} /* DIR_read */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 DIR_write(fvoid *opaque, const void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
PHYSFS_sint64 retval;
|
|
||||||
retval = __PHYSFS_platformWrite(opaque, buffer, objSize, objCount);
|
|
||||||
return(retval);
|
|
||||||
} /* DIR_write */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_eof(fvoid *opaque)
|
|
||||||
{
|
|
||||||
return(__PHYSFS_platformEOF(opaque));
|
|
||||||
} /* DIR_eof */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 DIR_tell(fvoid *opaque)
|
|
||||||
{
|
|
||||||
return(__PHYSFS_platformTell(opaque));
|
|
||||||
} /* DIR_tell */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
|
||||||
{
|
|
||||||
return(__PHYSFS_platformSeek(opaque, offset));
|
|
||||||
} /* DIR_seek */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 DIR_fileLength(fvoid *opaque)
|
|
||||||
{
|
|
||||||
return(__PHYSFS_platformFileLength(opaque));
|
|
||||||
} /* DIR_fileLength */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_fileClose(fvoid *opaque)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* we manually flush the buffer, since that's the place a close will
|
|
||||||
* most likely fail, but that will leave the file handle in an undefined
|
|
||||||
* state if it fails. Flush failures we can recover from.
|
|
||||||
*/
|
|
||||||
BAIL_IF_MACRO(!__PHYSFS_platformFlush(opaque), NULL, 0);
|
|
||||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(opaque), NULL, 0);
|
|
||||||
return(1);
|
|
||||||
} /* DIR_fileClose */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_isArchive(const char *filename, int forWriting)
|
|
||||||
{
|
|
||||||
/* directories ARE archives in this driver... */
|
|
||||||
return(__PHYSFS_platformIsDirectory(filename));
|
|
||||||
} /* DIR_isArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static void *DIR_openArchive(const char *name, int forWriting)
|
|
||||||
{
|
|
||||||
const char *dirsep = PHYSFS_getDirSeparator();
|
|
||||||
char *retval = NULL;
|
|
||||||
size_t namelen = strlen(name);
|
|
||||||
size_t seplen = strlen(dirsep);
|
|
||||||
|
|
||||||
/* !!! FIXME: when is this not called right before openArchive? */
|
|
||||||
BAIL_IF_MACRO(!DIR_isArchive(name, forWriting),
|
|
||||||
ERR_UNSUPPORTED_ARCHIVE, 0);
|
|
||||||
|
|
||||||
retval = allocator.Malloc(namelen + seplen + 1);
|
|
||||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
|
|
||||||
/* make sure there's a dir separator at the end of the string */
|
|
||||||
strcpy(retval, name);
|
|
||||||
if (strcmp((name + namelen) - seplen, dirsep) != 0)
|
|
||||||
strcat(retval, dirsep);
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* DIR_openArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static void DIR_enumerateFiles(dvoid *opaque, const char *dname,
|
|
||||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
|
||||||
const char *origdir, void *callbackdata)
|
|
||||||
{
|
|
||||||
char *d = __PHYSFS_platformCvtToDependent((char *)opaque, dname, NULL);
|
|
||||||
if (d != NULL)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb,
|
|
||||||
origdir, callbackdata);
|
|
||||||
allocator.Free(d);
|
|
||||||
} /* if */
|
|
||||||
} /* DIR_enumerateFiles */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_exists(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
|
||||||
retval = __PHYSFS_platformExists(f);
|
|
||||||
allocator.Free(f);
|
|
||||||
return(retval);
|
|
||||||
} /* DIR_exists */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
|
||||||
int retval = 0;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(d == NULL, NULL, 0);
|
|
||||||
*fileExists = __PHYSFS_platformExists(d);
|
|
||||||
if (*fileExists)
|
|
||||||
retval = __PHYSFS_platformIsDirectory(d);
|
|
||||||
allocator.Free(d);
|
|
||||||
return(retval);
|
|
||||||
} /* DIR_isDirectory */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
|
||||||
int retval = 0;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
|
||||||
*fileExists = __PHYSFS_platformExists(f);
|
|
||||||
if (*fileExists)
|
|
||||||
retval = __PHYSFS_platformIsSymLink(f);
|
|
||||||
allocator.Free(f);
|
|
||||||
return(retval);
|
|
||||||
} /* DIR_isSymLink */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 DIR_getLastModTime(dvoid *opaque,
|
|
||||||
const char *name,
|
|
||||||
int *fileExists)
|
|
||||||
{
|
|
||||||
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
|
||||||
PHYSFS_sint64 retval = -1;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(d == NULL, NULL, 0);
|
|
||||||
*fileExists = __PHYSFS_platformExists(d);
|
|
||||||
if (*fileExists)
|
|
||||||
retval = __PHYSFS_platformGetLastModTime(d);
|
|
||||||
allocator.Free(d);
|
|
||||||
return(retval);
|
|
||||||
} /* DIR_getLastModTime */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *doOpen(dvoid *opaque, const char *name,
|
|
||||||
void *(*openFunc)(const char *filename),
|
|
||||||
int *fileExists)
|
|
||||||
{
|
|
||||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
|
||||||
void *rc = NULL;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(f == NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (fileExists != NULL)
|
|
||||||
{
|
|
||||||
*fileExists = __PHYSFS_platformExists(f);
|
|
||||||
if (!(*fileExists))
|
|
||||||
{
|
|
||||||
allocator.Free(f);
|
|
||||||
return(NULL);
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
rc = openFunc(f);
|
|
||||||
allocator.Free(f);
|
|
||||||
|
|
||||||
return((fvoid *) rc);
|
|
||||||
} /* doOpen */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *DIR_openRead(dvoid *opaque, const char *fnm, int *exist)
|
|
||||||
{
|
|
||||||
return(doOpen(opaque, fnm, __PHYSFS_platformOpenRead, exist));
|
|
||||||
} /* DIR_openRead */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *DIR_openWrite(dvoid *opaque, const char *filename)
|
|
||||||
{
|
|
||||||
return(doOpen(opaque, filename, __PHYSFS_platformOpenWrite, NULL));
|
|
||||||
} /* DIR_openWrite */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *DIR_openAppend(dvoid *opaque, const char *filename)
|
|
||||||
{
|
|
||||||
return(doOpen(opaque, filename, __PHYSFS_platformOpenAppend, NULL));
|
|
||||||
} /* DIR_openAppend */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_remove(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
|
||||||
retval = __PHYSFS_platformDelete(f);
|
|
||||||
allocator.Free(f);
|
|
||||||
return(retval);
|
|
||||||
} /* DIR_remove */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_mkdir(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
|
||||||
retval = __PHYSFS_platformMkDir(f);
|
|
||||||
allocator.Free(f);
|
|
||||||
return(retval);
|
|
||||||
} /* DIR_mkdir */
|
|
||||||
|
|
||||||
|
|
||||||
static void DIR_dirClose(dvoid *opaque)
|
|
||||||
{
|
|
||||||
allocator.Free(opaque);
|
|
||||||
} /* DIR_dirClose */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_DIR =
|
|
||||||
{
|
|
||||||
"",
|
|
||||||
DIR_ARCHIVE_DESCRIPTION,
|
|
||||||
"Ryan C. Gordon <icculus@icculus.org>",
|
|
||||||
"http://icculus.org/physfs/",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
|
|
||||||
{
|
|
||||||
&__PHYSFS_ArchiveInfo_DIR,
|
|
||||||
DIR_isArchive, /* isArchive() method */
|
|
||||||
DIR_openArchive, /* openArchive() method */
|
|
||||||
DIR_enumerateFiles, /* enumerateFiles() method */
|
|
||||||
DIR_exists, /* exists() method */
|
|
||||||
DIR_isDirectory, /* isDirectory() method */
|
|
||||||
DIR_isSymLink, /* isSymLink() method */
|
|
||||||
DIR_getLastModTime, /* getLastModTime() method */
|
|
||||||
DIR_openRead, /* openRead() method */
|
|
||||||
DIR_openWrite, /* openWrite() method */
|
|
||||||
DIR_openAppend, /* openAppend() method */
|
|
||||||
DIR_remove, /* remove() method */
|
|
||||||
DIR_mkdir, /* mkdir() method */
|
|
||||||
DIR_dirClose, /* dirClose() method */
|
|
||||||
DIR_read, /* read() method */
|
|
||||||
DIR_write, /* write() method */
|
|
||||||
DIR_eof, /* eof() method */
|
|
||||||
DIR_tell, /* tell() method */
|
|
||||||
DIR_seek, /* seek() method */
|
|
||||||
DIR_fileLength, /* fileLength() method */
|
|
||||||
DIR_fileClose /* fileClose() method */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* end of dir.c ... */
|
|
||||||
|
|
||||||
@@ -1,475 +0,0 @@
|
|||||||
/*
|
|
||||||
* GRP support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* This driver handles BUILD engine archives ("groupfiles"). This format
|
|
||||||
* (but not this driver) was put together by Ken Silverman.
|
|
||||||
*
|
|
||||||
* The format is simple enough. In Ken's words:
|
|
||||||
*
|
|
||||||
* What's the .GRP file format?
|
|
||||||
*
|
|
||||||
* The ".grp" file format is just a collection of a lot of files stored
|
|
||||||
* into 1 big one. I tried to make the format as simple as possible: The
|
|
||||||
* first 12 bytes contains my name, "KenSilverman". The next 4 bytes is
|
|
||||||
* the number of files that were compacted into the group file. Then for
|
|
||||||
* each file, there is a 16 byte structure, where the first 12 bytes are
|
|
||||||
* the filename, and the last 4 bytes are the file's size. The rest of
|
|
||||||
* the group file is just the raw data packed one after the other in the
|
|
||||||
* same order as the list of files.
|
|
||||||
*
|
|
||||||
* (That info is from http://www.advsys.net/ken/build.htm ...)
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (defined PHYSFS_SUPPORTS_GRP)
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "physfs.h"
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char name[13];
|
|
||||||
PHYSFS_uint32 startPos;
|
|
||||||
PHYSFS_uint32 size;
|
|
||||||
} GRPentry;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
PHYSFS_sint64 last_mod_time;
|
|
||||||
PHYSFS_uint32 entryCount;
|
|
||||||
GRPentry *entries;
|
|
||||||
} GRPinfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
void *handle;
|
|
||||||
GRPentry *entry;
|
|
||||||
PHYSFS_uint32 curPos;
|
|
||||||
} GRPfileinfo;
|
|
||||||
|
|
||||||
|
|
||||||
static void GRP_dirClose(dvoid *opaque)
|
|
||||||
{
|
|
||||||
GRPinfo *info = ((GRPinfo *) opaque);
|
|
||||||
allocator.Free(info->filename);
|
|
||||||
allocator.Free(info->entries);
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* GRP_dirClose */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 GRP_read(fvoid *opaque, void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
|
||||||
GRPentry *entry = finfo->entry;
|
|
||||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
|
||||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
|
||||||
PHYSFS_sint64 rc;
|
|
||||||
|
|
||||||
if (objsLeft < objCount)
|
|
||||||
objCount = objsLeft;
|
|
||||||
|
|
||||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
|
||||||
if (rc > 0)
|
|
||||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* GRP_read */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 GRP_write(fvoid *opaque, const void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
|
||||||
} /* GRP_write */
|
|
||||||
|
|
||||||
|
|
||||||
static int GRP_eof(fvoid *opaque)
|
|
||||||
{
|
|
||||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
|
||||||
GRPentry *entry = finfo->entry;
|
|
||||||
return(finfo->curPos >= entry->size);
|
|
||||||
} /* GRP_eof */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 GRP_tell(fvoid *opaque)
|
|
||||||
{
|
|
||||||
return(((GRPfileinfo *) opaque)->curPos);
|
|
||||||
} /* GRP_tell */
|
|
||||||
|
|
||||||
|
|
||||||
static int GRP_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
|
||||||
{
|
|
||||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
|
||||||
GRPentry *entry = finfo->entry;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
|
||||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
|
||||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
|
||||||
if (rc)
|
|
||||||
finfo->curPos = (PHYSFS_uint32) offset;
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* GRP_seek */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 GRP_fileLength(fvoid *opaque)
|
|
||||||
{
|
|
||||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
|
||||||
return((PHYSFS_sint64) finfo->entry->size);
|
|
||||||
} /* GRP_fileLength */
|
|
||||||
|
|
||||||
|
|
||||||
static int GRP_fileClose(fvoid *opaque)
|
|
||||||
{
|
|
||||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
|
||||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
|
||||||
allocator.Free(finfo);
|
|
||||||
return(1);
|
|
||||||
} /* GRP_fileClose */
|
|
||||||
|
|
||||||
|
|
||||||
static int grp_open(const char *filename, int forWriting,
|
|
||||||
void **fh, PHYSFS_uint32 *count)
|
|
||||||
{
|
|
||||||
PHYSFS_uint8 buf[12];
|
|
||||||
|
|
||||||
*fh = NULL;
|
|
||||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
|
||||||
|
|
||||||
*fh = __PHYSFS_platformOpenRead(filename);
|
|
||||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, buf, 12, 1) != 1)
|
|
||||||
goto openGrp_failed;
|
|
||||||
|
|
||||||
if (memcmp(buf, "KenSilverman", 12) != 0)
|
|
||||||
{
|
|
||||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
|
||||||
goto openGrp_failed;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
|
||||||
goto openGrp_failed;
|
|
||||||
|
|
||||||
*count = PHYSFS_swapULE32(*count);
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
|
|
||||||
openGrp_failed:
|
|
||||||
if (*fh != NULL)
|
|
||||||
__PHYSFS_platformClose(*fh);
|
|
||||||
|
|
||||||
*count = -1;
|
|
||||||
*fh = NULL;
|
|
||||||
return(0);
|
|
||||||
} /* grp_open */
|
|
||||||
|
|
||||||
|
|
||||||
static int GRP_isArchive(const char *filename, int forWriting)
|
|
||||||
{
|
|
||||||
void *fh;
|
|
||||||
PHYSFS_uint32 fileCount;
|
|
||||||
int retval = grp_open(filename, forWriting, &fh, &fileCount);
|
|
||||||
|
|
||||||
if (fh != NULL)
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* GRP_isArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static int grp_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
if (one != two)
|
|
||||||
{
|
|
||||||
const GRPentry *a = (const GRPentry *) _a;
|
|
||||||
return(strcmp(a[one].name, a[two].name));
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* grp_entry_cmp */
|
|
||||||
|
|
||||||
|
|
||||||
static void grp_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
if (one != two)
|
|
||||||
{
|
|
||||||
GRPentry tmp;
|
|
||||||
GRPentry *first = &(((GRPentry *) _a)[one]);
|
|
||||||
GRPentry *second = &(((GRPentry *) _a)[two]);
|
|
||||||
memcpy(&tmp, first, sizeof (GRPentry));
|
|
||||||
memcpy(first, second, sizeof (GRPentry));
|
|
||||||
memcpy(second, &tmp, sizeof (GRPentry));
|
|
||||||
} /* if */
|
|
||||||
} /* grp_entry_swap */
|
|
||||||
|
|
||||||
|
|
||||||
static int grp_load_entries(const char *name, int forWriting, GRPinfo *info)
|
|
||||||
{
|
|
||||||
void *fh = NULL;
|
|
||||||
PHYSFS_uint32 fileCount;
|
|
||||||
PHYSFS_uint32 location = 16; /* sizeof sig. */
|
|
||||||
GRPentry *entry;
|
|
||||||
char *ptr;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(!grp_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
|
||||||
info->entryCount = fileCount;
|
|
||||||
info->entries = (GRPentry *) allocator.Malloc(sizeof(GRPentry)*fileCount);
|
|
||||||
if (info->entries == NULL)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
location += (16 * fileCount);
|
|
||||||
|
|
||||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
|
||||||
{
|
|
||||||
if (__PHYSFS_platformRead(fh, &entry->name, 12, 1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
entry->name[12] = '\0'; /* name isn't null-terminated in file. */
|
|
||||||
if ((ptr = strchr(entry->name, ' ')) != NULL)
|
|
||||||
*ptr = '\0'; /* trim extra spaces. */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
entry->size = PHYSFS_swapULE32(entry->size);
|
|
||||||
entry->startPos = location;
|
|
||||||
location += entry->size;
|
|
||||||
} /* for */
|
|
||||||
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
|
|
||||||
__PHYSFS_sort(info->entries, info->entryCount,
|
|
||||||
grp_entry_cmp, grp_entry_swap);
|
|
||||||
return(1);
|
|
||||||
} /* grp_load_entries */
|
|
||||||
|
|
||||||
|
|
||||||
static void *GRP_openArchive(const char *name, int forWriting)
|
|
||||||
{
|
|
||||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
|
||||||
GRPinfo *info = (GRPinfo *) allocator.Malloc(sizeof (GRPinfo));
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
||||||
|
|
||||||
memset(info, '\0', sizeof (GRPinfo));
|
|
||||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
|
||||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, GRP_openArchive_failed);
|
|
||||||
|
|
||||||
if (!grp_load_entries(name, forWriting, info))
|
|
||||||
goto GRP_openArchive_failed;
|
|
||||||
|
|
||||||
strcpy(info->filename, name);
|
|
||||||
info->last_mod_time = modtime;
|
|
||||||
|
|
||||||
return(info);
|
|
||||||
|
|
||||||
GRP_openArchive_failed:
|
|
||||||
if (info != NULL)
|
|
||||||
{
|
|
||||||
if (info->filename != NULL)
|
|
||||||
allocator.Free(info->filename);
|
|
||||||
if (info->entries != NULL)
|
|
||||||
allocator.Free(info->entries);
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return(NULL);
|
|
||||||
} /* GRP_openArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static void GRP_enumerateFiles(dvoid *opaque, const char *dname,
|
|
||||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
|
||||||
const char *origdir, void *callbackdata)
|
|
||||||
{
|
|
||||||
/* no directories in GRP files. */
|
|
||||||
if (*dname == '\0')
|
|
||||||
{
|
|
||||||
GRPinfo *info = (GRPinfo *) opaque;
|
|
||||||
GRPentry *entry = info->entries;
|
|
||||||
PHYSFS_uint32 max = info->entryCount;
|
|
||||||
PHYSFS_uint32 i;
|
|
||||||
|
|
||||||
for (i = 0; i < max; i++, entry++)
|
|
||||||
cb(callbackdata, origdir, entry->name);
|
|
||||||
} /* if */
|
|
||||||
} /* GRP_enumerateFiles */
|
|
||||||
|
|
||||||
|
|
||||||
static GRPentry *grp_find_entry(GRPinfo *info, const char *name)
|
|
||||||
{
|
|
||||||
char *ptr = strchr(name, '.');
|
|
||||||
GRPentry *a = info->entries;
|
|
||||||
PHYSFS_sint32 lo = 0;
|
|
||||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
|
||||||
PHYSFS_sint32 middle;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Rule out filenames to avoid unneeded processing...no dirs,
|
|
||||||
* big filenames, or extensions > 3 chars.
|
|
||||||
*/
|
|
||||||
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
|
|
||||||
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
|
|
||||||
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
|
|
||||||
|
|
||||||
while (lo <= hi)
|
|
||||||
{
|
|
||||||
middle = lo + ((hi - lo) / 2);
|
|
||||||
rc = strcmp(name, a[middle].name);
|
|
||||||
if (rc == 0) /* found it! */
|
|
||||||
return(&a[middle]);
|
|
||||||
else if (rc > 0)
|
|
||||||
lo = middle + 1;
|
|
||||||
else
|
|
||||||
hi = middle - 1;
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
|
||||||
} /* grp_find_entry */
|
|
||||||
|
|
||||||
|
|
||||||
static int GRP_exists(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
return(grp_find_entry((GRPinfo *) opaque, name) != NULL);
|
|
||||||
} /* GRP_exists */
|
|
||||||
|
|
||||||
|
|
||||||
static int GRP_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
*fileExists = GRP_exists(opaque, name);
|
|
||||||
return(0); /* never directories in a groupfile. */
|
|
||||||
} /* GRP_isDirectory */
|
|
||||||
|
|
||||||
|
|
||||||
static int GRP_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
*fileExists = GRP_exists(opaque, name);
|
|
||||||
return(0); /* never symlinks in a groupfile. */
|
|
||||||
} /* GRP_isSymLink */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 GRP_getLastModTime(dvoid *opaque,
|
|
||||||
const char *name,
|
|
||||||
int *fileExists)
|
|
||||||
{
|
|
||||||
GRPinfo *info = (GRPinfo *) opaque;
|
|
||||||
PHYSFS_sint64 retval = -1;
|
|
||||||
|
|
||||||
*fileExists = (grp_find_entry(info, name) != NULL);
|
|
||||||
if (*fileExists) /* use time of GRP itself in the physical filesystem. */
|
|
||||||
retval = info->last_mod_time;
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* GRP_getLastModTime */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *GRP_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
|
||||||
{
|
|
||||||
GRPinfo *info = (GRPinfo *) opaque;
|
|
||||||
GRPfileinfo *finfo;
|
|
||||||
GRPentry *entry;
|
|
||||||
|
|
||||||
entry = grp_find_entry(info, fnm);
|
|
||||||
*fileExists = (entry != NULL);
|
|
||||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
|
||||||
|
|
||||||
finfo = (GRPfileinfo *) allocator.Malloc(sizeof (GRPfileinfo));
|
|
||||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
|
|
||||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
|
||||||
if ( (finfo->handle == NULL) ||
|
|
||||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
|
||||||
{
|
|
||||||
allocator.Free(finfo);
|
|
||||||
return(NULL);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
finfo->curPos = 0;
|
|
||||||
finfo->entry = entry;
|
|
||||||
return(finfo);
|
|
||||||
} /* GRP_openRead */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *GRP_openWrite(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* GRP_openWrite */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *GRP_openAppend(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* GRP_openAppend */
|
|
||||||
|
|
||||||
|
|
||||||
static int GRP_remove(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* GRP_remove */
|
|
||||||
|
|
||||||
|
|
||||||
static int GRP_mkdir(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* GRP_mkdir */
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_GRP =
|
|
||||||
{
|
|
||||||
"GRP",
|
|
||||||
GRP_ARCHIVE_DESCRIPTION,
|
|
||||||
"Ryan C. Gordon <icculus@icculus.org>",
|
|
||||||
"http://icculus.org/physfs/",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
|
|
||||||
{
|
|
||||||
&__PHYSFS_ArchiveInfo_GRP,
|
|
||||||
GRP_isArchive, /* isArchive() method */
|
|
||||||
GRP_openArchive, /* openArchive() method */
|
|
||||||
GRP_enumerateFiles, /* enumerateFiles() method */
|
|
||||||
GRP_exists, /* exists() method */
|
|
||||||
GRP_isDirectory, /* isDirectory() method */
|
|
||||||
GRP_isSymLink, /* isSymLink() method */
|
|
||||||
GRP_getLastModTime, /* getLastModTime() method */
|
|
||||||
GRP_openRead, /* openRead() method */
|
|
||||||
GRP_openWrite, /* openWrite() method */
|
|
||||||
GRP_openAppend, /* openAppend() method */
|
|
||||||
GRP_remove, /* remove() method */
|
|
||||||
GRP_mkdir, /* mkdir() method */
|
|
||||||
GRP_dirClose, /* dirClose() method */
|
|
||||||
GRP_read, /* read() method */
|
|
||||||
GRP_write, /* write() method */
|
|
||||||
GRP_eof, /* eof() method */
|
|
||||||
GRP_tell, /* tell() method */
|
|
||||||
GRP_seek, /* seek() method */
|
|
||||||
GRP_fileLength, /* fileLength() method */
|
|
||||||
GRP_fileClose /* fileClose() method */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined PHYSFS_SUPPORTS_GRP */
|
|
||||||
|
|
||||||
/* end of grp.c ... */
|
|
||||||
|
|
||||||
@@ -1,514 +0,0 @@
|
|||||||
/*
|
|
||||||
* HOG support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* This driver handles Descent I/II HOG archives.
|
|
||||||
*
|
|
||||||
* The format is very simple:
|
|
||||||
*
|
|
||||||
* The file always starts with the 3-byte signature "DHF" (Descent
|
|
||||||
* HOG file). After that the files of a HOG are just attached after
|
|
||||||
* another, divided by a 17 bytes header, which specifies the name
|
|
||||||
* and length (in bytes) of the forthcoming file! So you just read
|
|
||||||
* the header with its information of how big the following file is,
|
|
||||||
* and then skip exact that number of bytes to get to the next file
|
|
||||||
* in that HOG.
|
|
||||||
*
|
|
||||||
* char sig[3] = {'D', 'H', 'F'}; // "DHF"=Descent HOG File
|
|
||||||
*
|
|
||||||
* struct {
|
|
||||||
* char file_name[13]; // Filename, padded to 13 bytes with 0s
|
|
||||||
* int file_size; // filesize in bytes
|
|
||||||
* char data[file_size]; // The file data
|
|
||||||
* } FILE_STRUCT; // Repeated until the end of the file.
|
|
||||||
*
|
|
||||||
* (That info is from http://www.descent2.com/ddn/specs/hog/)
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Bradley Bell.
|
|
||||||
* Based on grp.c by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (defined PHYSFS_SUPPORTS_HOG)
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "physfs.h"
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* One HOGentry is kept for each file in an open HOG archive.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char name[13];
|
|
||||||
PHYSFS_uint32 startPos;
|
|
||||||
PHYSFS_uint32 size;
|
|
||||||
} HOGentry;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* One HOGinfo is kept for each open HOG archive.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
PHYSFS_sint64 last_mod_time;
|
|
||||||
PHYSFS_uint32 entryCount;
|
|
||||||
HOGentry *entries;
|
|
||||||
} HOGinfo;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* One HOGfileinfo is kept for each open file in a HOG archive.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
void *handle;
|
|
||||||
HOGentry *entry;
|
|
||||||
PHYSFS_uint32 curPos;
|
|
||||||
} HOGfileinfo;
|
|
||||||
|
|
||||||
|
|
||||||
static void HOG_dirClose(dvoid *opaque)
|
|
||||||
{
|
|
||||||
HOGinfo *info = ((HOGinfo *) opaque);
|
|
||||||
allocator.Free(info->filename);
|
|
||||||
allocator.Free(info->entries);
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* HOG_dirClose */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 HOG_read(fvoid *opaque, void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
|
||||||
HOGentry *entry = finfo->entry;
|
|
||||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
|
||||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
|
||||||
PHYSFS_sint64 rc;
|
|
||||||
|
|
||||||
if (objsLeft < objCount)
|
|
||||||
objCount = objsLeft;
|
|
||||||
|
|
||||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
|
||||||
if (rc > 0)
|
|
||||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* HOG_read */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 HOG_write(fvoid *opaque, const void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
|
||||||
} /* HOG_write */
|
|
||||||
|
|
||||||
|
|
||||||
static int HOG_eof(fvoid *opaque)
|
|
||||||
{
|
|
||||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
|
||||||
HOGentry *entry = finfo->entry;
|
|
||||||
return(finfo->curPos >= entry->size);
|
|
||||||
} /* HOG_eof */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 HOG_tell(fvoid *opaque)
|
|
||||||
{
|
|
||||||
return(((HOGfileinfo *) opaque)->curPos);
|
|
||||||
} /* HOG_tell */
|
|
||||||
|
|
||||||
|
|
||||||
static int HOG_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
|
||||||
{
|
|
||||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
|
||||||
HOGentry *entry = finfo->entry;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
|
||||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
|
||||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
|
||||||
if (rc)
|
|
||||||
finfo->curPos = (PHYSFS_uint32) offset;
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* HOG_seek */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 HOG_fileLength(fvoid *opaque)
|
|
||||||
{
|
|
||||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
|
||||||
return((PHYSFS_sint64) finfo->entry->size);
|
|
||||||
} /* HOG_fileLength */
|
|
||||||
|
|
||||||
|
|
||||||
static int HOG_fileClose(fvoid *opaque)
|
|
||||||
{
|
|
||||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
|
||||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
|
||||||
allocator.Free(finfo);
|
|
||||||
return(1);
|
|
||||||
} /* HOG_fileClose */
|
|
||||||
|
|
||||||
|
|
||||||
static int hog_open(const char *filename, int forWriting,
|
|
||||||
void **fh, PHYSFS_uint32 *count)
|
|
||||||
{
|
|
||||||
PHYSFS_uint8 buf[13];
|
|
||||||
PHYSFS_uint32 size;
|
|
||||||
PHYSFS_sint64 pos;
|
|
||||||
|
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
*fh = NULL;
|
|
||||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
|
||||||
|
|
||||||
*fh = __PHYSFS_platformOpenRead(filename);
|
|
||||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, buf, 3, 1) != 1)
|
|
||||||
goto openHog_failed;
|
|
||||||
|
|
||||||
if (memcmp(buf, "DHF", 3) != 0)
|
|
||||||
{
|
|
||||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
|
||||||
goto openHog_failed;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (__PHYSFS_platformRead(*fh, buf, 13, 1) != 1)
|
|
||||||
break; /* eof here is ok */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, &size, 4, 1) != 1)
|
|
||||||
goto openHog_failed;
|
|
||||||
|
|
||||||
size = PHYSFS_swapULE32(size);
|
|
||||||
|
|
||||||
(*count)++;
|
|
||||||
|
|
||||||
/* Skip over entry... */
|
|
||||||
pos = __PHYSFS_platformTell(*fh);
|
|
||||||
if (pos == -1)
|
|
||||||
goto openHog_failed;
|
|
||||||
if (!__PHYSFS_platformSeek(*fh, pos + size))
|
|
||||||
goto openHog_failed;
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
/* Rewind to start of entries... */
|
|
||||||
if (!__PHYSFS_platformSeek(*fh, 3))
|
|
||||||
goto openHog_failed;
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
|
|
||||||
openHog_failed:
|
|
||||||
if (*fh != NULL)
|
|
||||||
__PHYSFS_platformClose(*fh);
|
|
||||||
|
|
||||||
*count = -1;
|
|
||||||
*fh = NULL;
|
|
||||||
return(0);
|
|
||||||
} /* hog_open */
|
|
||||||
|
|
||||||
|
|
||||||
static int HOG_isArchive(const char *filename, int forWriting)
|
|
||||||
{
|
|
||||||
void *fh;
|
|
||||||
PHYSFS_uint32 fileCount;
|
|
||||||
int retval = hog_open(filename, forWriting, &fh, &fileCount);
|
|
||||||
|
|
||||||
if (fh != NULL)
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* HOG_isArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static int hog_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
if (one != two)
|
|
||||||
{
|
|
||||||
const HOGentry *a = (const HOGentry *) _a;
|
|
||||||
return(__PHYSFS_stricmpASCII(a[one].name, a[two].name));
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* hog_entry_cmp */
|
|
||||||
|
|
||||||
|
|
||||||
static void hog_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
if (one != two)
|
|
||||||
{
|
|
||||||
HOGentry tmp;
|
|
||||||
HOGentry *first = &(((HOGentry *) _a)[one]);
|
|
||||||
HOGentry *second = &(((HOGentry *) _a)[two]);
|
|
||||||
memcpy(&tmp, first, sizeof (HOGentry));
|
|
||||||
memcpy(first, second, sizeof (HOGentry));
|
|
||||||
memcpy(second, &tmp, sizeof (HOGentry));
|
|
||||||
} /* if */
|
|
||||||
} /* hog_entry_swap */
|
|
||||||
|
|
||||||
|
|
||||||
static int hog_load_entries(const char *name, int forWriting, HOGinfo *info)
|
|
||||||
{
|
|
||||||
void *fh = NULL;
|
|
||||||
PHYSFS_uint32 fileCount;
|
|
||||||
HOGentry *entry;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(!hog_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
|
||||||
info->entryCount = fileCount;
|
|
||||||
info->entries = (HOGentry *) allocator.Malloc(sizeof(HOGentry)*fileCount);
|
|
||||||
if (info->entries == NULL)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
|
||||||
{
|
|
||||||
if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
entry->size = PHYSFS_swapULE32(entry->size);
|
|
||||||
entry->startPos = (unsigned int) __PHYSFS_platformTell(fh);
|
|
||||||
if (entry->startPos == -1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip over entry */
|
|
||||||
if (!__PHYSFS_platformSeek(fh, entry->startPos + entry->size))
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
} /* for */
|
|
||||||
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
|
|
||||||
__PHYSFS_sort(info->entries, info->entryCount,
|
|
||||||
hog_entry_cmp, hog_entry_swap);
|
|
||||||
return(1);
|
|
||||||
} /* hog_load_entries */
|
|
||||||
|
|
||||||
|
|
||||||
static void *HOG_openArchive(const char *name, int forWriting)
|
|
||||||
{
|
|
||||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
|
||||||
HOGinfo *info = (HOGinfo *) allocator.Malloc(sizeof (HOGinfo));
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
||||||
memset(info, '\0', sizeof (HOGinfo));
|
|
||||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
|
||||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, HOG_openArchive_failed);
|
|
||||||
|
|
||||||
if (!hog_load_entries(name, forWriting, info))
|
|
||||||
goto HOG_openArchive_failed;
|
|
||||||
|
|
||||||
strcpy(info->filename, name);
|
|
||||||
info->last_mod_time = modtime;
|
|
||||||
|
|
||||||
return(info);
|
|
||||||
|
|
||||||
HOG_openArchive_failed:
|
|
||||||
if (info != NULL)
|
|
||||||
{
|
|
||||||
if (info->filename != NULL)
|
|
||||||
allocator.Free(info->filename);
|
|
||||||
if (info->entries != NULL)
|
|
||||||
allocator.Free(info->entries);
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return(NULL);
|
|
||||||
} /* HOG_openArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static void HOG_enumerateFiles(dvoid *opaque, const char *dname,
|
|
||||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
|
||||||
const char *origdir, void *callbackdata)
|
|
||||||
{
|
|
||||||
/* no directories in HOG files. */
|
|
||||||
if (*dname == '\0')
|
|
||||||
{
|
|
||||||
HOGinfo *info = (HOGinfo *) opaque;
|
|
||||||
HOGentry *entry = info->entries;
|
|
||||||
PHYSFS_uint32 max = info->entryCount;
|
|
||||||
PHYSFS_uint32 i;
|
|
||||||
|
|
||||||
for (i = 0; i < max; i++, entry++)
|
|
||||||
cb(callbackdata, origdir, entry->name);
|
|
||||||
} /* if */
|
|
||||||
} /* HOG_enumerateFiles */
|
|
||||||
|
|
||||||
|
|
||||||
static HOGentry *hog_find_entry(HOGinfo *info, const char *name)
|
|
||||||
{
|
|
||||||
char *ptr = strchr(name, '.');
|
|
||||||
HOGentry *a = info->entries;
|
|
||||||
PHYSFS_sint32 lo = 0;
|
|
||||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
|
||||||
PHYSFS_sint32 middle;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Rule out filenames to avoid unneeded processing...no dirs,
|
|
||||||
* big filenames, or extensions > 3 chars.
|
|
||||||
*/
|
|
||||||
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
|
|
||||||
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
|
|
||||||
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
|
|
||||||
|
|
||||||
while (lo <= hi)
|
|
||||||
{
|
|
||||||
middle = lo + ((hi - lo) / 2);
|
|
||||||
rc = __PHYSFS_stricmpASCII(name, a[middle].name);
|
|
||||||
if (rc == 0) /* found it! */
|
|
||||||
return(&a[middle]);
|
|
||||||
else if (rc > 0)
|
|
||||||
lo = middle + 1;
|
|
||||||
else
|
|
||||||
hi = middle - 1;
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
|
||||||
} /* hog_find_entry */
|
|
||||||
|
|
||||||
|
|
||||||
static int HOG_exists(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
return(hog_find_entry(((HOGinfo *) opaque), name) != NULL);
|
|
||||||
} /* HOG_exists */
|
|
||||||
|
|
||||||
|
|
||||||
static int HOG_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
*fileExists = HOG_exists(opaque, name);
|
|
||||||
return(0); /* never directories in a groupfile. */
|
|
||||||
} /* HOG_isDirectory */
|
|
||||||
|
|
||||||
|
|
||||||
static int HOG_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
*fileExists = HOG_exists(opaque, name);
|
|
||||||
return(0); /* never symlinks in a groupfile. */
|
|
||||||
} /* HOG_isSymLink */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 HOG_getLastModTime(dvoid *opaque,
|
|
||||||
const char *name,
|
|
||||||
int *fileExists)
|
|
||||||
{
|
|
||||||
HOGinfo *info = ((HOGinfo *) opaque);
|
|
||||||
PHYSFS_sint64 retval = -1;
|
|
||||||
|
|
||||||
*fileExists = (hog_find_entry(info, name) != NULL);
|
|
||||||
if (*fileExists) /* use time of HOG itself in the physical filesystem. */
|
|
||||||
retval = info->last_mod_time;
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* HOG_getLastModTime */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *HOG_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
|
||||||
{
|
|
||||||
HOGinfo *info = ((HOGinfo *) opaque);
|
|
||||||
HOGfileinfo *finfo;
|
|
||||||
HOGentry *entry;
|
|
||||||
|
|
||||||
entry = hog_find_entry(info, fnm);
|
|
||||||
*fileExists = (entry != NULL);
|
|
||||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
|
||||||
|
|
||||||
finfo = (HOGfileinfo *) allocator.Malloc(sizeof (HOGfileinfo));
|
|
||||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
|
|
||||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
|
||||||
if ( (finfo->handle == NULL) ||
|
|
||||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
|
||||||
{
|
|
||||||
allocator.Free(finfo);
|
|
||||||
return(NULL);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
finfo->curPos = 0;
|
|
||||||
finfo->entry = entry;
|
|
||||||
return(finfo);
|
|
||||||
} /* HOG_openRead */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *HOG_openWrite(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* HOG_openWrite */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *HOG_openAppend(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* HOG_openAppend */
|
|
||||||
|
|
||||||
|
|
||||||
static int HOG_remove(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* HOG_remove */
|
|
||||||
|
|
||||||
|
|
||||||
static int HOG_mkdir(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* HOG_mkdir */
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_HOG =
|
|
||||||
{
|
|
||||||
"HOG",
|
|
||||||
HOG_ARCHIVE_DESCRIPTION,
|
|
||||||
"Bradley Bell <btb@icculus.org>",
|
|
||||||
"http://icculus.org/physfs/",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
|
|
||||||
{
|
|
||||||
&__PHYSFS_ArchiveInfo_HOG,
|
|
||||||
HOG_isArchive, /* isArchive() method */
|
|
||||||
HOG_openArchive, /* openArchive() method */
|
|
||||||
HOG_enumerateFiles, /* enumerateFiles() method */
|
|
||||||
HOG_exists, /* exists() method */
|
|
||||||
HOG_isDirectory, /* isDirectory() method */
|
|
||||||
HOG_isSymLink, /* isSymLink() method */
|
|
||||||
HOG_getLastModTime, /* getLastModTime() method */
|
|
||||||
HOG_openRead, /* openRead() method */
|
|
||||||
HOG_openWrite, /* openWrite() method */
|
|
||||||
HOG_openAppend, /* openAppend() method */
|
|
||||||
HOG_remove, /* remove() method */
|
|
||||||
HOG_mkdir, /* mkdir() method */
|
|
||||||
HOG_dirClose, /* dirClose() method */
|
|
||||||
HOG_read, /* read() method */
|
|
||||||
HOG_write, /* write() method */
|
|
||||||
HOG_eof, /* eof() method */
|
|
||||||
HOG_tell, /* tell() method */
|
|
||||||
HOG_seek, /* seek() method */
|
|
||||||
HOG_fileLength, /* fileLength() method */
|
|
||||||
HOG_fileClose /* fileClose() method */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined PHYSFS_SUPPORTS_HOG */
|
|
||||||
|
|
||||||
/* end of hog.c ... */
|
|
||||||
|
|
||||||
@@ -1,736 +0,0 @@
|
|||||||
/*
|
|
||||||
* LZMA support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* Please see the file lzma.txt in the lzma/ directory.
|
|
||||||
*
|
|
||||||
* This file was written by Dennis Schridde, with some peeking at "7zMain.c"
|
|
||||||
* by Igor Pavlov.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (defined PHYSFS_SUPPORTS_7Z)
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "physfs.h"
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
#include "lzma/C/7zCrc.h"
|
|
||||||
#include "lzma/C/Archive/7z/7zIn.h"
|
|
||||||
#include "lzma/C/Archive/7z/7zExtract.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* 7z internal from 7zIn.c */
|
|
||||||
extern int TestSignatureCandidate(Byte *testBytes);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
# define BUFFER_SIZE (1 << 12)
|
|
||||||
#endif /* _LZMA_IN_CB */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Carries filestream metadata through 7z
|
|
||||||
*/
|
|
||||||
typedef struct _FileInputStream
|
|
||||||
{
|
|
||||||
ISzAlloc allocImp; /* Allocation implementation, used by 7z */
|
|
||||||
ISzAlloc allocTempImp; /* Temporary allocation implementation, used by 7z */
|
|
||||||
ISzInStream inStream; /* Input stream with read callbacks, used by 7z */
|
|
||||||
void *file; /* Filehandle, used by read implementation */
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
Byte buffer[BUFFER_SIZE]; /* Buffer, used by read implementation */
|
|
||||||
#endif /* _LZMA_IN_CB */
|
|
||||||
} FileInputStream;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* In the 7z format archives are splited into blocks, those are called folders
|
|
||||||
* Set by LZMA_read()
|
|
||||||
*/
|
|
||||||
typedef struct _LZMAfolder
|
|
||||||
{
|
|
||||||
PHYSFS_uint32 index; /* Index of folder in archive */
|
|
||||||
PHYSFS_uint32 references; /* Number of files using this block */
|
|
||||||
PHYSFS_uint8 *cache; /* Cached folder */
|
|
||||||
size_t size; /* Size of folder */
|
|
||||||
} LZMAfolder;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set by LZMA_openArchive(), except folder which gets it's values
|
|
||||||
* in LZMA_read()
|
|
||||||
*/
|
|
||||||
typedef struct _LZMAarchive
|
|
||||||
{
|
|
||||||
struct _LZMAfile *files; /* Array of files, size == archive->db.Database.NumFiles */
|
|
||||||
LZMAfolder *folders; /* Array of folders, size == archive->db.Database.NumFolders */
|
|
||||||
CArchiveDatabaseEx db; /* For 7z: Database */
|
|
||||||
FileInputStream stream; /* For 7z: Input file incl. read and seek callbacks */
|
|
||||||
} LZMAarchive;
|
|
||||||
|
|
||||||
/* Set by LZMA_openArchive(), except offset which is set by LZMA_read() */
|
|
||||||
typedef struct _LZMAfile
|
|
||||||
{
|
|
||||||
PHYSFS_uint32 index; /* Index of file in archive */
|
|
||||||
LZMAarchive *archive; /* Link to corresponding archive */
|
|
||||||
LZMAfolder *folder; /* Link to corresponding folder */
|
|
||||||
CFileItem *item; /* For 7z: File info, eg. name, size */
|
|
||||||
size_t offset; /* Offset in folder */
|
|
||||||
size_t position; /* Current "virtual" position in file */
|
|
||||||
} LZMAfile;
|
|
||||||
|
|
||||||
|
|
||||||
/* Memory management implementations to be passed to 7z */
|
|
||||||
|
|
||||||
static void *SzAllocPhysicsFS(size_t size)
|
|
||||||
{
|
|
||||||
return ((size == 0) ? NULL : allocator.Malloc(size));
|
|
||||||
} /* SzAllocPhysicsFS */
|
|
||||||
|
|
||||||
|
|
||||||
static void SzFreePhysicsFS(void *address)
|
|
||||||
{
|
|
||||||
if (address != NULL)
|
|
||||||
allocator.Free(address);
|
|
||||||
} /* SzFreePhysicsFS */
|
|
||||||
|
|
||||||
|
|
||||||
/* Filesystem implementations to be passed to 7z */
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read implementation, to be passed to 7z
|
|
||||||
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
|
|
||||||
*/
|
|
||||||
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxReqSize,
|
|
||||||
size_t *processedSize)
|
|
||||||
{
|
|
||||||
FileInputStream *s = (FileInputStream *)(object - offsetof(FileInputStream, inStream)); /* HACK! */
|
|
||||||
PHYSFS_sint64 processedSizeLoc = 0;
|
|
||||||
|
|
||||||
if (maxReqSize > BUFFER_SIZE)
|
|
||||||
maxReqSize = BUFFER_SIZE;
|
|
||||||
processedSizeLoc = __PHYSFS_platformRead(s->file, s->buffer, 1, maxReqSize);
|
|
||||||
*buffer = s->buffer;
|
|
||||||
if (processedSize != NULL)
|
|
||||||
*processedSize = (size_t) processedSizeLoc;
|
|
||||||
|
|
||||||
return SZ_OK;
|
|
||||||
} /* SzFileReadImp */
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read implementation, to be passed to 7z
|
|
||||||
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
|
|
||||||
*/
|
|
||||||
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size,
|
|
||||||
size_t *processedSize)
|
|
||||||
{
|
|
||||||
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
|
|
||||||
size_t processedSizeLoc = __PHYSFS_platformRead(s->file, buffer, 1, size);
|
|
||||||
if (processedSize != 0)
|
|
||||||
*processedSize = processedSizeLoc;
|
|
||||||
return SZ_OK;
|
|
||||||
} /* SzFileReadImp */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Seek implementation, to be passed to 7z
|
|
||||||
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
|
|
||||||
*/
|
|
||||||
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
|
|
||||||
{
|
|
||||||
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
|
|
||||||
if (__PHYSFS_platformSeek(s->file, (PHYSFS_uint64) pos))
|
|
||||||
return SZ_OK;
|
|
||||||
return SZE_FAIL;
|
|
||||||
} /* SzFileSeekImp */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Translate Microsoft FILETIME (used by 7zip) into UNIX timestamp
|
|
||||||
*/
|
|
||||||
static PHYSFS_sint64 lzma_filetime_to_unix_timestamp(CArchiveFileTime *ft)
|
|
||||||
{
|
|
||||||
/* MS counts in nanoseconds ... */
|
|
||||||
const PHYSFS_uint64 FILETIME_NANOTICKS_PER_SECOND = __PHYSFS_UI64(10000000);
|
|
||||||
/* MS likes to count seconds since 01.01.1601 ... */
|
|
||||||
const PHYSFS_uint64 FILETIME_UNIX_DIFF = __PHYSFS_UI64(11644473600);
|
|
||||||
|
|
||||||
PHYSFS_uint64 filetime = ft->Low | ((PHYSFS_uint64)ft->High << 32);
|
|
||||||
return filetime/FILETIME_NANOTICKS_PER_SECOND - FILETIME_UNIX_DIFF;
|
|
||||||
} /* lzma_filetime_to_unix_timestamp */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compare a file with a given name, C89 stdlib variant
|
|
||||||
* Used for sorting
|
|
||||||
*/
|
|
||||||
static int lzma_file_cmp_stdlib(const void *key, const void *object)
|
|
||||||
{
|
|
||||||
const char *name = (const char *) key;
|
|
||||||
LZMAfile *file = (LZMAfile *) object;
|
|
||||||
return(strcmp(name, file->item->Name));
|
|
||||||
} /* lzma_file_cmp_posix */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compare two files with each other based on the name
|
|
||||||
* Used for sorting
|
|
||||||
*/
|
|
||||||
static int lzma_file_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
LZMAfile *files = (LZMAfile *) _a;
|
|
||||||
return(strcmp(files[one].item->Name, files[two].item->Name));
|
|
||||||
} /* lzma_file_cmp */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Swap two entries in the file array
|
|
||||||
*/
|
|
||||||
static void lzma_file_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
LZMAfile tmp;
|
|
||||||
LZMAfile *first = &(((LZMAfile *) _a)[one]);
|
|
||||||
LZMAfile *second = &(((LZMAfile *) _a)[two]);
|
|
||||||
memcpy(&tmp, first, sizeof (LZMAfile));
|
|
||||||
memcpy(first, second, sizeof (LZMAfile));
|
|
||||||
memcpy(second, &tmp, sizeof (LZMAfile));
|
|
||||||
} /* lzma_file_swap */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find entry 'name' in 'archive'
|
|
||||||
*/
|
|
||||||
static LZMAfile * lzma_find_file(LZMAarchive *archive, const char *name)
|
|
||||||
{
|
|
||||||
LZMAfile *file = bsearch(name, archive->files, archive->db.Database.NumFiles, sizeof(*archive->files), lzma_file_cmp_stdlib); /* FIXME: Should become __PHYSFS_search!!! */
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, NULL);
|
|
||||||
|
|
||||||
return(file);
|
|
||||||
} /* lzma_find_file */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Load metadata for the file at given index
|
|
||||||
*/
|
|
||||||
static int lzma_file_init(LZMAarchive *archive, PHYSFS_uint32 fileIndex)
|
|
||||||
{
|
|
||||||
LZMAfile *file = &archive->files[fileIndex];
|
|
||||||
PHYSFS_uint32 folderIndex = archive->db.FileIndexToFolderIndexMap[fileIndex];
|
|
||||||
|
|
||||||
file->index = fileIndex; /* Store index into 7z array, since we sort our own. */
|
|
||||||
file->archive = archive;
|
|
||||||
file->folder = (folderIndex != (PHYSFS_uint32)-1 ? &archive->folders[folderIndex] : NULL); /* Directories don't have a folder (they contain no own data...) */
|
|
||||||
file->item = &archive->db.Database.Files[fileIndex]; /* Holds crucial data and is often referenced -> Store link */
|
|
||||||
file->position = 0;
|
|
||||||
file->offset = 0; /* Offset will be set by LZMA_read() */
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
} /* lzma_load_file */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Load metadata for all files
|
|
||||||
*/
|
|
||||||
static int lzma_files_init(LZMAarchive *archive)
|
|
||||||
{
|
|
||||||
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
|
|
||||||
|
|
||||||
for (fileIndex = 0; fileIndex < numFiles; fileIndex++ )
|
|
||||||
{
|
|
||||||
if (!lzma_file_init(archive, fileIndex))
|
|
||||||
{
|
|
||||||
return(0); /* FALSE on failure */
|
|
||||||
}
|
|
||||||
} /* for */
|
|
||||||
|
|
||||||
__PHYSFS_sort(archive->files, numFiles, lzma_file_cmp, lzma_file_swap);
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
} /* lzma_load_files */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialise specified archive
|
|
||||||
*/
|
|
||||||
static void lzma_archive_init(LZMAarchive *archive)
|
|
||||||
{
|
|
||||||
memset(archive, 0, sizeof(*archive));
|
|
||||||
|
|
||||||
/* Prepare callbacks for 7z */
|
|
||||||
archive->stream.inStream.Read = SzFileReadImp;
|
|
||||||
archive->stream.inStream.Seek = SzFileSeekImp;
|
|
||||||
|
|
||||||
archive->stream.allocImp.Alloc = SzAllocPhysicsFS;
|
|
||||||
archive->stream.allocImp.Free = SzFreePhysicsFS;
|
|
||||||
|
|
||||||
archive->stream.allocTempImp.Alloc = SzAllocPhysicsFS;
|
|
||||||
archive->stream.allocTempImp.Free = SzFreePhysicsFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Deinitialise archive
|
|
||||||
*/
|
|
||||||
static void lzma_archive_exit(LZMAarchive *archive)
|
|
||||||
{
|
|
||||||
/* Free arrays */
|
|
||||||
allocator.Free(archive->folders);
|
|
||||||
allocator.Free(archive->files);
|
|
||||||
allocator.Free(archive);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wrap all 7z calls in this, so the physfs error state is set appropriately.
|
|
||||||
*/
|
|
||||||
static int lzma_err(SZ_RESULT rc)
|
|
||||||
{
|
|
||||||
switch (rc)
|
|
||||||
{
|
|
||||||
case SZ_OK: /* Same as LZMA_RESULT_OK */
|
|
||||||
break;
|
|
||||||
case SZE_DATA_ERROR: /* Same as LZMA_RESULT_DATA_ERROR */
|
|
||||||
__PHYSFS_setError(ERR_DATA_ERROR);
|
|
||||||
break;
|
|
||||||
case SZE_OUTOFMEMORY:
|
|
||||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
|
||||||
break;
|
|
||||||
case SZE_CRC_ERROR:
|
|
||||||
__PHYSFS_setError(ERR_CORRUPTED);
|
|
||||||
break;
|
|
||||||
case SZE_NOTIMPL:
|
|
||||||
__PHYSFS_setError(ERR_NOT_IMPLEMENTED);
|
|
||||||
break;
|
|
||||||
case SZE_FAIL:
|
|
||||||
__PHYSFS_setError(ERR_UNKNOWN_ERROR); /* !!! FIXME: right? */
|
|
||||||
break;
|
|
||||||
case SZE_ARCHIVE_ERROR:
|
|
||||||
__PHYSFS_setError(ERR_CORRUPTED); /* !!! FIXME: right? */
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
__PHYSFS_setError(ERR_UNKNOWN_ERROR);
|
|
||||||
} /* switch */
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* lzma_err */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
LZMAfile *file = (LZMAfile *) opaque;
|
|
||||||
|
|
||||||
size_t wantedSize = objSize*objCount;
|
|
||||||
size_t remainingSize = file->item->Size - file->position;
|
|
||||||
size_t fileSize = 0;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(wantedSize == 0, NULL, 0); /* quick rejection. */
|
|
||||||
BAIL_IF_MACRO(remainingSize == 0, ERR_PAST_EOF, 0);
|
|
||||||
|
|
||||||
if (remainingSize < wantedSize)
|
|
||||||
{
|
|
||||||
wantedSize = remainingSize - (remainingSize % objSize);
|
|
||||||
objCount = (PHYSFS_uint32) (remainingSize / objSize);
|
|
||||||
BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */
|
|
||||||
__PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
/* Only decompress the folder if it is not allready cached */
|
|
||||||
if (file->folder->cache == NULL)
|
|
||||||
{
|
|
||||||
int rc = lzma_err(SzExtract(
|
|
||||||
&file->archive->stream.inStream, /* compressed data */
|
|
||||||
&file->archive->db, /* 7z's database, containing everything */
|
|
||||||
file->index, /* Index into database arrays */
|
|
||||||
/* Index of cached folder, will be changed by SzExtract */
|
|
||||||
&file->folder->index,
|
|
||||||
/* Cache for decompressed folder, allocated/freed by SzExtract */
|
|
||||||
&file->folder->cache,
|
|
||||||
/* Size of cache, will be changed by SzExtract */
|
|
||||||
&file->folder->size,
|
|
||||||
/* Offset of this file inside the cache, set by SzExtract */
|
|
||||||
&file->offset,
|
|
||||||
&fileSize, /* Size of this file */
|
|
||||||
&file->archive->stream.allocImp,
|
|
||||||
&file->archive->stream.allocTempImp));
|
|
||||||
|
|
||||||
if (rc != SZ_OK)
|
|
||||||
return -1;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
/* Copy wanted bytes over from cache to outBuffer */
|
|
||||||
memcpy(outBuffer,
|
|
||||||
(file->folder->cache +
|
|
||||||
file->offset + file->position),
|
|
||||||
wantedSize);
|
|
||||||
file->position += wantedSize; /* Increase virtual position */
|
|
||||||
|
|
||||||
return objCount;
|
|
||||||
} /* LZMA_read */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 LZMA_write(fvoid *opaque, const void *buf,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
|
||||||
} /* LZMA_write */
|
|
||||||
|
|
||||||
|
|
||||||
static int LZMA_eof(fvoid *opaque)
|
|
||||||
{
|
|
||||||
LZMAfile *file = (LZMAfile *) opaque;
|
|
||||||
return (file->position >= file->item->Size);
|
|
||||||
} /* LZMA_eof */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 LZMA_tell(fvoid *opaque)
|
|
||||||
{
|
|
||||||
LZMAfile *file = (LZMAfile *) opaque;
|
|
||||||
return (file->position);
|
|
||||||
} /* LZMA_tell */
|
|
||||||
|
|
||||||
|
|
||||||
static int LZMA_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
|
||||||
{
|
|
||||||
LZMAfile *file = (LZMAfile *) opaque;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(offset < 0, ERR_SEEK_OUT_OF_RANGE, 0);
|
|
||||||
BAIL_IF_MACRO(offset > file->item->Size, ERR_PAST_EOF, 0);
|
|
||||||
|
|
||||||
file->position = offset; /* We only use a virtual position... */
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
} /* LZMA_seek */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 LZMA_fileLength(fvoid *opaque)
|
|
||||||
{
|
|
||||||
LZMAfile *file = (LZMAfile *) opaque;
|
|
||||||
return (file->item->Size);
|
|
||||||
} /* LZMA_fileLength */
|
|
||||||
|
|
||||||
|
|
||||||
static int LZMA_fileClose(fvoid *opaque)
|
|
||||||
{
|
|
||||||
LZMAfile *file = (LZMAfile *) opaque;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(file->folder == NULL, ERR_NOT_A_FILE, 0);
|
|
||||||
|
|
||||||
/* Only decrease refcount if someone actually requested this file... Prevents from overflows and close-on-open... */
|
|
||||||
if (file->folder->references > 0)
|
|
||||||
file->folder->references--;
|
|
||||||
if (file->folder->references == 0)
|
|
||||||
{
|
|
||||||
/* Free the cache which might have been allocated by LZMA_read() */
|
|
||||||
allocator.Free(file->folder->cache);
|
|
||||||
file->folder->cache = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
} /* LZMA_fileClose */
|
|
||||||
|
|
||||||
|
|
||||||
static int LZMA_isArchive(const char *filename, int forWriting)
|
|
||||||
{
|
|
||||||
PHYSFS_uint8 sig[k7zSignatureSize];
|
|
||||||
void *in;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
|
||||||
|
|
||||||
in = __PHYSFS_platformOpenRead(filename);
|
|
||||||
BAIL_IF_MACRO(in == NULL, NULL, 0);
|
|
||||||
|
|
||||||
/* Read signature bytes */
|
|
||||||
if (__PHYSFS_platformRead(in, sig, k7zSignatureSize, 1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(in); /* Don't forget to close the file before returning... */
|
|
||||||
BAIL_MACRO(NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
__PHYSFS_platformClose(in);
|
|
||||||
|
|
||||||
/* Test whether sig is the 7z signature */
|
|
||||||
return(TestSignatureCandidate(sig));
|
|
||||||
} /* LZMA_isArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static void *LZMA_openArchive(const char *name, int forWriting)
|
|
||||||
{
|
|
||||||
size_t len = 0;
|
|
||||||
LZMAarchive *archive = NULL;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
|
|
||||||
BAIL_IF_MACRO(!LZMA_isArchive(name,forWriting), ERR_UNSUPPORTED_ARCHIVE, 0);
|
|
||||||
|
|
||||||
archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
|
|
||||||
BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
|
|
||||||
lzma_archive_init(archive);
|
|
||||||
|
|
||||||
if ( (archive->stream.file = __PHYSFS_platformOpenRead(name)) == NULL )
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(archive->stream.file);
|
|
||||||
lzma_archive_exit(archive);
|
|
||||||
return(NULL); /* Error is set by platformOpenRead! */
|
|
||||||
}
|
|
||||||
|
|
||||||
CrcGenerateTable();
|
|
||||||
SzArDbExInit(&archive->db);
|
|
||||||
if (lzma_err(SzArchiveOpen(&archive->stream.inStream,
|
|
||||||
&archive->db,
|
|
||||||
&archive->stream.allocImp,
|
|
||||||
&archive->stream.allocTempImp)) != SZ_OK)
|
|
||||||
{
|
|
||||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
|
||||||
__PHYSFS_platformClose(archive->stream.file);
|
|
||||||
lzma_archive_exit(archive);
|
|
||||||
return NULL; /* Error is set by lzma_err! */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
len = archive->db.Database.NumFiles * sizeof (LZMAfile);
|
|
||||||
archive->files = (LZMAfile *) allocator.Malloc(len);
|
|
||||||
if (archive->files == NULL)
|
|
||||||
{
|
|
||||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
|
||||||
__PHYSFS_platformClose(archive->stream.file);
|
|
||||||
lzma_archive_exit(archive);
|
|
||||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Init with 0 so we know when a folder is already cached
|
|
||||||
* Values will be set by LZMA_openRead()
|
|
||||||
*/
|
|
||||||
memset(archive->files, 0, len);
|
|
||||||
|
|
||||||
len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
|
|
||||||
archive->folders = (LZMAfolder *) allocator.Malloc(len);
|
|
||||||
if (archive->folders == NULL)
|
|
||||||
{
|
|
||||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
|
||||||
__PHYSFS_platformClose(archive->stream.file);
|
|
||||||
lzma_archive_exit(archive);
|
|
||||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Init with 0 so we know when a folder is already cached
|
|
||||||
* Values will be set by LZMA_read()
|
|
||||||
*/
|
|
||||||
memset(archive->folders, 0, len);
|
|
||||||
|
|
||||||
if(!lzma_files_init(archive))
|
|
||||||
{
|
|
||||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
|
||||||
__PHYSFS_platformClose(archive->stream.file);
|
|
||||||
lzma_archive_exit(archive);
|
|
||||||
BAIL_MACRO(ERR_UNKNOWN_ERROR, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(archive);
|
|
||||||
} /* LZMA_openArchive */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Moved to seperate function so we can use alloca then immediately throw
|
|
||||||
* away the allocated stack space...
|
|
||||||
*/
|
|
||||||
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
|
||||||
const char *odir, const char *str, size_t flen)
|
|
||||||
{
|
|
||||||
char *newstr = __PHYSFS_smallAlloc(flen + 1);
|
|
||||||
if (newstr == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
memcpy(newstr, str, flen);
|
|
||||||
newstr[flen] = '\0';
|
|
||||||
cb(callbackdata, odir, newstr);
|
|
||||||
__PHYSFS_smallFree(newstr);
|
|
||||||
} /* doEnumCallback */
|
|
||||||
|
|
||||||
|
|
||||||
static void LZMA_enumerateFiles(dvoid *opaque, const char *dname,
|
|
||||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
|
||||||
const char *origdir, void *callbackdata)
|
|
||||||
{
|
|
||||||
size_t dlen = strlen(dname),
|
|
||||||
dlen_inc = dlen + ((dlen > 0) ? 1 : 0);
|
|
||||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
|
||||||
LZMAfile *file = NULL,
|
|
||||||
*lastFile = &archive->files[archive->db.Database.NumFiles];
|
|
||||||
if (dlen)
|
|
||||||
{
|
|
||||||
file = lzma_find_file(archive, dname);
|
|
||||||
if (file != NULL) /* if 'file' is NULL it should stay so, otherwise errors will not be handled */
|
|
||||||
file += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file = archive->files;
|
|
||||||
}
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, );
|
|
||||||
|
|
||||||
while (file < lastFile)
|
|
||||||
{
|
|
||||||
const char * fname = file->item->Name;
|
|
||||||
const char * dirNameEnd = fname + dlen_inc;
|
|
||||||
|
|
||||||
if (strncmp(dname, fname, dlen) != 0) /* Stop after mismatch, archive->files is sorted */
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (strchr(dirNameEnd, '/')) /* Skip subdirs */
|
|
||||||
{
|
|
||||||
file++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do the actual callback... */
|
|
||||||
doEnumCallback(cb, callbackdata, origdir, dirNameEnd, strlen(dirNameEnd));
|
|
||||||
|
|
||||||
file++;
|
|
||||||
}
|
|
||||||
} /* LZMA_enumerateFiles */
|
|
||||||
|
|
||||||
|
|
||||||
static int LZMA_exists(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
|
||||||
return(lzma_find_file(archive, name) != NULL);
|
|
||||||
} /* LZMA_exists */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 LZMA_getLastModTime(dvoid *opaque,
|
|
||||||
const char *name,
|
|
||||||
int *fileExists)
|
|
||||||
{
|
|
||||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
|
||||||
LZMAfile *file = lzma_find_file(archive, name);
|
|
||||||
|
|
||||||
*fileExists = (file != NULL);
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(file == NULL, NULL, -1);
|
|
||||||
BAIL_IF_MACRO(!file->item->IsLastWriteTimeDefined, NULL, -1); /* write-time may not be defined for every file */
|
|
||||||
|
|
||||||
return(lzma_filetime_to_unix_timestamp(&file->item->LastWriteTime));
|
|
||||||
} /* LZMA_getLastModTime */
|
|
||||||
|
|
||||||
|
|
||||||
static int LZMA_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
|
||||||
LZMAfile *file = lzma_find_file(archive, name);
|
|
||||||
|
|
||||||
*fileExists = (file != NULL);
|
|
||||||
|
|
||||||
return(file == NULL ? 0 : file->item->IsDirectory);
|
|
||||||
} /* LZMA_isDirectory */
|
|
||||||
|
|
||||||
|
|
||||||
static int LZMA_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* LZMA_isSymLink */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *LZMA_openRead(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
|
||||||
LZMAfile *file = lzma_find_file(archive, name);
|
|
||||||
|
|
||||||
*fileExists = (file != NULL);
|
|
||||||
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, NULL);
|
|
||||||
BAIL_IF_MACRO(file->folder == NULL, ERR_NOT_A_FILE, NULL);
|
|
||||||
|
|
||||||
file->position = 0;
|
|
||||||
file->folder->references++; /* Increase refcount for automatic cleanup... */
|
|
||||||
|
|
||||||
return(file);
|
|
||||||
} /* LZMA_openRead */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *LZMA_openWrite(dvoid *opaque, const char *filename)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* LZMA_openWrite */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *LZMA_openAppend(dvoid *opaque, const char *filename)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* LZMA_openAppend */
|
|
||||||
|
|
||||||
|
|
||||||
static void LZMA_dirClose(dvoid *opaque)
|
|
||||||
{
|
|
||||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
|
||||||
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
|
|
||||||
|
|
||||||
for (fileIndex = 0; fileIndex < numFiles; fileIndex++)
|
|
||||||
{
|
|
||||||
LZMA_fileClose(&archive->files[fileIndex]);
|
|
||||||
} /* for */
|
|
||||||
|
|
||||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
|
||||||
__PHYSFS_platformClose(archive->stream.file);
|
|
||||||
lzma_archive_exit(archive);
|
|
||||||
} /* LZMA_dirClose */
|
|
||||||
|
|
||||||
|
|
||||||
static int LZMA_remove(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* LZMA_remove */
|
|
||||||
|
|
||||||
|
|
||||||
static int LZMA_mkdir(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* LZMA_mkdir */
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_LZMA =
|
|
||||||
{
|
|
||||||
"7Z",
|
|
||||||
LZMA_ARCHIVE_DESCRIPTION,
|
|
||||||
"Dennis Schridde <devurandom@gmx.net>",
|
|
||||||
"http://icculus.org/physfs/",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
|
|
||||||
{
|
|
||||||
&__PHYSFS_ArchiveInfo_LZMA,
|
|
||||||
LZMA_isArchive, /* isArchive() method */
|
|
||||||
LZMA_openArchive, /* openArchive() method */
|
|
||||||
LZMA_enumerateFiles, /* enumerateFiles() method */
|
|
||||||
LZMA_exists, /* exists() method */
|
|
||||||
LZMA_isDirectory, /* isDirectory() method */
|
|
||||||
LZMA_isSymLink, /* isSymLink() method */
|
|
||||||
LZMA_getLastModTime, /* getLastModTime() method */
|
|
||||||
LZMA_openRead, /* openRead() method */
|
|
||||||
LZMA_openWrite, /* openWrite() method */
|
|
||||||
LZMA_openAppend, /* openAppend() method */
|
|
||||||
LZMA_remove, /* remove() method */
|
|
||||||
LZMA_mkdir, /* mkdir() method */
|
|
||||||
LZMA_dirClose, /* dirClose() method */
|
|
||||||
LZMA_read, /* read() method */
|
|
||||||
LZMA_write, /* write() method */
|
|
||||||
LZMA_eof, /* eof() method */
|
|
||||||
LZMA_tell, /* tell() method */
|
|
||||||
LZMA_seek, /* seek() method */
|
|
||||||
LZMA_fileLength, /* fileLength() method */
|
|
||||||
LZMA_fileClose /* fileClose() method */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined PHYSFS_SUPPORTS_7Z */
|
|
||||||
|
|
||||||
/* end of lzma.c ... */
|
|
||||||
|
|
||||||
@@ -1,471 +0,0 @@
|
|||||||
/*
|
|
||||||
* MVL support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* This driver handles Descent II Movielib archives.
|
|
||||||
*
|
|
||||||
* The file format of MVL is quite easy...
|
|
||||||
*
|
|
||||||
* //MVL File format - Written by Heiko Herrmann
|
|
||||||
* char sig[4] = {'D','M', 'V', 'L'}; // "DMVL"=Descent MoVie Library
|
|
||||||
*
|
|
||||||
* int num_files; // the number of files in this MVL
|
|
||||||
*
|
|
||||||
* struct {
|
|
||||||
* char file_name[13]; // Filename, padded to 13 bytes with 0s
|
|
||||||
* int file_size; // filesize in bytes
|
|
||||||
* }DIR_STRUCT[num_files];
|
|
||||||
*
|
|
||||||
* struct {
|
|
||||||
* char data[file_size]; // The file data
|
|
||||||
* }FILE_STRUCT[num_files];
|
|
||||||
*
|
|
||||||
* (That info is from http://www.descent2.com/ddn/specs/mvl/)
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Bradley Bell.
|
|
||||||
* Based on grp.c by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (defined PHYSFS_SUPPORTS_MVL)
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "physfs.h"
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char name[13];
|
|
||||||
PHYSFS_uint32 startPos;
|
|
||||||
PHYSFS_uint32 size;
|
|
||||||
} MVLentry;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
PHYSFS_sint64 last_mod_time;
|
|
||||||
PHYSFS_uint32 entryCount;
|
|
||||||
MVLentry *entries;
|
|
||||||
} MVLinfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
void *handle;
|
|
||||||
MVLentry *entry;
|
|
||||||
PHYSFS_uint32 curPos;
|
|
||||||
} MVLfileinfo;
|
|
||||||
|
|
||||||
|
|
||||||
static void MVL_dirClose(dvoid *opaque)
|
|
||||||
{
|
|
||||||
MVLinfo *info = ((MVLinfo *) opaque);
|
|
||||||
allocator.Free(info->filename);
|
|
||||||
allocator.Free(info->entries);
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* MVL_dirClose */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 MVL_read(fvoid *opaque, void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
|
||||||
MVLentry *entry = finfo->entry;
|
|
||||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
|
||||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
|
||||||
PHYSFS_sint64 rc;
|
|
||||||
|
|
||||||
if (objsLeft < objCount)
|
|
||||||
objCount = objsLeft;
|
|
||||||
|
|
||||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
|
||||||
if (rc > 0)
|
|
||||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* MVL_read */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 MVL_write(fvoid *opaque, const void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
|
||||||
} /* MVL_write */
|
|
||||||
|
|
||||||
|
|
||||||
static int MVL_eof(fvoid *opaque)
|
|
||||||
{
|
|
||||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
|
||||||
MVLentry *entry = finfo->entry;
|
|
||||||
return(finfo->curPos >= entry->size);
|
|
||||||
} /* MVL_eof */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 MVL_tell(fvoid *opaque)
|
|
||||||
{
|
|
||||||
return(((MVLfileinfo *) opaque)->curPos);
|
|
||||||
} /* MVL_tell */
|
|
||||||
|
|
||||||
|
|
||||||
static int MVL_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
|
||||||
{
|
|
||||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
|
||||||
MVLentry *entry = finfo->entry;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
|
||||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
|
||||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
|
||||||
if (rc)
|
|
||||||
finfo->curPos = (PHYSFS_uint32) offset;
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* MVL_seek */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 MVL_fileLength(fvoid *opaque)
|
|
||||||
{
|
|
||||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
|
||||||
return((PHYSFS_sint64) finfo->entry->size);
|
|
||||||
} /* MVL_fileLength */
|
|
||||||
|
|
||||||
|
|
||||||
static int MVL_fileClose(fvoid *opaque)
|
|
||||||
{
|
|
||||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
|
||||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
|
||||||
allocator.Free(finfo);
|
|
||||||
return(1);
|
|
||||||
} /* MVL_fileClose */
|
|
||||||
|
|
||||||
|
|
||||||
static int mvl_open(const char *filename, int forWriting,
|
|
||||||
void **fh, PHYSFS_uint32 *count)
|
|
||||||
{
|
|
||||||
PHYSFS_uint8 buf[4];
|
|
||||||
|
|
||||||
*fh = NULL;
|
|
||||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
|
||||||
|
|
||||||
*fh = __PHYSFS_platformOpenRead(filename);
|
|
||||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
|
|
||||||
goto openMvl_failed;
|
|
||||||
|
|
||||||
if (memcmp(buf, "DMVL", 4) != 0)
|
|
||||||
{
|
|
||||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
|
||||||
goto openMvl_failed;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
|
||||||
goto openMvl_failed;
|
|
||||||
|
|
||||||
*count = PHYSFS_swapULE32(*count);
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
|
|
||||||
openMvl_failed:
|
|
||||||
if (*fh != NULL)
|
|
||||||
__PHYSFS_platformClose(*fh);
|
|
||||||
|
|
||||||
*count = -1;
|
|
||||||
*fh = NULL;
|
|
||||||
return(0);
|
|
||||||
} /* mvl_open */
|
|
||||||
|
|
||||||
|
|
||||||
static int MVL_isArchive(const char *filename, int forWriting)
|
|
||||||
{
|
|
||||||
void *fh;
|
|
||||||
PHYSFS_uint32 fileCount;
|
|
||||||
int retval = mvl_open(filename, forWriting, &fh, &fileCount);
|
|
||||||
|
|
||||||
if (fh != NULL)
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* MVL_isArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static int mvl_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
if (one != two)
|
|
||||||
{
|
|
||||||
const MVLentry *a = (const MVLentry *) _a;
|
|
||||||
return(strcmp(a[one].name, a[two].name));
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* mvl_entry_cmp */
|
|
||||||
|
|
||||||
|
|
||||||
static void mvl_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
if (one != two)
|
|
||||||
{
|
|
||||||
MVLentry tmp;
|
|
||||||
MVLentry *first = &(((MVLentry *) _a)[one]);
|
|
||||||
MVLentry *second = &(((MVLentry *) _a)[two]);
|
|
||||||
memcpy(&tmp, first, sizeof (MVLentry));
|
|
||||||
memcpy(first, second, sizeof (MVLentry));
|
|
||||||
memcpy(second, &tmp, sizeof (MVLentry));
|
|
||||||
} /* if */
|
|
||||||
} /* mvl_entry_swap */
|
|
||||||
|
|
||||||
|
|
||||||
static int mvl_load_entries(const char *name, int forWriting, MVLinfo *info)
|
|
||||||
{
|
|
||||||
void *fh = NULL;
|
|
||||||
PHYSFS_uint32 fileCount;
|
|
||||||
PHYSFS_uint32 location = 8; /* sizeof sig. */
|
|
||||||
MVLentry *entry;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(!mvl_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
|
||||||
info->entryCount = fileCount;
|
|
||||||
info->entries = (MVLentry *) allocator.Malloc(sizeof(MVLentry)*fileCount);
|
|
||||||
if (info->entries == NULL)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
location += (17 * fileCount);
|
|
||||||
|
|
||||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
|
||||||
{
|
|
||||||
if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
entry->size = PHYSFS_swapULE32(entry->size);
|
|
||||||
entry->startPos = location;
|
|
||||||
location += entry->size;
|
|
||||||
} /* for */
|
|
||||||
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
|
|
||||||
__PHYSFS_sort(info->entries, info->entryCount,
|
|
||||||
mvl_entry_cmp, mvl_entry_swap);
|
|
||||||
return(1);
|
|
||||||
} /* mvl_load_entries */
|
|
||||||
|
|
||||||
|
|
||||||
static void *MVL_openArchive(const char *name, int forWriting)
|
|
||||||
{
|
|
||||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
|
||||||
MVLinfo *info = (MVLinfo *) allocator.Malloc(sizeof (MVLinfo));
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
memset(info, '\0', sizeof (MVLinfo));
|
|
||||||
|
|
||||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
|
||||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, MVL_openArchive_failed);
|
|
||||||
if (!mvl_load_entries(name, forWriting, info))
|
|
||||||
goto MVL_openArchive_failed;
|
|
||||||
|
|
||||||
strcpy(info->filename, name);
|
|
||||||
info->last_mod_time = modtime;
|
|
||||||
return(info);
|
|
||||||
|
|
||||||
MVL_openArchive_failed:
|
|
||||||
if (info != NULL)
|
|
||||||
{
|
|
||||||
if (info->filename != NULL)
|
|
||||||
allocator.Free(info->filename);
|
|
||||||
if (info->entries != NULL)
|
|
||||||
allocator.Free(info->entries);
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return(NULL);
|
|
||||||
} /* MVL_openArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static void MVL_enumerateFiles(dvoid *opaque, const char *dname,
|
|
||||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
|
||||||
const char *origdir, void *callbackdata)
|
|
||||||
{
|
|
||||||
/* no directories in MVL files. */
|
|
||||||
if (*dname == '\0')
|
|
||||||
{
|
|
||||||
MVLinfo *info = ((MVLinfo *) opaque);
|
|
||||||
MVLentry *entry = info->entries;
|
|
||||||
PHYSFS_uint32 max = info->entryCount;
|
|
||||||
PHYSFS_uint32 i;
|
|
||||||
|
|
||||||
for (i = 0; i < max; i++, entry++)
|
|
||||||
cb(callbackdata, origdir, entry->name);
|
|
||||||
} /* if */
|
|
||||||
} /* MVL_enumerateFiles */
|
|
||||||
|
|
||||||
|
|
||||||
static MVLentry *mvl_find_entry(MVLinfo *info, const char *name)
|
|
||||||
{
|
|
||||||
char *ptr = strchr(name, '.');
|
|
||||||
MVLentry *a = info->entries;
|
|
||||||
PHYSFS_sint32 lo = 0;
|
|
||||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
|
||||||
PHYSFS_sint32 middle;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Rule out filenames to avoid unneeded processing...no dirs,
|
|
||||||
* big filenames, or extensions > 3 chars.
|
|
||||||
*/
|
|
||||||
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
|
|
||||||
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
|
|
||||||
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
|
|
||||||
|
|
||||||
while (lo <= hi)
|
|
||||||
{
|
|
||||||
middle = lo + ((hi - lo) / 2);
|
|
||||||
rc = __PHYSFS_stricmpASCII(name, a[middle].name);
|
|
||||||
if (rc == 0) /* found it! */
|
|
||||||
return(&a[middle]);
|
|
||||||
else if (rc > 0)
|
|
||||||
lo = middle + 1;
|
|
||||||
else
|
|
||||||
hi = middle - 1;
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
|
||||||
} /* mvl_find_entry */
|
|
||||||
|
|
||||||
|
|
||||||
static int MVL_exists(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
return(mvl_find_entry(((MVLinfo *) opaque), name) != NULL);
|
|
||||||
} /* MVL_exists */
|
|
||||||
|
|
||||||
|
|
||||||
static int MVL_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
*fileExists = MVL_exists(opaque, name);
|
|
||||||
return(0); /* never directories in a groupfile. */
|
|
||||||
} /* MVL_isDirectory */
|
|
||||||
|
|
||||||
|
|
||||||
static int MVL_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
*fileExists = MVL_exists(opaque, name);
|
|
||||||
return(0); /* never symlinks in a groupfile. */
|
|
||||||
} /* MVL_isSymLink */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 MVL_getLastModTime(dvoid *opaque,
|
|
||||||
const char *name,
|
|
||||||
int *fileExists)
|
|
||||||
{
|
|
||||||
MVLinfo *info = ((MVLinfo *) opaque);
|
|
||||||
PHYSFS_sint64 retval = -1;
|
|
||||||
|
|
||||||
*fileExists = (mvl_find_entry(info, name) != NULL);
|
|
||||||
if (*fileExists) /* use time of MVL itself in the physical filesystem. */
|
|
||||||
retval = info->last_mod_time;
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* MVL_getLastModTime */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *MVL_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
|
||||||
{
|
|
||||||
MVLinfo *info = ((MVLinfo *) opaque);
|
|
||||||
MVLfileinfo *finfo;
|
|
||||||
MVLentry *entry;
|
|
||||||
|
|
||||||
entry = mvl_find_entry(info, fnm);
|
|
||||||
*fileExists = (entry != NULL);
|
|
||||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
|
||||||
|
|
||||||
finfo = (MVLfileinfo *) allocator.Malloc(sizeof (MVLfileinfo));
|
|
||||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
|
|
||||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
|
||||||
if ( (finfo->handle == NULL) ||
|
|
||||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
|
||||||
{
|
|
||||||
allocator.Free(finfo);
|
|
||||||
return(NULL);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
finfo->curPos = 0;
|
|
||||||
finfo->entry = entry;
|
|
||||||
return(finfo);
|
|
||||||
} /* MVL_openRead */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *MVL_openWrite(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* MVL_openWrite */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *MVL_openAppend(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* MVL_openAppend */
|
|
||||||
|
|
||||||
|
|
||||||
static int MVL_remove(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* MVL_remove */
|
|
||||||
|
|
||||||
|
|
||||||
static int MVL_mkdir(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* MVL_mkdir */
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_MVL =
|
|
||||||
{
|
|
||||||
"MVL",
|
|
||||||
MVL_ARCHIVE_DESCRIPTION,
|
|
||||||
"Bradley Bell <btb@icculus.org>",
|
|
||||||
"http://icculus.org/physfs/",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_Archiver __PHYSFS_Archiver_MVL =
|
|
||||||
{
|
|
||||||
&__PHYSFS_ArchiveInfo_MVL,
|
|
||||||
MVL_isArchive, /* isArchive() method */
|
|
||||||
MVL_openArchive, /* openArchive() method */
|
|
||||||
MVL_enumerateFiles, /* enumerateFiles() method */
|
|
||||||
MVL_exists, /* exists() method */
|
|
||||||
MVL_isDirectory, /* isDirectory() method */
|
|
||||||
MVL_isSymLink, /* isSymLink() method */
|
|
||||||
MVL_getLastModTime, /* getLastModTime() method */
|
|
||||||
MVL_openRead, /* openRead() method */
|
|
||||||
MVL_openWrite, /* openWrite() method */
|
|
||||||
MVL_openAppend, /* openAppend() method */
|
|
||||||
MVL_remove, /* remove() method */
|
|
||||||
MVL_mkdir, /* mkdir() method */
|
|
||||||
MVL_dirClose, /* dirClose() method */
|
|
||||||
MVL_read, /* read() method */
|
|
||||||
MVL_write, /* write() method */
|
|
||||||
MVL_eof, /* eof() method */
|
|
||||||
MVL_tell, /* tell() method */
|
|
||||||
MVL_seek, /* seek() method */
|
|
||||||
MVL_fileLength, /* fileLength() method */
|
|
||||||
MVL_fileClose /* fileClose() method */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined PHYSFS_SUPPORTS_MVL */
|
|
||||||
|
|
||||||
/* end of mvl.c ... */
|
|
||||||
|
|
||||||
@@ -1,633 +0,0 @@
|
|||||||
/*
|
|
||||||
* QPAK support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* This archiver handles the archive format utilized by Quake 1 and 2.
|
|
||||||
* Quake3-based games use the PkZip/Info-Zip format (which our zip.c
|
|
||||||
* archiver handles).
|
|
||||||
*
|
|
||||||
* ========================================================================
|
|
||||||
*
|
|
||||||
* This format info (in more detail) comes from:
|
|
||||||
* http://debian.fmi.uni-sofia.bg/~sergei/cgsr/docs/pak.txt
|
|
||||||
*
|
|
||||||
* Quake PAK Format
|
|
||||||
*
|
|
||||||
* Header
|
|
||||||
* (4 bytes) signature = 'PACK'
|
|
||||||
* (4 bytes) directory offset
|
|
||||||
* (4 bytes) directory length
|
|
||||||
*
|
|
||||||
* Directory
|
|
||||||
* (56 bytes) file name
|
|
||||||
* (4 bytes) file position
|
|
||||||
* (4 bytes) file length
|
|
||||||
*
|
|
||||||
* ========================================================================
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (defined PHYSFS_SUPPORTS_QPAK)
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "physfs.h"
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
#if 1 /* Make this case insensitive? */
|
|
||||||
#define QPAK_strcmp(x, y) __PHYSFS_stricmpASCII(x, y)
|
|
||||||
#define QPAK_strncmp(x, y, z) __PHYSFS_strnicmpASCII(x, y, z)
|
|
||||||
#else
|
|
||||||
#define QPAK_strcmp(x, y) strcmp(x, y)
|
|
||||||
#define QPAK_strncmp(x, y, z) strncmp(x, y, z)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char name[56];
|
|
||||||
PHYSFS_uint32 startPos;
|
|
||||||
PHYSFS_uint32 size;
|
|
||||||
} QPAKentry;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
PHYSFS_sint64 last_mod_time;
|
|
||||||
PHYSFS_uint32 entryCount;
|
|
||||||
QPAKentry *entries;
|
|
||||||
} QPAKinfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
void *handle;
|
|
||||||
QPAKentry *entry;
|
|
||||||
PHYSFS_uint32 curPos;
|
|
||||||
} QPAKfileinfo;
|
|
||||||
|
|
||||||
/* Magic numbers... */
|
|
||||||
#define QPAK_SIG 0x4b434150 /* "PACK" in ASCII. */
|
|
||||||
|
|
||||||
|
|
||||||
static void QPAK_dirClose(dvoid *opaque)
|
|
||||||
{
|
|
||||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
|
||||||
allocator.Free(info->filename);
|
|
||||||
allocator.Free(info->entries);
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* QPAK_dirClose */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 QPAK_read(fvoid *opaque, void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
|
||||||
QPAKentry *entry = finfo->entry;
|
|
||||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
|
||||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
|
||||||
PHYSFS_sint64 rc;
|
|
||||||
|
|
||||||
if (objsLeft < objCount)
|
|
||||||
objCount = objsLeft;
|
|
||||||
|
|
||||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
|
||||||
if (rc > 0)
|
|
||||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* QPAK_read */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 QPAK_write(fvoid *opaque, const void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
|
||||||
} /* QPAK_write */
|
|
||||||
|
|
||||||
|
|
||||||
static int QPAK_eof(fvoid *opaque)
|
|
||||||
{
|
|
||||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
|
||||||
QPAKentry *entry = finfo->entry;
|
|
||||||
return(finfo->curPos >= entry->size);
|
|
||||||
} /* QPAK_eof */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 QPAK_tell(fvoid *opaque)
|
|
||||||
{
|
|
||||||
return(((QPAKfileinfo *) opaque)->curPos);
|
|
||||||
} /* QPAK_tell */
|
|
||||||
|
|
||||||
|
|
||||||
static int QPAK_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
|
||||||
{
|
|
||||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
|
||||||
QPAKentry *entry = finfo->entry;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
|
||||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
|
||||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
|
||||||
if (rc)
|
|
||||||
finfo->curPos = (PHYSFS_uint32) offset;
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* QPAK_seek */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 QPAK_fileLength(fvoid *opaque)
|
|
||||||
{
|
|
||||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
|
||||||
return((PHYSFS_sint64) finfo->entry->size);
|
|
||||||
} /* QPAK_fileLength */
|
|
||||||
|
|
||||||
|
|
||||||
static int QPAK_fileClose(fvoid *opaque)
|
|
||||||
{
|
|
||||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
|
||||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
|
||||||
allocator.Free(finfo);
|
|
||||||
return(1);
|
|
||||||
} /* QPAK_fileClose */
|
|
||||||
|
|
||||||
|
|
||||||
static int qpak_open(const char *filename, int forWriting,
|
|
||||||
void **fh, PHYSFS_uint32 *count)
|
|
||||||
{
|
|
||||||
PHYSFS_uint32 buf;
|
|
||||||
|
|
||||||
*fh = NULL;
|
|
||||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
|
||||||
|
|
||||||
*fh = __PHYSFS_platformOpenRead(filename);
|
|
||||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, &buf, sizeof (PHYSFS_uint32), 1) != 1)
|
|
||||||
goto openQpak_failed;
|
|
||||||
|
|
||||||
buf = PHYSFS_swapULE32(buf);
|
|
||||||
GOTO_IF_MACRO(buf != QPAK_SIG, ERR_UNSUPPORTED_ARCHIVE, openQpak_failed);
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, &buf, sizeof (PHYSFS_uint32), 1) != 1)
|
|
||||||
goto openQpak_failed;
|
|
||||||
|
|
||||||
buf = PHYSFS_swapULE32(buf); /* directory table offset. */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
|
||||||
goto openQpak_failed;
|
|
||||||
|
|
||||||
*count = PHYSFS_swapULE32(*count);
|
|
||||||
|
|
||||||
/* corrupted archive? */
|
|
||||||
GOTO_IF_MACRO((*count % 64) != 0, ERR_CORRUPTED, openQpak_failed);
|
|
||||||
|
|
||||||
if (!__PHYSFS_platformSeek(*fh, buf))
|
|
||||||
goto openQpak_failed;
|
|
||||||
|
|
||||||
*count /= 64;
|
|
||||||
return(1);
|
|
||||||
|
|
||||||
openQpak_failed:
|
|
||||||
if (*fh != NULL)
|
|
||||||
__PHYSFS_platformClose(*fh);
|
|
||||||
|
|
||||||
*count = -1;
|
|
||||||
*fh = NULL;
|
|
||||||
return(0);
|
|
||||||
} /* qpak_open */
|
|
||||||
|
|
||||||
|
|
||||||
static int QPAK_isArchive(const char *filename, int forWriting)
|
|
||||||
{
|
|
||||||
void *fh;
|
|
||||||
PHYSFS_uint32 fileCount;
|
|
||||||
int retval = qpak_open(filename, forWriting, &fh, &fileCount);
|
|
||||||
|
|
||||||
if (fh != NULL)
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* QPAK_isArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static int qpak_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
if (one != two)
|
|
||||||
{
|
|
||||||
const QPAKentry *a = (const QPAKentry *) _a;
|
|
||||||
return(QPAK_strcmp(a[one].name, a[two].name));
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* qpak_entry_cmp */
|
|
||||||
|
|
||||||
|
|
||||||
static void qpak_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
if (one != two)
|
|
||||||
{
|
|
||||||
QPAKentry tmp;
|
|
||||||
QPAKentry *first = &(((QPAKentry *) _a)[one]);
|
|
||||||
QPAKentry *second = &(((QPAKentry *) _a)[two]);
|
|
||||||
memcpy(&tmp, first, sizeof (QPAKentry));
|
|
||||||
memcpy(first, second, sizeof (QPAKentry));
|
|
||||||
memcpy(second, &tmp, sizeof (QPAKentry));
|
|
||||||
} /* if */
|
|
||||||
} /* qpak_entry_swap */
|
|
||||||
|
|
||||||
|
|
||||||
static int qpak_load_entries(const char *name, int forWriting, QPAKinfo *info)
|
|
||||||
{
|
|
||||||
void *fh = NULL;
|
|
||||||
PHYSFS_uint32 fileCount;
|
|
||||||
QPAKentry *entry;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(!qpak_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
|
||||||
info->entryCount = fileCount;
|
|
||||||
info->entries = (QPAKentry*) allocator.Malloc(sizeof(QPAKentry)*fileCount);
|
|
||||||
if (info->entries == NULL)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
|
||||||
{
|
|
||||||
PHYSFS_uint32 loc;
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(fh,&entry->name,sizeof(entry->name),1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(fh,&loc,sizeof(loc),1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(fh,&entry->size,sizeof(entry->size),1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
entry->size = PHYSFS_swapULE32(entry->size);
|
|
||||||
entry->startPos = PHYSFS_swapULE32(loc);
|
|
||||||
} /* for */
|
|
||||||
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
|
|
||||||
__PHYSFS_sort(info->entries, info->entryCount,
|
|
||||||
qpak_entry_cmp, qpak_entry_swap);
|
|
||||||
return(1);
|
|
||||||
} /* qpak_load_entries */
|
|
||||||
|
|
||||||
|
|
||||||
static void *QPAK_openArchive(const char *name, int forWriting)
|
|
||||||
{
|
|
||||||
QPAKinfo *info = (QPAKinfo *) allocator.Malloc(sizeof (QPAKinfo));
|
|
||||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
memset(info, '\0', sizeof (QPAKinfo));
|
|
||||||
|
|
||||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
|
||||||
if (info->filename == NULL)
|
|
||||||
{
|
|
||||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
|
||||||
goto QPAK_openArchive_failed;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (!qpak_load_entries(name, forWriting, info))
|
|
||||||
goto QPAK_openArchive_failed;
|
|
||||||
|
|
||||||
strcpy(info->filename, name);
|
|
||||||
info->last_mod_time = modtime;
|
|
||||||
return(info);
|
|
||||||
|
|
||||||
QPAK_openArchive_failed:
|
|
||||||
if (info != NULL)
|
|
||||||
{
|
|
||||||
if (info->filename != NULL)
|
|
||||||
allocator.Free(info->filename);
|
|
||||||
if (info->entries != NULL)
|
|
||||||
allocator.Free(info->entries);
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return(NULL);
|
|
||||||
} /* QPAK_openArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint32 qpak_find_start_of_dir(QPAKinfo *info, const char *path,
|
|
||||||
int stop_on_first_find)
|
|
||||||
{
|
|
||||||
PHYSFS_sint32 lo = 0;
|
|
||||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
|
||||||
PHYSFS_sint32 middle;
|
|
||||||
PHYSFS_uint32 dlen = strlen(path);
|
|
||||||
PHYSFS_sint32 retval = -1;
|
|
||||||
const char *name;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (*path == '\0') /* root dir? */
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
if ((dlen > 0) && (path[dlen - 1] == '/')) /* ignore trailing slash. */
|
|
||||||
dlen--;
|
|
||||||
|
|
||||||
while (lo <= hi)
|
|
||||||
{
|
|
||||||
middle = lo + ((hi - lo) / 2);
|
|
||||||
name = info->entries[middle].name;
|
|
||||||
rc = QPAK_strncmp(path, name, dlen);
|
|
||||||
if (rc == 0)
|
|
||||||
{
|
|
||||||
char ch = name[dlen];
|
|
||||||
if (ch < '/') /* make sure this isn't just a substr match. */
|
|
||||||
rc = -1;
|
|
||||||
else if (ch > '/')
|
|
||||||
rc = 1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (stop_on_first_find) /* Just checking dir's existance? */
|
|
||||||
return(middle);
|
|
||||||
|
|
||||||
if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
|
|
||||||
return(middle + 1);
|
|
||||||
|
|
||||||
/* there might be more entries earlier in the list. */
|
|
||||||
retval = middle;
|
|
||||||
hi = middle - 1;
|
|
||||||
} /* else */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (rc > 0)
|
|
||||||
lo = middle + 1;
|
|
||||||
else
|
|
||||||
hi = middle - 1;
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* qpak_find_start_of_dir */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Moved to seperate function so we can use alloca then immediately throw
|
|
||||||
* away the allocated stack space...
|
|
||||||
*/
|
|
||||||
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
|
||||||
const char *odir, const char *str, PHYSFS_sint32 ln)
|
|
||||||
{
|
|
||||||
char *newstr = __PHYSFS_smallAlloc(ln + 1);
|
|
||||||
if (newstr == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
memcpy(newstr, str, ln);
|
|
||||||
newstr[ln] = '\0';
|
|
||||||
cb(callbackdata, odir, newstr);
|
|
||||||
__PHYSFS_smallFree(newstr);
|
|
||||||
} /* doEnumCallback */
|
|
||||||
|
|
||||||
|
|
||||||
static void QPAK_enumerateFiles(dvoid *opaque, const char *dname,
|
|
||||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
|
||||||
const char *origdir, void *callbackdata)
|
|
||||||
{
|
|
||||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
|
||||||
PHYSFS_sint32 dlen, dlen_inc, max, i;
|
|
||||||
|
|
||||||
i = qpak_find_start_of_dir(info, dname, 0);
|
|
||||||
if (i == -1) /* no such directory. */
|
|
||||||
return;
|
|
||||||
|
|
||||||
dlen = strlen(dname);
|
|
||||||
if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
|
|
||||||
dlen--;
|
|
||||||
|
|
||||||
dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;
|
|
||||||
max = (PHYSFS_sint32) info->entryCount;
|
|
||||||
while (i < max)
|
|
||||||
{
|
|
||||||
char *add;
|
|
||||||
char *ptr;
|
|
||||||
PHYSFS_sint32 ln;
|
|
||||||
char *e = info->entries[i].name;
|
|
||||||
if ((dlen) && ((QPAK_strncmp(e, dname, dlen)) || (e[dlen] != '/')))
|
|
||||||
break; /* past end of this dir; we're done. */
|
|
||||||
|
|
||||||
add = e + dlen_inc;
|
|
||||||
ptr = strchr(add, '/');
|
|
||||||
ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));
|
|
||||||
doEnumCallback(cb, callbackdata, origdir, add, ln);
|
|
||||||
ln += dlen_inc; /* point past entry to children... */
|
|
||||||
|
|
||||||
/* increment counter and skip children of subdirs... */
|
|
||||||
while ((++i < max) && (ptr != NULL))
|
|
||||||
{
|
|
||||||
char *e_new = info->entries[i].name;
|
|
||||||
if ((QPAK_strncmp(e, e_new, ln) != 0) || (e_new[ln] != '/'))
|
|
||||||
break;
|
|
||||||
} /* while */
|
|
||||||
} /* while */
|
|
||||||
} /* QPAK_enumerateFiles */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This will find the QPAKentry associated with a path in platform-independent
|
|
||||||
* notation. Directories don't have QPAKentries associated with them, but
|
|
||||||
* (*isDir) will be set to non-zero if a dir was hit.
|
|
||||||
*/
|
|
||||||
static QPAKentry *qpak_find_entry(QPAKinfo *info, const char *path, int *isDir)
|
|
||||||
{
|
|
||||||
QPAKentry *a = info->entries;
|
|
||||||
PHYSFS_sint32 pathlen = strlen(path);
|
|
||||||
PHYSFS_sint32 lo = 0;
|
|
||||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
|
||||||
PHYSFS_sint32 middle;
|
|
||||||
const char *thispath = NULL;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
while (lo <= hi)
|
|
||||||
{
|
|
||||||
middle = lo + ((hi - lo) / 2);
|
|
||||||
thispath = a[middle].name;
|
|
||||||
rc = QPAK_strncmp(path, thispath, pathlen);
|
|
||||||
|
|
||||||
if (rc > 0)
|
|
||||||
lo = middle + 1;
|
|
||||||
|
|
||||||
else if (rc < 0)
|
|
||||||
hi = middle - 1;
|
|
||||||
|
|
||||||
else /* substring match...might be dir or entry or nothing. */
|
|
||||||
{
|
|
||||||
if (isDir != NULL)
|
|
||||||
{
|
|
||||||
*isDir = (thispath[pathlen] == '/');
|
|
||||||
if (*isDir)
|
|
||||||
return(NULL);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (thispath[pathlen] == '\0') /* found entry? */
|
|
||||||
return(&a[middle]);
|
|
||||||
/* adjust search params, try again. */
|
|
||||||
else if (thispath[pathlen] > '/')
|
|
||||||
hi = middle - 1;
|
|
||||||
else
|
|
||||||
lo = middle + 1;
|
|
||||||
} /* if */
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
if (isDir != NULL)
|
|
||||||
*isDir = 0;
|
|
||||||
|
|
||||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
|
||||||
} /* qpak_find_entry */
|
|
||||||
|
|
||||||
|
|
||||||
static int QPAK_exists(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
int isDir;
|
|
||||||
QPAKinfo *info = (QPAKinfo *) opaque;
|
|
||||||
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
|
|
||||||
return((entry != NULL) || (isDir));
|
|
||||||
} /* QPAK_exists */
|
|
||||||
|
|
||||||
|
|
||||||
static int QPAK_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
QPAKinfo *info = (QPAKinfo *) opaque;
|
|
||||||
int isDir;
|
|
||||||
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
|
|
||||||
|
|
||||||
*fileExists = ((isDir) || (entry != NULL));
|
|
||||||
if (isDir)
|
|
||||||
return(1); /* definitely a dir. */
|
|
||||||
|
|
||||||
BAIL_MACRO(ERR_NO_SUCH_FILE, 0);
|
|
||||||
} /* QPAK_isDirectory */
|
|
||||||
|
|
||||||
|
|
||||||
static int QPAK_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
*fileExists = QPAK_exists(opaque, name);
|
|
||||||
return(0); /* never symlinks in a quake pak. */
|
|
||||||
} /* QPAK_isSymLink */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 QPAK_getLastModTime(dvoid *opaque,
|
|
||||||
const char *name,
|
|
||||||
int *fileExists)
|
|
||||||
{
|
|
||||||
int isDir;
|
|
||||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
|
||||||
PHYSFS_sint64 retval = -1;
|
|
||||||
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
|
|
||||||
|
|
||||||
*fileExists = ((isDir) || (entry != NULL));
|
|
||||||
if (*fileExists) /* use time of QPAK itself in the physical filesystem. */
|
|
||||||
retval = info->last_mod_time;
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* QPAK_getLastModTime */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *QPAK_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
|
||||||
{
|
|
||||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
|
||||||
QPAKfileinfo *finfo;
|
|
||||||
QPAKentry *entry;
|
|
||||||
int isDir;
|
|
||||||
|
|
||||||
entry = qpak_find_entry(info, fnm, &isDir);
|
|
||||||
*fileExists = ((entry != NULL) || (isDir));
|
|
||||||
BAIL_IF_MACRO(isDir, ERR_NOT_A_FILE, NULL);
|
|
||||||
BAIL_IF_MACRO(entry == NULL, ERR_NO_SUCH_FILE, NULL);
|
|
||||||
|
|
||||||
finfo = (QPAKfileinfo *) allocator.Malloc(sizeof (QPAKfileinfo));
|
|
||||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
|
|
||||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
|
||||||
if ( (finfo->handle == NULL) ||
|
|
||||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
|
||||||
{
|
|
||||||
allocator.Free(finfo);
|
|
||||||
return(NULL);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
finfo->curPos = 0;
|
|
||||||
finfo->entry = entry;
|
|
||||||
return(finfo);
|
|
||||||
} /* QPAK_openRead */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *QPAK_openWrite(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* QPAK_openWrite */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *QPAK_openAppend(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* QPAK_openAppend */
|
|
||||||
|
|
||||||
|
|
||||||
static int QPAK_remove(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* QPAK_remove */
|
|
||||||
|
|
||||||
|
|
||||||
static int QPAK_mkdir(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* QPAK_mkdir */
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_QPAK =
|
|
||||||
{
|
|
||||||
"PAK",
|
|
||||||
QPAK_ARCHIVE_DESCRIPTION,
|
|
||||||
"Ryan C. Gordon <icculus@icculus.org>",
|
|
||||||
"http://icculus.org/physfs/",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
|
|
||||||
{
|
|
||||||
&__PHYSFS_ArchiveInfo_QPAK,
|
|
||||||
QPAK_isArchive, /* isArchive() method */
|
|
||||||
QPAK_openArchive, /* openArchive() method */
|
|
||||||
QPAK_enumerateFiles, /* enumerateFiles() method */
|
|
||||||
QPAK_exists, /* exists() method */
|
|
||||||
QPAK_isDirectory, /* isDirectory() method */
|
|
||||||
QPAK_isSymLink, /* isSymLink() method */
|
|
||||||
QPAK_getLastModTime, /* getLastModTime() method */
|
|
||||||
QPAK_openRead, /* openRead() method */
|
|
||||||
QPAK_openWrite, /* openWrite() method */
|
|
||||||
QPAK_openAppend, /* openAppend() method */
|
|
||||||
QPAK_remove, /* remove() method */
|
|
||||||
QPAK_mkdir, /* mkdir() method */
|
|
||||||
QPAK_dirClose, /* dirClose() method */
|
|
||||||
QPAK_read, /* read() method */
|
|
||||||
QPAK_write, /* write() method */
|
|
||||||
QPAK_eof, /* eof() method */
|
|
||||||
QPAK_tell, /* tell() method */
|
|
||||||
QPAK_seek, /* seek() method */
|
|
||||||
QPAK_fileLength, /* fileLength() method */
|
|
||||||
QPAK_fileClose /* fileClose() method */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined PHYSFS_SUPPORTS_QPAK */
|
|
||||||
|
|
||||||
/* end of qpak.c ... */
|
|
||||||
|
|
||||||
@@ -1,531 +0,0 @@
|
|||||||
/*
|
|
||||||
* WAD support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* This driver handles DOOM engine archives ("wads").
|
|
||||||
* This format (but not this driver) was designed by id Software for use
|
|
||||||
* with the DOOM engine.
|
|
||||||
* The specs of the format are from the unofficial doom specs v1.666
|
|
||||||
* found here: http://www.gamers.org/dhs/helpdocs/dmsp1666.html
|
|
||||||
* The format of the archive: (from the specs)
|
|
||||||
*
|
|
||||||
* A WAD file has three parts:
|
|
||||||
* (1) a twelve-byte header
|
|
||||||
* (2) one or more "lumps"
|
|
||||||
* (3) a directory or "info table" that contains the names, offsets, and
|
|
||||||
* sizes of all the lumps in the WAD
|
|
||||||
*
|
|
||||||
* The header consists of three four-byte parts:
|
|
||||||
* (a) an ASCII string which must be either "IWAD" or "PWAD"
|
|
||||||
* (b) a 4-byte (long) integer which is the number of lumps in the wad
|
|
||||||
* (c) a long integer which is the file offset to the start of
|
|
||||||
* the directory
|
|
||||||
*
|
|
||||||
* The directory has one 16-byte entry for every lump. Each entry consists
|
|
||||||
* of three parts:
|
|
||||||
*
|
|
||||||
* (a) a long integer, the file offset to the start of the lump
|
|
||||||
* (b) a long integer, the size of the lump in bytes
|
|
||||||
* (c) an 8-byte ASCII string, the name of the lump, padded with zeros.
|
|
||||||
* For example, the "DEMO1" entry in hexadecimal would be
|
|
||||||
* (44 45 4D 4F 31 00 00 00)
|
|
||||||
*
|
|
||||||
* Note that there is no way to tell if an opened WAD archive is a
|
|
||||||
* IWAD or PWAD with this archiver.
|
|
||||||
* I couldn't think of a way to provide that information, without being too
|
|
||||||
* hacky.
|
|
||||||
* I don't think it's really that important though.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Travis Wells, based on the GRP archiver by
|
|
||||||
* Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (defined PHYSFS_SUPPORTS_WAD)
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "physfs.h"
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char name[18];
|
|
||||||
PHYSFS_uint32 startPos;
|
|
||||||
PHYSFS_uint32 size;
|
|
||||||
} WADentry;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
PHYSFS_sint64 last_mod_time;
|
|
||||||
PHYSFS_uint32 entryCount;
|
|
||||||
PHYSFS_uint32 entryOffset;
|
|
||||||
WADentry *entries;
|
|
||||||
} WADinfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
void *handle;
|
|
||||||
WADentry *entry;
|
|
||||||
PHYSFS_uint32 curPos;
|
|
||||||
} WADfileinfo;
|
|
||||||
|
|
||||||
|
|
||||||
static void WAD_dirClose(dvoid *opaque)
|
|
||||||
{
|
|
||||||
WADinfo *info = ((WADinfo *) opaque);
|
|
||||||
allocator.Free(info->filename);
|
|
||||||
allocator.Free(info->entries);
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* WAD_dirClose */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 WAD_read(fvoid *opaque, void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
|
||||||
WADentry *entry = finfo->entry;
|
|
||||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
|
||||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
|
||||||
PHYSFS_sint64 rc;
|
|
||||||
|
|
||||||
if (objsLeft < objCount)
|
|
||||||
objCount = objsLeft;
|
|
||||||
|
|
||||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
|
||||||
if (rc > 0)
|
|
||||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* WAD_read */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 WAD_write(fvoid *opaque, const void *buffer,
|
|
||||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
|
||||||
} /* WAD_write */
|
|
||||||
|
|
||||||
|
|
||||||
static int WAD_eof(fvoid *opaque)
|
|
||||||
{
|
|
||||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
|
||||||
WADentry *entry = finfo->entry;
|
|
||||||
return(finfo->curPos >= entry->size);
|
|
||||||
} /* WAD_eof */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 WAD_tell(fvoid *opaque)
|
|
||||||
{
|
|
||||||
return(((WADfileinfo *) opaque)->curPos);
|
|
||||||
} /* WAD_tell */
|
|
||||||
|
|
||||||
|
|
||||||
static int WAD_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
|
||||||
{
|
|
||||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
|
||||||
WADentry *entry = finfo->entry;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
|
||||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
|
||||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
|
||||||
if (rc)
|
|
||||||
finfo->curPos = (PHYSFS_uint32) offset;
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* WAD_seek */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 WAD_fileLength(fvoid *opaque)
|
|
||||||
{
|
|
||||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
|
||||||
return((PHYSFS_sint64) finfo->entry->size);
|
|
||||||
} /* WAD_fileLength */
|
|
||||||
|
|
||||||
|
|
||||||
static int WAD_fileClose(fvoid *opaque)
|
|
||||||
{
|
|
||||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
|
||||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
|
||||||
allocator.Free(finfo);
|
|
||||||
return(1);
|
|
||||||
} /* WAD_fileClose */
|
|
||||||
|
|
||||||
|
|
||||||
static int wad_open(const char *filename, int forWriting,
|
|
||||||
void **fh, PHYSFS_uint32 *count,PHYSFS_uint32 *offset)
|
|
||||||
{
|
|
||||||
PHYSFS_uint8 buf[4];
|
|
||||||
|
|
||||||
*fh = NULL;
|
|
||||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
|
||||||
|
|
||||||
*fh = __PHYSFS_platformOpenRead(filename);
|
|
||||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
|
|
||||||
goto openWad_failed;
|
|
||||||
|
|
||||||
if (memcmp(buf, "IWAD", 4) != 0 && memcmp(buf, "PWAD", 4) != 0)
|
|
||||||
{
|
|
||||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
|
||||||
goto openWad_failed;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
|
||||||
goto openWad_failed;
|
|
||||||
|
|
||||||
*count = PHYSFS_swapULE32(*count);
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(*fh, offset, sizeof (PHYSFS_uint32), 1) != 1)
|
|
||||||
goto openWad_failed;
|
|
||||||
|
|
||||||
*offset = PHYSFS_swapULE32(*offset);
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
|
|
||||||
openWad_failed:
|
|
||||||
if (*fh != NULL)
|
|
||||||
__PHYSFS_platformClose(*fh);
|
|
||||||
|
|
||||||
*count = -1;
|
|
||||||
*fh = NULL;
|
|
||||||
return(0);
|
|
||||||
} /* wad_open */
|
|
||||||
|
|
||||||
|
|
||||||
static int WAD_isArchive(const char *filename, int forWriting)
|
|
||||||
{
|
|
||||||
void *fh;
|
|
||||||
PHYSFS_uint32 fileCount,offset;
|
|
||||||
int retval = wad_open(filename, forWriting, &fh, &fileCount,&offset);
|
|
||||||
|
|
||||||
if (fh != NULL)
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* WAD_isArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static int wad_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
if (one != two)
|
|
||||||
{
|
|
||||||
const WADentry *a = (const WADentry *) _a;
|
|
||||||
return(strcmp(a[one].name, a[two].name));
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* wad_entry_cmp */
|
|
||||||
|
|
||||||
|
|
||||||
static void wad_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
|
||||||
{
|
|
||||||
if (one != two)
|
|
||||||
{
|
|
||||||
WADentry tmp;
|
|
||||||
WADentry *first = &(((WADentry *) _a)[one]);
|
|
||||||
WADentry *second = &(((WADentry *) _a)[two]);
|
|
||||||
memcpy(&tmp, first, sizeof (WADentry));
|
|
||||||
memcpy(first, second, sizeof (WADentry));
|
|
||||||
memcpy(second, &tmp, sizeof (WADentry));
|
|
||||||
} /* if */
|
|
||||||
} /* wad_entry_swap */
|
|
||||||
|
|
||||||
|
|
||||||
static int wad_load_entries(const char *name, int forWriting, WADinfo *info)
|
|
||||||
{
|
|
||||||
void *fh = NULL;
|
|
||||||
PHYSFS_uint32 fileCount;
|
|
||||||
PHYSFS_uint32 directoryOffset;
|
|
||||||
WADentry *entry;
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(!wad_open(name, forWriting, &fh, &fileCount,&directoryOffset), NULL, 0);
|
|
||||||
info->entryCount = fileCount;
|
|
||||||
info->entries = (WADentry *) allocator.Malloc(sizeof(WADentry)*fileCount);
|
|
||||||
if (info->entries == NULL)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
__PHYSFS_platformSeek(fh,directoryOffset);
|
|
||||||
|
|
||||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
|
||||||
{
|
|
||||||
if (__PHYSFS_platformRead(fh, &entry->startPos, 4, 1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (__PHYSFS_platformRead(fh, &entry->name, 8, 1) != 1)
|
|
||||||
{
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
entry->name[8] = '\0'; /* name might not be null-terminated in file. */
|
|
||||||
entry->size = PHYSFS_swapULE32(entry->size);
|
|
||||||
entry->startPos = PHYSFS_swapULE32(entry->startPos);
|
|
||||||
} /* for */
|
|
||||||
|
|
||||||
__PHYSFS_platformClose(fh);
|
|
||||||
|
|
||||||
__PHYSFS_sort(info->entries, info->entryCount,
|
|
||||||
wad_entry_cmp, wad_entry_swap);
|
|
||||||
return(1);
|
|
||||||
} /* wad_load_entries */
|
|
||||||
|
|
||||||
|
|
||||||
static void *WAD_openArchive(const char *name, int forWriting)
|
|
||||||
{
|
|
||||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
|
||||||
WADinfo *info = (WADinfo *) allocator.Malloc(sizeof (WADinfo));
|
|
||||||
|
|
||||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
memset(info, '\0', sizeof (WADinfo));
|
|
||||||
|
|
||||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
|
||||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, WAD_openArchive_failed);
|
|
||||||
|
|
||||||
if (!wad_load_entries(name, forWriting, info))
|
|
||||||
goto WAD_openArchive_failed;
|
|
||||||
|
|
||||||
strcpy(info->filename, name);
|
|
||||||
info->last_mod_time = modtime;
|
|
||||||
return(info);
|
|
||||||
|
|
||||||
WAD_openArchive_failed:
|
|
||||||
if (info != NULL)
|
|
||||||
{
|
|
||||||
if (info->filename != NULL)
|
|
||||||
allocator.Free(info->filename);
|
|
||||||
if (info->entries != NULL)
|
|
||||||
allocator.Free(info->entries);
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return(NULL);
|
|
||||||
} /* WAD_openArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static void WAD_enumerateFiles(dvoid *opaque, const char *dname,
|
|
||||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
|
||||||
const char *origdir, void *callbackdata)
|
|
||||||
{
|
|
||||||
WADinfo *info = ((WADinfo *) opaque);
|
|
||||||
WADentry *entry = info->entries;
|
|
||||||
PHYSFS_uint32 max = info->entryCount;
|
|
||||||
PHYSFS_uint32 i;
|
|
||||||
const char *name;
|
|
||||||
char *sep;
|
|
||||||
|
|
||||||
if (*dname == '\0') /* root directory enumeration? */
|
|
||||||
{
|
|
||||||
for (i = 0; i < max; i++, entry++)
|
|
||||||
{
|
|
||||||
name = entry->name;
|
|
||||||
if (strchr(name, '/') == NULL)
|
|
||||||
cb(callbackdata, origdir, name);
|
|
||||||
} /* for */
|
|
||||||
} /* if */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < max; i++, entry++)
|
|
||||||
{
|
|
||||||
name = entry->name;
|
|
||||||
sep = strchr(name, '/');
|
|
||||||
if (sep != NULL)
|
|
||||||
{
|
|
||||||
if (strncmp(dname, name, (sep - name)) == 0)
|
|
||||||
cb(callbackdata, origdir, sep + 1);
|
|
||||||
} /* if */
|
|
||||||
} /* for */
|
|
||||||
} /* else */
|
|
||||||
} /* WAD_enumerateFiles */
|
|
||||||
|
|
||||||
|
|
||||||
static WADentry *wad_find_entry(WADinfo *info, const char *name)
|
|
||||||
{
|
|
||||||
WADentry *a = info->entries;
|
|
||||||
PHYSFS_sint32 lo = 0;
|
|
||||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
|
||||||
PHYSFS_sint32 middle;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
while (lo <= hi)
|
|
||||||
{
|
|
||||||
middle = lo + ((hi - lo) / 2);
|
|
||||||
rc = strcmp(name, a[middle].name);
|
|
||||||
if (rc == 0) /* found it! */
|
|
||||||
return(&a[middle]);
|
|
||||||
else if (rc > 0)
|
|
||||||
lo = middle + 1;
|
|
||||||
else
|
|
||||||
hi = middle - 1;
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
|
||||||
} /* wad_find_entry */
|
|
||||||
|
|
||||||
|
|
||||||
static int WAD_exists(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
return(wad_find_entry(((WADinfo *) opaque), name) != NULL);
|
|
||||||
} /* WAD_exists */
|
|
||||||
|
|
||||||
|
|
||||||
static int WAD_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
WADentry *entry = wad_find_entry(((WADinfo *) opaque), name);
|
|
||||||
if (entry != NULL)
|
|
||||||
{
|
|
||||||
char *n;
|
|
||||||
|
|
||||||
*fileExists = 1;
|
|
||||||
|
|
||||||
/* Can't be a directory if it's a subdirectory. */
|
|
||||||
if (strchr(entry->name, '/') != NULL)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
/* Check if it matches "MAP??" or "E?M?" ... */
|
|
||||||
n = entry->name;
|
|
||||||
if ((n[0] == 'E' && n[2] == 'M') ||
|
|
||||||
(n[0] == 'M' && n[1] == 'A' && n[2] == 'P' && n[6] == 0))
|
|
||||||
{
|
|
||||||
return(1);
|
|
||||||
} /* if */
|
|
||||||
return(0);
|
|
||||||
} /* if */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*fileExists = 0;
|
|
||||||
return(0);
|
|
||||||
} /* else */
|
|
||||||
} /* WAD_isDirectory */
|
|
||||||
|
|
||||||
|
|
||||||
static int WAD_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
|
||||||
{
|
|
||||||
*fileExists = WAD_exists(opaque, name);
|
|
||||||
return(0); /* never symlinks in a wad. */
|
|
||||||
} /* WAD_isSymLink */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 WAD_getLastModTime(dvoid *opaque,
|
|
||||||
const char *name,
|
|
||||||
int *fileExists)
|
|
||||||
{
|
|
||||||
WADinfo *info = ((WADinfo *) opaque);
|
|
||||||
PHYSFS_sint64 retval = -1;
|
|
||||||
|
|
||||||
*fileExists = (wad_find_entry(info, name) != NULL);
|
|
||||||
if (*fileExists) /* use time of WAD itself in the physical filesystem. */
|
|
||||||
retval = info->last_mod_time;
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* WAD_getLastModTime */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *WAD_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
|
||||||
{
|
|
||||||
WADinfo *info = ((WADinfo *) opaque);
|
|
||||||
WADfileinfo *finfo;
|
|
||||||
WADentry *entry;
|
|
||||||
|
|
||||||
entry = wad_find_entry(info, fnm);
|
|
||||||
*fileExists = (entry != NULL);
|
|
||||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
|
||||||
|
|
||||||
finfo = (WADfileinfo *) allocator.Malloc(sizeof (WADfileinfo));
|
|
||||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
|
|
||||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
|
||||||
if ( (finfo->handle == NULL) ||
|
|
||||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
|
||||||
{
|
|
||||||
allocator.Free(finfo);
|
|
||||||
return(NULL);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
finfo->curPos = 0;
|
|
||||||
finfo->entry = entry;
|
|
||||||
return(finfo);
|
|
||||||
} /* WAD_openRead */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *WAD_openWrite(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* WAD_openWrite */
|
|
||||||
|
|
||||||
|
|
||||||
static fvoid *WAD_openAppend(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
||||||
} /* WAD_openAppend */
|
|
||||||
|
|
||||||
|
|
||||||
static int WAD_remove(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* WAD_remove */
|
|
||||||
|
|
||||||
|
|
||||||
static int WAD_mkdir(dvoid *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
||||||
} /* WAD_mkdir */
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_WAD =
|
|
||||||
{
|
|
||||||
"WAD",
|
|
||||||
WAD_ARCHIVE_DESCRIPTION,
|
|
||||||
"Travis Wells <traviswells@mchsi.com>",
|
|
||||||
"http://www.3dmm2.com/doom/",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_Archiver __PHYSFS_Archiver_WAD =
|
|
||||||
{
|
|
||||||
&__PHYSFS_ArchiveInfo_WAD,
|
|
||||||
WAD_isArchive, /* isArchive() method */
|
|
||||||
WAD_openArchive, /* openArchive() method */
|
|
||||||
WAD_enumerateFiles, /* enumerateFiles() method */
|
|
||||||
WAD_exists, /* exists() method */
|
|
||||||
WAD_isDirectory, /* isDirectory() method */
|
|
||||||
WAD_isSymLink, /* isSymLink() method */
|
|
||||||
WAD_getLastModTime, /* getLastModTime() method */
|
|
||||||
WAD_openRead, /* openRead() method */
|
|
||||||
WAD_openWrite, /* openWrite() method */
|
|
||||||
WAD_openAppend, /* openAppend() method */
|
|
||||||
WAD_remove, /* remove() method */
|
|
||||||
WAD_mkdir, /* mkdir() method */
|
|
||||||
WAD_dirClose, /* dirClose() method */
|
|
||||||
WAD_read, /* read() method */
|
|
||||||
WAD_write, /* write() method */
|
|
||||||
WAD_eof, /* eof() method */
|
|
||||||
WAD_tell, /* tell() method */
|
|
||||||
WAD_seek, /* seek() method */
|
|
||||||
WAD_fileLength, /* fileLength() method */
|
|
||||||
WAD_fileClose /* fileClose() method */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* defined PHYSFS_SUPPORTS_WAD */
|
|
||||||
|
|
||||||
/* end of wad.c ... */
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,58 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
//
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
//
|
|
||||||
[assembly: AssemblyTitle("PhysFS.NET")]
|
|
||||||
[assembly: AssemblyDescription("PhysFS Bindings for .NET")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("PhysFS.NET")]
|
|
||||||
[assembly: AssemblyCopyright("(c)2003 Gregory S. Read")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
|
|
||||||
//
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Revision and Build Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.0.*")]
|
|
||||||
|
|
||||||
//
|
|
||||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
|
||||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
|
||||||
//
|
|
||||||
// Use the attributes below to control which key is used for signing.
|
|
||||||
//
|
|
||||||
// Notes:
|
|
||||||
// (*) If no key is specified, the assembly is not signed.
|
|
||||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
|
||||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
|
||||||
// a key.
|
|
||||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
|
||||||
// following processing occurs:
|
|
||||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
|
||||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
|
||||||
// in the KeyFile is installed into the CSP and used.
|
|
||||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
|
||||||
// When specifying the KeyFile, the location of the KeyFile should be
|
|
||||||
// relative to the project output directory which is
|
|
||||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
|
||||||
// located in the project directory, you would specify the AssemblyKeyFile
|
|
||||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
|
||||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
|
||||||
// documentation for more information on this.
|
|
||||||
//
|
|
||||||
[assembly: AssemblyDelaySign(false)]
|
|
||||||
[assembly: AssemblyKeyFile("")]
|
|
||||||
[assembly: AssemblyKeyName("")]
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
<VisualStudioProject>
|
|
||||||
<CSHARP
|
|
||||||
ProjectType = "Local"
|
|
||||||
ProductVersion = "7.0.9466"
|
|
||||||
SchemaVersion = "1.0"
|
|
||||||
ProjectGuid = "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
|
||||||
>
|
|
||||||
<Build>
|
|
||||||
<Settings
|
|
||||||
ApplicationIcon = ""
|
|
||||||
AssemblyKeyContainerName = ""
|
|
||||||
AssemblyName = "PhysFS.NET"
|
|
||||||
AssemblyOriginatorKeyFile = ""
|
|
||||||
DefaultClientScript = "JScript"
|
|
||||||
DefaultHTMLPageLayout = "Grid"
|
|
||||||
DefaultTargetSchema = "IE50"
|
|
||||||
DelaySign = "false"
|
|
||||||
OutputType = "Library"
|
|
||||||
RootNamespace = "PhysFS.NET"
|
|
||||||
StartupObject = ""
|
|
||||||
>
|
|
||||||
<Config
|
|
||||||
Name = "Debug"
|
|
||||||
AllowUnsafeBlocks = "true"
|
|
||||||
BaseAddress = "285212672"
|
|
||||||
CheckForOverflowUnderflow = "false"
|
|
||||||
ConfigurationOverrideFile = ""
|
|
||||||
DefineConstants = "DEBUG;TRACE"
|
|
||||||
DocumentationFile = ""
|
|
||||||
DebugSymbols = "true"
|
|
||||||
FileAlignment = "4096"
|
|
||||||
IncrementalBuild = "true"
|
|
||||||
Optimize = "false"
|
|
||||||
OutputPath = "bin\Debug\"
|
|
||||||
RegisterForComInterop = "false"
|
|
||||||
RemoveIntegerChecks = "false"
|
|
||||||
TreatWarningsAsErrors = "false"
|
|
||||||
WarningLevel = "4"
|
|
||||||
/>
|
|
||||||
<Config
|
|
||||||
Name = "Release"
|
|
||||||
AllowUnsafeBlocks = "true"
|
|
||||||
BaseAddress = "285212672"
|
|
||||||
CheckForOverflowUnderflow = "false"
|
|
||||||
ConfigurationOverrideFile = ""
|
|
||||||
DefineConstants = "TRACE"
|
|
||||||
DocumentationFile = ""
|
|
||||||
DebugSymbols = "false"
|
|
||||||
FileAlignment = "4096"
|
|
||||||
IncrementalBuild = "false"
|
|
||||||
Optimize = "true"
|
|
||||||
OutputPath = "bin\Release\"
|
|
||||||
RegisterForComInterop = "false"
|
|
||||||
RemoveIntegerChecks = "false"
|
|
||||||
TreatWarningsAsErrors = "false"
|
|
||||||
WarningLevel = "4"
|
|
||||||
/>
|
|
||||||
</Settings>
|
|
||||||
<References>
|
|
||||||
<Reference
|
|
||||||
Name = "System"
|
|
||||||
AssemblyName = "System"
|
|
||||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
|
|
||||||
/>
|
|
||||||
<Reference
|
|
||||||
Name = "System.Data"
|
|
||||||
AssemblyName = "System.Data"
|
|
||||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
|
|
||||||
/>
|
|
||||||
<Reference
|
|
||||||
Name = "System.XML"
|
|
||||||
AssemblyName = "System.Xml"
|
|
||||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
|
|
||||||
/>
|
|
||||||
<Reference
|
|
||||||
Name = "System.Drawing"
|
|
||||||
AssemblyName = "System.Drawing"
|
|
||||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
|
|
||||||
/>
|
|
||||||
<Reference
|
|
||||||
Name = "System.Windows.Forms"
|
|
||||||
AssemblyName = "System.Windows.Forms"
|
|
||||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"
|
|
||||||
/>
|
|
||||||
</References>
|
|
||||||
</Build>
|
|
||||||
<Files>
|
|
||||||
<Include>
|
|
||||||
<File
|
|
||||||
RelPath = "AssemblyInfo.cs"
|
|
||||||
SubType = "Code"
|
|
||||||
BuildAction = "Compile"
|
|
||||||
/>
|
|
||||||
<File
|
|
||||||
RelPath = "PhysFS.cs"
|
|
||||||
SubType = "Code"
|
|
||||||
BuildAction = "Compile"
|
|
||||||
/>
|
|
||||||
<File
|
|
||||||
RelPath = "PhysFS_DLL.cs"
|
|
||||||
SubType = "Code"
|
|
||||||
BuildAction = "Compile"
|
|
||||||
/>
|
|
||||||
<File
|
|
||||||
RelPath = "PhysFSFileStream.cs"
|
|
||||||
SubType = "Code"
|
|
||||||
BuildAction = "Compile"
|
|
||||||
/>
|
|
||||||
</Include>
|
|
||||||
</Files>
|
|
||||||
</CSHARP>
|
|
||||||
</VisualStudioProject>
|
|
||||||
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 7.00
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysFS.NET", "PhysFS.NET.csproj", "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfiguration) = preSolution
|
|
||||||
ConfigName.0 = Debug
|
|
||||||
ConfigName.1 = Release
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectDependencies) = postSolution
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfiguration) = postSolution
|
|
||||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.ActiveCfg = Debug|.NET
|
|
||||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.Build.0 = Debug|.NET
|
|
||||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.ActiveCfg = Release|.NET
|
|
||||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.Build.0 = Release|.NET
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
/* PhysFS.cs - (c)2003 Gregory S. Read
|
|
||||||
* Provides access to PhysFS API calls not specific to file handle access.
|
|
||||||
*/
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace PhysFS_NET
|
|
||||||
{
|
|
||||||
public class PhysFS
|
|
||||||
{
|
|
||||||
/* Initialize
|
|
||||||
* Inits the PhysFS API. This normally does not need to be called unless
|
|
||||||
* the API has been manually deinitialized since the PhysFS_DLL class
|
|
||||||
* initializes just before the first call is made into the DLL.
|
|
||||||
* Parameters
|
|
||||||
* none
|
|
||||||
* Returns
|
|
||||||
* none
|
|
||||||
* Exceptions
|
|
||||||
* PhysFSException - An error occured in the PhysFS API
|
|
||||||
*/
|
|
||||||
public static void Initialize()
|
|
||||||
{
|
|
||||||
// Initialize the physfs library, raise an exception if error
|
|
||||||
if(PhysFS_DLL.PHYSFS_init("") == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Deinitialize
|
|
||||||
* Deinits the PhysFS API. It is recommended that this method be called
|
|
||||||
* by the application before exiting in order to gracefully deallocate
|
|
||||||
* resources and close all filehandles, etc.
|
|
||||||
* Parameters
|
|
||||||
* none
|
|
||||||
* Returns
|
|
||||||
* none
|
|
||||||
* Exceptions
|
|
||||||
* PhysFSException - An error occured in the PhysFS API
|
|
||||||
*/
|
|
||||||
public static void Deinitialize()
|
|
||||||
{
|
|
||||||
// Deinit, raise an exception if an error occured
|
|
||||||
if(PhysFS_DLL.PHYSFS_deinit() == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BaseDir
|
|
||||||
* Gets the base directory configured for PhysFS. See the PhysFS API
|
|
||||||
* documentation for more information.
|
|
||||||
* Parameters
|
|
||||||
* none
|
|
||||||
* Returns
|
|
||||||
* A string value representing the Base Directory
|
|
||||||
* Exceptions
|
|
||||||
* none
|
|
||||||
*/
|
|
||||||
public static string BaseDir
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// Return the current base directory
|
|
||||||
return PhysFS_DLL.PHYSFS_getBaseDir();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* WriteDir
|
|
||||||
* Gets or sets the write directory configured for PhysFS. See the PhysFS API
|
|
||||||
* documentation for more information.
|
|
||||||
* Parameters
|
|
||||||
* set - Path to set the WriteDir property to
|
|
||||||
* Returns
|
|
||||||
* A string value representing the Write Directory
|
|
||||||
* Exceptions
|
|
||||||
* PhysFSException - An error occured in the PhysFS API when
|
|
||||||
* settings the write directory.
|
|
||||||
*/
|
|
||||||
public static string WriteDir
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// Return the current write directory
|
|
||||||
return PhysFS_DLL.PHYSFS_getWriteDir();
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
// Set the write directory and raise an exception if an error occured
|
|
||||||
if(PhysFS_DLL.PHYSFS_setWriteDir(value) == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UserDir
|
|
||||||
* Gets or sets the write directory configured for PhysFS. See the PhysFS API
|
|
||||||
* documentation for more information.
|
|
||||||
* Parameters
|
|
||||||
* set - Path to set the WriteDir property to
|
|
||||||
* Returns
|
|
||||||
* A string value representing the Write Directory
|
|
||||||
* Exceptions
|
|
||||||
* PhysFSException - An error occured in the PhysFS API when
|
|
||||||
* settings the write directory.
|
|
||||||
*/
|
|
||||||
public static string UserDir
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// Return the current user directory
|
|
||||||
return PhysFS_DLL.PHYSFS_getUserDir();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void AddToSearchPath(string NewDir, bool Append)
|
|
||||||
{
|
|
||||||
if(PhysFS_DLL.PHYSFS_addToSearchPath(NewDir, Append?1:0) == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
public static void RemoveFromSearchPath(string OldDir)
|
|
||||||
{
|
|
||||||
if(PhysFS_DLL.PHYSFS_removeFromSearchPath(OldDir) == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
public unsafe static string[] GetSearchPath()
|
|
||||||
{
|
|
||||||
byte** p; // Searchpath list from PhysFS dll
|
|
||||||
string[] pathlist; // List converted to an array
|
|
||||||
|
|
||||||
// Get the CDROM drive listing
|
|
||||||
p = PhysFS_DLL.PHYSFS_getSearchPath();
|
|
||||||
// Convert the C-style array to a .NET style array
|
|
||||||
pathlist = PhysFS_DLL.BytePPToArray(p);
|
|
||||||
// Free the original list since we're done with it
|
|
||||||
PhysFS_DLL.PHYSFS_freeList(p);
|
|
||||||
|
|
||||||
return pathlist;
|
|
||||||
}
|
|
||||||
public unsafe static string[] GetCDROMDrives()
|
|
||||||
{
|
|
||||||
byte** p; // CDROM list from PhysFS dll
|
|
||||||
string[] cdromlist; // List converted to an array
|
|
||||||
|
|
||||||
// Get the CDROM drive listing
|
|
||||||
p = PhysFS_DLL.PHYSFS_getCdRomDirs();
|
|
||||||
// Convert the C-style array to a .NET style array
|
|
||||||
cdromlist = PhysFS_DLL.BytePPToArray(p);
|
|
||||||
// Free the original list since we're done with it
|
|
||||||
PhysFS_DLL.PHYSFS_freeList(p);
|
|
||||||
|
|
||||||
return cdromlist;
|
|
||||||
}
|
|
||||||
public static void MkDir(string Dirname)
|
|
||||||
{
|
|
||||||
if(PhysFS_DLL.PHYSFS_mkdir(Dirname) == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
public static void Delete(string Filename)
|
|
||||||
{
|
|
||||||
if(PhysFS_DLL.PHYSFS_delete(Filename) == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
public static string GetRealDir(string Filename)
|
|
||||||
{
|
|
||||||
string RetValue;
|
|
||||||
|
|
||||||
RetValue = PhysFS_DLL.PHYSFS_getRealDir(Filename);
|
|
||||||
if(RetValue == null)
|
|
||||||
throw new PhysFSException("File not found in search path.");
|
|
||||||
|
|
||||||
// Return the real file path of the specified filename
|
|
||||||
return RetValue;
|
|
||||||
}
|
|
||||||
public unsafe static string[] EnumerateFiles(string Dirname)
|
|
||||||
{
|
|
||||||
byte** p; // File list from PhysFS dll
|
|
||||||
string[] filelist; // List converted to an array
|
|
||||||
|
|
||||||
// Get the CDROM drive listing
|
|
||||||
p = PhysFS_DLL.PHYSFS_enumerateFiles(Dirname);
|
|
||||||
// Convert the C-style array to a .NET style array
|
|
||||||
filelist = PhysFS_DLL.BytePPToArray(p);
|
|
||||||
// Free the original list since we're done with it
|
|
||||||
PhysFS_DLL.PHYSFS_freeList(p);
|
|
||||||
|
|
||||||
return filelist;
|
|
||||||
}
|
|
||||||
public static bool IsDirectory(string Filename)
|
|
||||||
{
|
|
||||||
// Return true if non-zero, otherwise return false
|
|
||||||
return (PhysFS_DLL.PHYSFS_isDirectory(Filename) == 0)?false:true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
/* PhysFSFileStream.cs - (c)2003 Gregory S. Read */
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace PhysFS_NET
|
|
||||||
{
|
|
||||||
public enum PhysFSFileMode {Read, Write, Append};
|
|
||||||
|
|
||||||
// Our exception class we'll use for throwing all PhysFS API related exception
|
|
||||||
public class PhysFSException : IOException
|
|
||||||
{
|
|
||||||
public PhysFSException(string Message) : base(Message) {}
|
|
||||||
public PhysFSException() : base(PhysFS_DLL.PHYSFS_getLastError()) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe class PhysFSFileStream : Stream
|
|
||||||
{
|
|
||||||
// ***Public properties***
|
|
||||||
public override bool CanRead
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// Reading is supported
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanSeek
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// Seek is supported
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanWrite
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// Writing is supported
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Length
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
long TempLength;
|
|
||||||
TempLength = PhysFS_DLL.PHYSFS_fileLength(pHandle);
|
|
||||||
|
|
||||||
// If call returned an error, throw an exception
|
|
||||||
if(TempLength == -1)
|
|
||||||
throw new PhysFSException();
|
|
||||||
|
|
||||||
return TempLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
long TempPosition;
|
|
||||||
TempPosition = PhysFS_DLL.PHYSFS_tell(pHandle);
|
|
||||||
|
|
||||||
// If call returned an error, throw an exception
|
|
||||||
if(TempPosition == -1)
|
|
||||||
throw new PhysFSException();
|
|
||||||
|
|
||||||
return TempPosition;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
// Seek from beginning of file using the position value
|
|
||||||
Seek(value, SeekOrigin.Begin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ***Public methods***
|
|
||||||
public PhysFSFileStream(string FileName, PhysFSFileMode FileMode, ulong BufferSize)
|
|
||||||
{
|
|
||||||
// Open the specified file with the appropriate file access
|
|
||||||
switch(FileMode)
|
|
||||||
{
|
|
||||||
case PhysFSFileMode.Read:
|
|
||||||
pHandle = PhysFS_DLL.PHYSFS_openRead(FileName);
|
|
||||||
break;
|
|
||||||
case PhysFSFileMode.Write:
|
|
||||||
pHandle = PhysFS_DLL.PHYSFS_openWrite(FileName);
|
|
||||||
break;
|
|
||||||
case PhysFSFileMode.Append:
|
|
||||||
pHandle = PhysFS_DLL.PHYSFS_openAppend(FileName);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new PhysFSException("Invalid FileMode specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If handle is null, an error occured, so raise an exception
|
|
||||||
//!!! Does object get created if exception is thrown?
|
|
||||||
if(pHandle == null)
|
|
||||||
throw new PhysFSException();
|
|
||||||
|
|
||||||
// Set buffer size, raise an exception if an error occured
|
|
||||||
if(PhysFS_DLL.PHYSFS_setBuffer(pHandle, BufferSize) == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This constructor sets the buffer size to 0 if not specified
|
|
||||||
public PhysFSFileStream(string FileName, PhysFSFileMode FileMode) : this(FileName, FileMode, 0) {}
|
|
||||||
|
|
||||||
~PhysFSFileStream()
|
|
||||||
{
|
|
||||||
// Don't close the handle if they've specifically closed it already
|
|
||||||
if(!Closed)
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Flush()
|
|
||||||
{
|
|
||||||
if(PhysFS_DLL.PHYSFS_flush(pHandle) == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
long RetValue;
|
|
||||||
|
|
||||||
fixed(byte *pbytes = &buffer[offset])
|
|
||||||
{
|
|
||||||
// Read into our allocated pointer
|
|
||||||
RetValue = PhysFS_DLL.PHYSFS_read(pHandle, pbytes, sizeof(byte), (uint)count);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(RetValue == -1)
|
|
||||||
throw new PhysFSException();
|
|
||||||
|
|
||||||
// Return number of bytes read
|
|
||||||
// Note: This cast should be safe since we are only reading 'count' items, which
|
|
||||||
// is of type 'int'.
|
|
||||||
return (int)RetValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
long RetValue;
|
|
||||||
|
|
||||||
fixed(byte* pbytes = &buffer[offset])
|
|
||||||
{
|
|
||||||
// Write buffer
|
|
||||||
RetValue = PhysFS_DLL.PHYSFS_write(pHandle, pbytes, sizeof(byte), (uint)count);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(RetValue == -1)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
|
||||||
{
|
|
||||||
// Only seeking from beginning is supported by PhysFS API
|
|
||||||
if(origin != SeekOrigin.Begin)
|
|
||||||
throw new PhysFSException("Only seek origin of \"Begin\" is supported");
|
|
||||||
|
|
||||||
// Seek to specified offset, raise an exception if error occured
|
|
||||||
if(PhysFS_DLL.PHYSFS_seek(pHandle, (ulong)offset) == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
|
|
||||||
// Since we always seek from beginning, the offset is always
|
|
||||||
// the absolute position.
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetLength(long value)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("SetLength method not supported in PhysFSFileStream objects.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Close()
|
|
||||||
{
|
|
||||||
// Close the handle
|
|
||||||
if(PhysFS_DLL.PHYSFS_close(pHandle) == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
|
|
||||||
// File has been closed. Rock.
|
|
||||||
Closed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ***Private variables***
|
|
||||||
private void *pHandle;
|
|
||||||
private bool Closed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
/* PhysFS_DLL - (c)2003 Gregory S. Read
|
|
||||||
* Internal class that provides direct access to the PhysFS DLL. It is
|
|
||||||
* not accessible outside of the PhysFS.NET assembly.
|
|
||||||
*/
|
|
||||||
using System.Collections;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace PhysFS_NET
|
|
||||||
{
|
|
||||||
internal class PhysFS_DLL
|
|
||||||
{
|
|
||||||
/* Static constructor
|
|
||||||
* Initializes the PhysFS API before any method is called in this class. This
|
|
||||||
* relieves the user from having to explicitly initialize the API.
|
|
||||||
* Parameters
|
|
||||||
* none
|
|
||||||
* Returns
|
|
||||||
* none
|
|
||||||
* Exceptions
|
|
||||||
* PhysFSException - An error occured in the PhysFS API
|
|
||||||
*/
|
|
||||||
static PhysFS_DLL()
|
|
||||||
{
|
|
||||||
if(PHYSFS_init("") == 0)
|
|
||||||
throw new PhysFSException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BytePPToArray
|
|
||||||
* Converts a C-style string array into a .NET managed string array
|
|
||||||
* Parameters
|
|
||||||
* C-style string array pointer returned from PhysFS
|
|
||||||
* Returns
|
|
||||||
* .NET managed string array
|
|
||||||
* Exceptions
|
|
||||||
* none
|
|
||||||
*/
|
|
||||||
public unsafe static string[] BytePPToArray(byte **bytearray)
|
|
||||||
{
|
|
||||||
byte** ptr;
|
|
||||||
byte* c;
|
|
||||||
string tempstr;
|
|
||||||
ArrayList MyArrayList = new ArrayList();
|
|
||||||
string[] RetArray;
|
|
||||||
|
|
||||||
for(ptr = bytearray; *ptr != null; ptr++)
|
|
||||||
{
|
|
||||||
tempstr = "";
|
|
||||||
for(c = *ptr; *c != 0; c++)
|
|
||||||
{
|
|
||||||
tempstr += (char)*c;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add string to our list
|
|
||||||
MyArrayList.Add(tempstr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a normal array of the list
|
|
||||||
RetArray = new string[MyArrayList.Count];
|
|
||||||
MyArrayList.CopyTo(RetArray, 0);
|
|
||||||
return RetArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name of DLL to import
|
|
||||||
private const string PHYSFS_DLLNAME = "physfs.dll";
|
|
||||||
|
|
||||||
// DLL import declarations
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_init(string argv0);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_deinit();
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void PHYSFS_freeList(void *listVar);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getLastError();
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getDirSeparator();
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern void PHYSFS_permitSymbolicLinks(int allow);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe byte** PHYSFS_getCdRomDirs();
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getBaseDir();
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getUserDir();
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getWriteDir();
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_setWriteDir(string newDir);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_addToSearchPath(string newDir, int appendToPath);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_removeFromSearchPath(string oldDir);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe byte** PHYSFS_getSearchPath();
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_setSaneConfig(string organization,
|
|
||||||
string appName,
|
|
||||||
string archiveExt,
|
|
||||||
int includeCdRoms,
|
|
||||||
int archivesFirst);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_mkdir(string dirName);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_delete(string filename);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getRealDir(string filename);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe byte** PHYSFS_enumerateFiles(string dir);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_exists(string fname);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_isDirectory(string fname);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_isSymbolicLink(string fname);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void* PHYSFS_openWrite(string filename);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void* PHYSFS_openAppend(string filename);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void* PHYSFS_openRead(string filename);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_close(void* handle);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_getLastModTime(string filename);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_read(void* handle,
|
|
||||||
void *buffer,
|
|
||||||
uint objSize,
|
|
||||||
uint objCount);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_write(void* handle,
|
|
||||||
void *buffer,
|
|
||||||
uint objSize,
|
|
||||||
uint objCount);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_eof(void* handle);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_tell(void* handle);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_seek(void* handle, ulong pos);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_fileLength(void* handle);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_setBuffer(void* handle, ulong bufsize);
|
|
||||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_flush(void* handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
PhysFS.NET is a library that encapsulates the PhysFS API into a .NET assembly.
|
|
||||||
|
|
||||||
There are two class objects that are exposed in the assembly:
|
|
||||||
PhysFS.cs
|
|
||||||
This class exposes any non-filehandle specific functionality contained in
|
|
||||||
the PhysFS library.
|
|
||||||
PhysFSFileStream.cs
|
|
||||||
A System.IO.Stream derived class which provides file access via the
|
|
||||||
PhysFS API. Usage of this object is identical to a standard stream
|
|
||||||
object.
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,58 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
//
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
//
|
|
||||||
[assembly: AssemblyTitle("")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("")]
|
|
||||||
[assembly: AssemblyCopyright("")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
|
|
||||||
//
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Revision and Build Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.0.*")]
|
|
||||||
|
|
||||||
//
|
|
||||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
|
||||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
|
||||||
//
|
|
||||||
// Use the attributes below to control which key is used for signing.
|
|
||||||
//
|
|
||||||
// Notes:
|
|
||||||
// (*) If no key is specified, the assembly is not signed.
|
|
||||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
|
||||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
|
||||||
// a key.
|
|
||||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
|
||||||
// following processing occurs:
|
|
||||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
|
||||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
|
||||||
// in the KeyFile is installed into the CSP and used.
|
|
||||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
|
||||||
// When specifying the KeyFile, the location of the KeyFile should be
|
|
||||||
// relative to the project output directory which is
|
|
||||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
|
||||||
// located in the project directory, you would specify the AssemblyKeyFile
|
|
||||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
|
||||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
|
||||||
// documentation for more information on this.
|
|
||||||
//
|
|
||||||
[assembly: AssemblyDelaySign(false)]
|
|
||||||
[assembly: AssemblyKeyFile("")]
|
|
||||||
[assembly: AssemblyKeyName("")]
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
<VisualStudioProject>
|
|
||||||
<CSHARP
|
|
||||||
ProjectType = "Local"
|
|
||||||
ProductVersion = "7.0.9466"
|
|
||||||
SchemaVersion = "1.0"
|
|
||||||
ProjectGuid = "{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}"
|
|
||||||
>
|
|
||||||
<Build>
|
|
||||||
<Settings
|
|
||||||
ApplicationIcon = "App.ico"
|
|
||||||
AssemblyKeyContainerName = ""
|
|
||||||
AssemblyName = "TestApp"
|
|
||||||
AssemblyOriginatorKeyFile = ""
|
|
||||||
DefaultClientScript = "JScript"
|
|
||||||
DefaultHTMLPageLayout = "Grid"
|
|
||||||
DefaultTargetSchema = "IE50"
|
|
||||||
DelaySign = "false"
|
|
||||||
OutputType = "WinExe"
|
|
||||||
RootNamespace = "TestApp"
|
|
||||||
StartupObject = ""
|
|
||||||
>
|
|
||||||
<Config
|
|
||||||
Name = "Debug"
|
|
||||||
AllowUnsafeBlocks = "false"
|
|
||||||
BaseAddress = "285212672"
|
|
||||||
CheckForOverflowUnderflow = "false"
|
|
||||||
ConfigurationOverrideFile = ""
|
|
||||||
DefineConstants = "DEBUG;TRACE"
|
|
||||||
DocumentationFile = ""
|
|
||||||
DebugSymbols = "true"
|
|
||||||
FileAlignment = "4096"
|
|
||||||
IncrementalBuild = "true"
|
|
||||||
Optimize = "false"
|
|
||||||
OutputPath = "bin\Debug\"
|
|
||||||
RegisterForComInterop = "false"
|
|
||||||
RemoveIntegerChecks = "false"
|
|
||||||
TreatWarningsAsErrors = "false"
|
|
||||||
WarningLevel = "4"
|
|
||||||
/>
|
|
||||||
<Config
|
|
||||||
Name = "Release"
|
|
||||||
AllowUnsafeBlocks = "false"
|
|
||||||
BaseAddress = "285212672"
|
|
||||||
CheckForOverflowUnderflow = "false"
|
|
||||||
ConfigurationOverrideFile = ""
|
|
||||||
DefineConstants = "TRACE"
|
|
||||||
DocumentationFile = ""
|
|
||||||
DebugSymbols = "false"
|
|
||||||
FileAlignment = "4096"
|
|
||||||
IncrementalBuild = "false"
|
|
||||||
Optimize = "true"
|
|
||||||
OutputPath = "bin\Release\"
|
|
||||||
RegisterForComInterop = "false"
|
|
||||||
RemoveIntegerChecks = "false"
|
|
||||||
TreatWarningsAsErrors = "false"
|
|
||||||
WarningLevel = "4"
|
|
||||||
/>
|
|
||||||
</Settings>
|
|
||||||
<References>
|
|
||||||
<Reference
|
|
||||||
Name = "System"
|
|
||||||
AssemblyName = "System"
|
|
||||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
|
|
||||||
/>
|
|
||||||
<Reference
|
|
||||||
Name = "System.Data"
|
|
||||||
AssemblyName = "System.Data"
|
|
||||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
|
|
||||||
/>
|
|
||||||
<Reference
|
|
||||||
Name = "System.Drawing"
|
|
||||||
AssemblyName = "System.Drawing"
|
|
||||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
|
|
||||||
/>
|
|
||||||
<Reference
|
|
||||||
Name = "System.Windows.Forms"
|
|
||||||
AssemblyName = "System.Windows.Forms"
|
|
||||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"
|
|
||||||
/>
|
|
||||||
<Reference
|
|
||||||
Name = "System.XML"
|
|
||||||
AssemblyName = "System.Xml"
|
|
||||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
|
|
||||||
/>
|
|
||||||
<Reference
|
|
||||||
Name = "PhysFS.NET"
|
|
||||||
Project = "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
|
||||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
|
||||||
/>
|
|
||||||
</References>
|
|
||||||
</Build>
|
|
||||||
<Files>
|
|
||||||
<Include>
|
|
||||||
<File
|
|
||||||
RelPath = "App.ico"
|
|
||||||
BuildAction = "Content"
|
|
||||||
/>
|
|
||||||
<File
|
|
||||||
RelPath = "AssemblyInfo.cs"
|
|
||||||
BuildAction = "Compile"
|
|
||||||
/>
|
|
||||||
<File
|
|
||||||
RelPath = "TestAppForm.cs"
|
|
||||||
SubType = "Form"
|
|
||||||
BuildAction = "Compile"
|
|
||||||
/>
|
|
||||||
<File
|
|
||||||
RelPath = "TestAppForm.resx"
|
|
||||||
DependentUpon = "TestAppForm.cs"
|
|
||||||
BuildAction = "EmbeddedResource"
|
|
||||||
/>
|
|
||||||
</Include>
|
|
||||||
</Files>
|
|
||||||
</CSHARP>
|
|
||||||
</VisualStudioProject>
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 7.00
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp.csproj", "{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysFS.NET", "..\PhysFS.NET.csproj", "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfiguration) = preSolution
|
|
||||||
ConfigName.0 = Debug
|
|
||||||
ConfigName.1 = Release
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectDependencies) = postSolution
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfiguration) = postSolution
|
|
||||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Debug.ActiveCfg = Debug|.NET
|
|
||||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Debug.Build.0 = Debug|.NET
|
|
||||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Release.ActiveCfg = Release|.NET
|
|
||||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Release.Build.0 = Release|.NET
|
|
||||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.ActiveCfg = Debug|.NET
|
|
||||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.Build.0 = Debug|.NET
|
|
||||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.ActiveCfg = Release|.NET
|
|
||||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.Build.0 = Release|.NET
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Collections;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using System.Data;
|
|
||||||
using System.IO;
|
|
||||||
using PhysFS_NET;
|
|
||||||
|
|
||||||
namespace TestApp
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Summary description for Form1.
|
|
||||||
/// </summary>
|
|
||||||
public class TestAppForm : System.Windows.Forms.Form
|
|
||||||
{
|
|
||||||
private System.Windows.Forms.Label label2;
|
|
||||||
private System.Windows.Forms.Button RefreshCDsButton;
|
|
||||||
private System.Windows.Forms.ListBox CDDrivesList;
|
|
||||||
private System.Windows.Forms.ListBox SearchPathList;
|
|
||||||
private System.Windows.Forms.Label label1;
|
|
||||||
private System.Windows.Forms.TextBox EnumFilesPath;
|
|
||||||
private System.Windows.Forms.ListBox EnumList;
|
|
||||||
private System.Windows.Forms.Label label3;
|
|
||||||
private System.Windows.Forms.TextBox NewSearchPathText;
|
|
||||||
private System.Windows.Forms.Button AddSearchPathButton;
|
|
||||||
private System.Windows.Forms.Button RemovePathButton;
|
|
||||||
private System.Windows.Forms.Button RefreshEnumList;
|
|
||||||
private System.Windows.Forms.Button RefreshSearchPathButton;
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.Container components = null;
|
|
||||||
|
|
||||||
public TestAppForm()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Required for Windows Form Designer support
|
|
||||||
//
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
//
|
|
||||||
// TODO: Add any constructor code after InitializeComponent call
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
protected override void Dispose( bool disposing )
|
|
||||||
{
|
|
||||||
if( disposing )
|
|
||||||
{
|
|
||||||
if (components != null)
|
|
||||||
{
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base.Dispose( disposing );
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Windows Form Designer generated code
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent()
|
|
||||||
{
|
|
||||||
this.label2 = new System.Windows.Forms.Label();
|
|
||||||
this.RefreshCDsButton = new System.Windows.Forms.Button();
|
|
||||||
this.CDDrivesList = new System.Windows.Forms.ListBox();
|
|
||||||
this.SearchPathList = new System.Windows.Forms.ListBox();
|
|
||||||
this.label1 = new System.Windows.Forms.Label();
|
|
||||||
this.EnumFilesPath = new System.Windows.Forms.TextBox();
|
|
||||||
this.EnumList = new System.Windows.Forms.ListBox();
|
|
||||||
this.label3 = new System.Windows.Forms.Label();
|
|
||||||
this.RefreshEnumList = new System.Windows.Forms.Button();
|
|
||||||
this.NewSearchPathText = new System.Windows.Forms.TextBox();
|
|
||||||
this.AddSearchPathButton = new System.Windows.Forms.Button();
|
|
||||||
this.RemovePathButton = new System.Windows.Forms.Button();
|
|
||||||
this.RefreshSearchPathButton = new System.Windows.Forms.Button();
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// label2
|
|
||||||
//
|
|
||||||
this.label2.Location = new System.Drawing.Point(8, 8);
|
|
||||||
this.label2.Name = "label2";
|
|
||||||
this.label2.Size = new System.Drawing.Size(136, 16);
|
|
||||||
this.label2.TabIndex = 2;
|
|
||||||
this.label2.Text = "Available CD-ROM Drives";
|
|
||||||
//
|
|
||||||
// RefreshCDsButton
|
|
||||||
//
|
|
||||||
this.RefreshCDsButton.Location = new System.Drawing.Point(8, 152);
|
|
||||||
this.RefreshCDsButton.Name = "RefreshCDsButton";
|
|
||||||
this.RefreshCDsButton.Size = new System.Drawing.Size(72, 24);
|
|
||||||
this.RefreshCDsButton.TabIndex = 4;
|
|
||||||
this.RefreshCDsButton.Text = "Refresh";
|
|
||||||
this.RefreshCDsButton.Click += new System.EventHandler(this.RefreshCDsButton_Click);
|
|
||||||
//
|
|
||||||
// CDDrivesList
|
|
||||||
//
|
|
||||||
this.CDDrivesList.Location = new System.Drawing.Point(8, 24);
|
|
||||||
this.CDDrivesList.Name = "CDDrivesList";
|
|
||||||
this.CDDrivesList.Size = new System.Drawing.Size(136, 121);
|
|
||||||
this.CDDrivesList.TabIndex = 7;
|
|
||||||
//
|
|
||||||
// SearchPathList
|
|
||||||
//
|
|
||||||
this.SearchPathList.Location = new System.Drawing.Point(152, 24);
|
|
||||||
this.SearchPathList.Name = "SearchPathList";
|
|
||||||
this.SearchPathList.Size = new System.Drawing.Size(248, 95);
|
|
||||||
this.SearchPathList.TabIndex = 8;
|
|
||||||
//
|
|
||||||
// label1
|
|
||||||
//
|
|
||||||
this.label1.Location = new System.Drawing.Point(152, 8);
|
|
||||||
this.label1.Name = "label1";
|
|
||||||
this.label1.Size = new System.Drawing.Size(136, 16);
|
|
||||||
this.label1.TabIndex = 10;
|
|
||||||
this.label1.Text = "Search Path";
|
|
||||||
//
|
|
||||||
// EnumFilesPath
|
|
||||||
//
|
|
||||||
this.EnumFilesPath.Location = new System.Drawing.Point(408, 128);
|
|
||||||
this.EnumFilesPath.Name = "EnumFilesPath";
|
|
||||||
this.EnumFilesPath.Size = new System.Drawing.Size(208, 20);
|
|
||||||
this.EnumFilesPath.TabIndex = 11;
|
|
||||||
this.EnumFilesPath.Text = "";
|
|
||||||
//
|
|
||||||
// EnumList
|
|
||||||
//
|
|
||||||
this.EnumList.Location = new System.Drawing.Point(408, 24);
|
|
||||||
this.EnumList.Name = "EnumList";
|
|
||||||
this.EnumList.Size = new System.Drawing.Size(208, 95);
|
|
||||||
this.EnumList.TabIndex = 12;
|
|
||||||
//
|
|
||||||
// label3
|
|
||||||
//
|
|
||||||
this.label3.Location = new System.Drawing.Point(408, 8);
|
|
||||||
this.label3.Name = "label3";
|
|
||||||
this.label3.Size = new System.Drawing.Size(136, 16);
|
|
||||||
this.label3.TabIndex = 13;
|
|
||||||
this.label3.Text = "Enumerate Files";
|
|
||||||
//
|
|
||||||
// RefreshEnumList
|
|
||||||
//
|
|
||||||
this.RefreshEnumList.Location = new System.Drawing.Point(544, 152);
|
|
||||||
this.RefreshEnumList.Name = "RefreshEnumList";
|
|
||||||
this.RefreshEnumList.Size = new System.Drawing.Size(72, 24);
|
|
||||||
this.RefreshEnumList.TabIndex = 14;
|
|
||||||
this.RefreshEnumList.Text = "Refresh";
|
|
||||||
this.RefreshEnumList.Click += new System.EventHandler(this.RefreshEnumList_Click);
|
|
||||||
//
|
|
||||||
// NewSearchPathText
|
|
||||||
//
|
|
||||||
this.NewSearchPathText.Location = new System.Drawing.Point(152, 128);
|
|
||||||
this.NewSearchPathText.Name = "NewSearchPathText";
|
|
||||||
this.NewSearchPathText.Size = new System.Drawing.Size(248, 20);
|
|
||||||
this.NewSearchPathText.TabIndex = 15;
|
|
||||||
this.NewSearchPathText.Text = "";
|
|
||||||
//
|
|
||||||
// AddSearchPathButton
|
|
||||||
//
|
|
||||||
this.AddSearchPathButton.Location = new System.Drawing.Point(152, 152);
|
|
||||||
this.AddSearchPathButton.Name = "AddSearchPathButton";
|
|
||||||
this.AddSearchPathButton.Size = new System.Drawing.Size(72, 24);
|
|
||||||
this.AddSearchPathButton.TabIndex = 9;
|
|
||||||
this.AddSearchPathButton.Text = "Add Path";
|
|
||||||
this.AddSearchPathButton.Click += new System.EventHandler(this.AddSearchPathButton_Click);
|
|
||||||
//
|
|
||||||
// RemovePathButton
|
|
||||||
//
|
|
||||||
this.RemovePathButton.Location = new System.Drawing.Point(232, 152);
|
|
||||||
this.RemovePathButton.Name = "RemovePathButton";
|
|
||||||
this.RemovePathButton.Size = new System.Drawing.Size(88, 24);
|
|
||||||
this.RemovePathButton.TabIndex = 16;
|
|
||||||
this.RemovePathButton.Text = "Remove Path";
|
|
||||||
this.RemovePathButton.Click += new System.EventHandler(this.RemovePathButton_Click);
|
|
||||||
//
|
|
||||||
// RefreshSearchPathButton
|
|
||||||
//
|
|
||||||
this.RefreshSearchPathButton.Location = new System.Drawing.Point(328, 152);
|
|
||||||
this.RefreshSearchPathButton.Name = "RefreshSearchPathButton";
|
|
||||||
this.RefreshSearchPathButton.Size = new System.Drawing.Size(72, 24);
|
|
||||||
this.RefreshSearchPathButton.TabIndex = 17;
|
|
||||||
this.RefreshSearchPathButton.Text = "Refresh";
|
|
||||||
this.RefreshSearchPathButton.Click += new System.EventHandler(this.RefreshSearchPathButton_Click);
|
|
||||||
//
|
|
||||||
// TestAppForm
|
|
||||||
//
|
|
||||||
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
|
|
||||||
this.ClientSize = new System.Drawing.Size(624, 309);
|
|
||||||
this.Controls.AddRange(new System.Windows.Forms.Control[] {
|
|
||||||
this.RefreshSearchPathButton,
|
|
||||||
this.RemovePathButton,
|
|
||||||
this.NewSearchPathText,
|
|
||||||
this.RefreshEnumList,
|
|
||||||
this.label3,
|
|
||||||
this.EnumList,
|
|
||||||
this.EnumFilesPath,
|
|
||||||
this.label1,
|
|
||||||
this.SearchPathList,
|
|
||||||
this.CDDrivesList,
|
|
||||||
this.RefreshCDsButton,
|
|
||||||
this.label2,
|
|
||||||
this.AddSearchPathButton});
|
|
||||||
this.Name = "TestAppForm";
|
|
||||||
this.Text = "PhysFS Test Application";
|
|
||||||
this.Load += new System.EventHandler(this.TestAppForm_Load);
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The main entry point for the application.
|
|
||||||
/// </summary>
|
|
||||||
[STAThread]
|
|
||||||
static void Main()
|
|
||||||
{
|
|
||||||
Application.Run(new TestAppForm());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TestAppForm_Load(object sender, System.EventArgs e)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RefreshCDsButton_Click(object sender, System.EventArgs e)
|
|
||||||
{
|
|
||||||
// Clear ths listbox if it contains any items
|
|
||||||
CDDrivesList.Items.Clear();
|
|
||||||
// Add the items to the list
|
|
||||||
CDDrivesList.Items.AddRange(PhysFS.GetCDROMDrives());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RefreshSearchPathButton_Click(object sender, System.EventArgs e)
|
|
||||||
{
|
|
||||||
// Clear ths listbox if it contains any items
|
|
||||||
SearchPathList.Items.Clear();
|
|
||||||
// Add the items to the list
|
|
||||||
SearchPathList.Items.AddRange(PhysFS.GetSearchPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddSearchPathButton_Click(object sender, System.EventArgs e)
|
|
||||||
{
|
|
||||||
// Add search path
|
|
||||||
PhysFS.AddToSearchPath(NewSearchPathText.Text, false);
|
|
||||||
// Clear ths listbox if it contains any items
|
|
||||||
SearchPathList.Items.Clear();
|
|
||||||
// Add the items to the list
|
|
||||||
SearchPathList.Items.AddRange(PhysFS.GetSearchPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RemovePathButton_Click(object sender, System.EventArgs e)
|
|
||||||
{
|
|
||||||
if(SearchPathList.SelectedItem != null)
|
|
||||||
{
|
|
||||||
PhysFS.RemoveFromSearchPath(SearchPathList.SelectedItem.ToString());
|
|
||||||
// Clear ths listbox if it contains any items
|
|
||||||
SearchPathList.Items.Clear();
|
|
||||||
// Add the items to the list
|
|
||||||
SearchPathList.Items.AddRange(PhysFS.GetSearchPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RefreshEnumList_Click(object sender, System.EventArgs e)
|
|
||||||
{
|
|
||||||
EnumList.Items.Clear();
|
|
||||||
EnumList.Items.AddRange(PhysFS.EnumerateFiles(EnumFilesPath.Text));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 1.3
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">1.3</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1">this is my long string</data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
[base64 mime encoded serialized .NET Framework object]
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>1.3</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<data name="$this.Name">
|
|
||||||
<value>TestAppForm</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/** \file globbing.c */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "physfs.h"
|
|
||||||
#include "globbing.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Please see globbing.h for details.
|
|
||||||
*
|
|
||||||
* License: this code is public domain. I make no warranty that it is useful,
|
|
||||||
* correct, harmless, or environmentally safe.
|
|
||||||
*
|
|
||||||
* This particular file may be used however you like, including copying it
|
|
||||||
* verbatim into a closed-source project, exploiting it commercially, and
|
|
||||||
* removing any trace of my name from the source (although I hope you won't
|
|
||||||
* do that). I welcome enhancements and corrections to this file, but I do
|
|
||||||
* not require you to send me patches if you make changes. This code has
|
|
||||||
* NO WARRANTY.
|
|
||||||
*
|
|
||||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
|
||||||
* Please see LICENSE.txt in the root of the source tree.
|
|
||||||
*
|
|
||||||
* \author Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
static int matchesPattern(const char *fname, const char *wildcard,
|
|
||||||
int caseSensitive)
|
|
||||||
{
|
|
||||||
char x, y;
|
|
||||||
const char *fnameptr = fname;
|
|
||||||
const char *wildptr = wildcard;
|
|
||||||
|
|
||||||
while ((*wildptr) && (*fnameptr))
|
|
||||||
{
|
|
||||||
y = *wildptr;
|
|
||||||
if (y == '*')
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
wildptr++; /* skip multiple '*' in a row... */
|
|
||||||
} while (*wildptr == '*');
|
|
||||||
|
|
||||||
y = (caseSensitive) ? *wildptr : (char) tolower(*wildptr);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
x = (caseSensitive) ? *fnameptr : (char) tolower(*fnameptr);
|
|
||||||
if ((!x) || (x == y))
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
fnameptr++;
|
|
||||||
} /* while */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
else if (y == '?')
|
|
||||||
{
|
|
||||||
wildptr++;
|
|
||||||
fnameptr++;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (caseSensitive)
|
|
||||||
x = *fnameptr;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = tolower(*fnameptr);
|
|
||||||
y = tolower(y);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
wildptr++;
|
|
||||||
fnameptr++;
|
|
||||||
|
|
||||||
if (x != y)
|
|
||||||
return(0);
|
|
||||||
} /* else */
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
while (*wildptr == '*')
|
|
||||||
wildptr++;
|
|
||||||
|
|
||||||
return(*fnameptr == *wildptr);
|
|
||||||
} /* matchesPattern */
|
|
||||||
|
|
||||||
|
|
||||||
char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, const char *wildcard,
|
|
||||||
int caseSensitive)
|
|
||||||
{
|
|
||||||
char **rc = PHYSFS_enumerateFiles(dir);
|
|
||||||
char **i = rc;
|
|
||||||
char **j;
|
|
||||||
|
|
||||||
while (*i != NULL)
|
|
||||||
{
|
|
||||||
if (matchesPattern(*i, wildcard, caseSensitive))
|
|
||||||
i++;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME: This counts on physfs's allocation method not changing! */
|
|
||||||
free(*i);
|
|
||||||
for (j = i; *j != NULL; j++)
|
|
||||||
j[0] = j[1];
|
|
||||||
} /* else */
|
|
||||||
} /* for */
|
|
||||||
|
|
||||||
return(rc);
|
|
||||||
} /* PHYSFSEXT_enumerateFilesWildcard */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST_PHYSFSEXT_ENUMERATEFILESWILDCARD
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char **flist;
|
|
||||||
char **i;
|
|
||||||
|
|
||||||
if (argc != 3)
|
|
||||||
{
|
|
||||||
printf("USAGE: %s <pattern> <caseSen>\n"
|
|
||||||
" where <caseSen> is 1 or 0.\n", argv[0]);
|
|
||||||
return(1);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (!PHYSFS_init(argv[0]))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getLastError());
|
|
||||||
return(1);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (!PHYSFS_addToSearchPath(".", 1))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getLastError());
|
|
||||||
PHYSFS_deinit();
|
|
||||||
return(1);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
flist = PHYSFSEXT_enumerateFilesWildcard("/", argv[1], atoi(argv[2]));
|
|
||||||
rc = 0;
|
|
||||||
for (i = flist; *i; i++)
|
|
||||||
{
|
|
||||||
printf("%s\n", *i);
|
|
||||||
rc++;
|
|
||||||
} /* for */
|
|
||||||
printf("\n total %d files.\n\n", rc);
|
|
||||||
|
|
||||||
PHYSFS_freeList(flist);
|
|
||||||
PHYSFS_deinit();
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
} /* main */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* end of globbing.c ... */
|
|
||||||
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
#ifndef INCL_PHYSFSEXT_GLOBBING_H
|
|
||||||
#define INCL_PHYSFSEXT_GLOBBING_H
|
|
||||||
|
|
||||||
/** \file globbing.h */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \mainpage PhysicsFS globbing
|
|
||||||
*
|
|
||||||
* This is an extension to PhysicsFS to let you search for files with basic
|
|
||||||
* wildcard matching, regardless of what sort of filesystem or archive they
|
|
||||||
* reside in. It does this by enumerating directories as needed and manually
|
|
||||||
* locating matching entries.
|
|
||||||
*
|
|
||||||
* Usage: Set up PhysicsFS as you normally would, then use
|
|
||||||
* PHYSFSEXT_enumerateFilesPattern() when enumerating files. This is just
|
|
||||||
* like PHYSFS_enumerateFiles(), but it returns a subset that matches your
|
|
||||||
* wildcard pattern. You must call PHYSFS_freeList() on the results, just
|
|
||||||
* like you would with PHYSFS_enumerateFiles().
|
|
||||||
*
|
|
||||||
* License: this code is public domain. I make no warranty that it is useful,
|
|
||||||
* correct, harmless, or environmentally safe.
|
|
||||||
*
|
|
||||||
* This particular file may be used however you like, including copying it
|
|
||||||
* verbatim into a closed-source project, exploiting it commercially, and
|
|
||||||
* removing any trace of my name from the source (although I hope you won't
|
|
||||||
* do that). I welcome enhancements and corrections to this file, but I do
|
|
||||||
* not require you to send me patches if you make changes. This code has
|
|
||||||
* NO WARRANTY.
|
|
||||||
*
|
|
||||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
|
||||||
* Please see LICENSE.txt in the root of the source tree.
|
|
||||||
*
|
|
||||||
* \author Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \fn char **PHYSFS_enumerateFilesWildcard(const char *dir, const char *wildcard, int caseSensitive)
|
|
||||||
* \brief Get a file listing of a search path's directory.
|
|
||||||
*
|
|
||||||
* Matching directories are interpolated. That is, if "C:\mydir" is in the
|
|
||||||
* search path and contains a directory "savegames" that contains "x.sav",
|
|
||||||
* "y.Sav", and "z.txt", and there is also a "C:\userdir" in the search path
|
|
||||||
* that has a "savegames" subdirectory with "w.sav", then the following code:
|
|
||||||
*
|
|
||||||
* \code
|
|
||||||
* char **rc = PHYSFS_enumerateFilesWildcard("savegames", "*.sav", 0);
|
|
||||||
* char **i;
|
|
||||||
*
|
|
||||||
* for (i = rc; *i != NULL; i++)
|
|
||||||
* printf(" * We've got [%s].\n", *i);
|
|
||||||
*
|
|
||||||
* PHYSFS_freeList(rc);
|
|
||||||
* \endcode
|
|
||||||
*
|
|
||||||
* ...will print:
|
|
||||||
*
|
|
||||||
* \verbatim
|
|
||||||
* We've got [x.sav].
|
|
||||||
* We've got [y.Sav].
|
|
||||||
* We've got [w.sav].\endverbatim
|
|
||||||
*
|
|
||||||
* Feel free to sort the list however you like. We only promise there will
|
|
||||||
* be no duplicates, but not what order the final list will come back in.
|
|
||||||
*
|
|
||||||
* Wildcard strings can use the '*' and '?' characters, currently.
|
|
||||||
* Matches can be case-insensitive if you pass a zero for argument 3.
|
|
||||||
*
|
|
||||||
* Don't forget to call PHYSFS_freeList() with the return value from this
|
|
||||||
* function when you are done with it.
|
|
||||||
*
|
|
||||||
* \param dir directory in platform-independent notation to enumerate.
|
|
||||||
* \return Null-terminated array of null-terminated strings.
|
|
||||||
*/
|
|
||||||
__EXPORT__ char **PHYSFSEXT_enumerateFilesWildcard(const char *dir,
|
|
||||||
const char *wildcard,
|
|
||||||
int caseSensitive);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* include-once blocker. */
|
|
||||||
|
|
||||||
/* end of globbing.h ... */
|
|
||||||
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
#!/usr/bin/perl -w
|
|
||||||
|
|
||||||
use warnings;
|
|
||||||
use strict;
|
|
||||||
|
|
||||||
print <<__EOF__;
|
|
||||||
/*
|
|
||||||
* This file is part of PhysicsFS (http://icculus.org/physfs/)
|
|
||||||
*
|
|
||||||
* This data generated by physfs/extras/makecasefoldhashtable.pl ...
|
|
||||||
* Do not manually edit this file!
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __PHYSICSFS_INTERNAL__
|
|
||||||
#error Do not include this header from your applications.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__EOF__
|
|
||||||
|
|
||||||
|
|
||||||
my @foldPairs;
|
|
||||||
|
|
||||||
for (my $i = 0; $i < 256; $i++) {
|
|
||||||
$foldPairs[$i] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
open(FH,'<','casefolding.txt') or die("failed to open casefolding.txt: $!\n");
|
|
||||||
while (<FH>) {
|
|
||||||
chomp;
|
|
||||||
# strip comments from textfile...
|
|
||||||
s/\#.*\Z//;
|
|
||||||
|
|
||||||
# strip whitespace...
|
|
||||||
s/\A\s+//;
|
|
||||||
s/\s+\Z//;
|
|
||||||
|
|
||||||
next if not /\A([a-fA-F0-9]+)\;\s*(.)\;\s*(.+)\;/;
|
|
||||||
my ($code, $status, $mapping) = ($1, $2, $3);
|
|
||||||
my $hexxed = hex($code);
|
|
||||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & 0xFF);
|
|
||||||
#print("// code '$code' status '$status' mapping '$mapping'\n");
|
|
||||||
#print("// hexxed '$hexxed' hashed '$hashed'\n");
|
|
||||||
|
|
||||||
if (($status eq 'C') or ($status eq 'F')) {
|
|
||||||
my ($map1, $map2, $map3) = ('0000', '0000', '0000');
|
|
||||||
$map1 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
|
||||||
$map2 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
|
||||||
$map3 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
|
||||||
die("mapping space too small for '$code'\n") if ($mapping ne '');
|
|
||||||
$foldPairs[$hashed] .= " { 0x$code, 0x$map1, 0x$map2, 0x$map3 },\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(FH);
|
|
||||||
|
|
||||||
for (my $i = 0; $i < 256; $i++) {
|
|
||||||
$foldPairs[$i] =~ s/,\n\Z//;
|
|
||||||
my $str = $foldPairs[$i];
|
|
||||||
next if $str eq '';
|
|
||||||
my $num = '000' . $i;
|
|
||||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
|
||||||
my $sym = "case_fold_${num}";
|
|
||||||
print("static const CaseFoldMapping ${sym}[] = {\n$str\n};\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
print("\nstatic const CaseFoldHashBucket case_fold_hash[256] = {\n");
|
|
||||||
|
|
||||||
for (my $i = 0; $i < 256; $i++) {
|
|
||||||
my $str = $foldPairs[$i];
|
|
||||||
if ($str eq '') {
|
|
||||||
print(" { 0, NULL },\n");
|
|
||||||
} else {
|
|
||||||
my $num = '000' . $i;
|
|
||||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
|
||||||
my $sym = "case_fold_${num}";
|
|
||||||
print(" { __PHYSFS_ARRAYLEN($sym), $sym },\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print("};\n\n");
|
|
||||||
|
|
||||||
exit 0;
|
|
||||||
|
|
||||||
# end of makecashfoldhashtable.pl ...
|
|
||||||
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
# $Id: installer.rb,v 1.3 2003/07/21 03:46:50 icculus Exp $
|
|
||||||
|
|
||||||
require 'rbconfig'
|
|
||||||
require 'find'
|
|
||||||
require 'ftools'
|
|
||||||
|
|
||||||
include Config
|
|
||||||
|
|
||||||
module Slimb
|
|
||||||
class Installer
|
|
||||||
def initialize target_dir = "", &user_skip
|
|
||||||
@user_skip = user_skip or proc {|f| false}
|
|
||||||
|
|
||||||
@version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
|
|
||||||
@libdir = File.join(CONFIG["libdir"], "ruby", @version)
|
|
||||||
@sitedir = CONFIG["sitedir"] || File.join(@libdir, "site_ruby")
|
|
||||||
@dest = File.join @sitedir, target_dir
|
|
||||||
|
|
||||||
File::makedirs @dest
|
|
||||||
File::chmod 0755, @dest, true
|
|
||||||
end
|
|
||||||
|
|
||||||
def skip? file
|
|
||||||
@user_skip[file] or
|
|
||||||
file[0] == ?. or file[-1] == ?~ or file[-1] == ?#
|
|
||||||
end
|
|
||||||
|
|
||||||
def install_dir dir
|
|
||||||
File::makedirs(File.join(@dest, dir))
|
|
||||||
File::chmod(0755, File.join(@dest, dir), true)
|
|
||||||
Dir.foreach(dir) {|file|
|
|
||||||
next if skip? file
|
|
||||||
|
|
||||||
if File.ftype(File.join(dir, file)) == "directory"
|
|
||||||
install_dir File.join(dir, file)
|
|
||||||
else
|
|
||||||
install_file File.join(dir, file)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def install_file file
|
|
||||||
if file =~ /\.so$/
|
|
||||||
install_so file
|
|
||||||
else
|
|
||||||
File::install file, File.join(@dest, file), 0644, true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def install_so file
|
|
||||||
File::install file, File.join(CONFIG["sitearchdir"], file), 0644, true
|
|
||||||
end
|
|
||||||
|
|
||||||
def uninstall_so file
|
|
||||||
file = File.join(CONFIG["sitearchdir"], file)
|
|
||||||
File::safe_unlink file
|
|
||||||
end
|
|
||||||
|
|
||||||
def install something
|
|
||||||
case something
|
|
||||||
when Array
|
|
||||||
something.each {|x|
|
|
||||||
install x if x.is_a? String
|
|
||||||
}
|
|
||||||
when String
|
|
||||||
if File.ftype(something) == "directory"
|
|
||||||
install_dir something
|
|
||||||
else
|
|
||||||
install_file something
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def uninstall what = "*"
|
|
||||||
case what
|
|
||||||
when Array
|
|
||||||
files = what.map {|x| File.join(@dest, x)}
|
|
||||||
when String
|
|
||||||
files = Dir[File.join(@dest, what)]
|
|
||||||
end
|
|
||||||
|
|
||||||
files.each {|x|
|
|
||||||
# FIXME: recursive uninstall is a must
|
|
||||||
next if FileTest.directory? x
|
|
||||||
File::safe_unlink x
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def run files, argv
|
|
||||||
if !argv.grep(/--uninstall/).empty?
|
|
||||||
uninstall files
|
|
||||||
else
|
|
||||||
install files
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# self-installation
|
|
||||||
if $0 == __FILE__
|
|
||||||
$stderr.puts "Installing slimb installer..."
|
|
||||||
Slimb::Installer.new("slimb").install File.basename(__FILE__)
|
|
||||||
end
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
require 'mkmf'
|
|
||||||
|
|
||||||
$CFLAGS += `sdl-config --cflags`.chomp
|
|
||||||
$LDFLAGS += `sdl-config --libs`.chomp
|
|
||||||
|
|
||||||
have_library "physfs", "PHYSFS_init"
|
|
||||||
have_library "SDL", "SDL_AllocRW"
|
|
||||||
|
|
||||||
create_makefile "physfs_so"
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/usr/local/bin/ruby
|
|
||||||
|
|
||||||
if __FILE__ == $0
|
|
||||||
require 'slimb/installer'
|
|
||||||
files = ["physfs.rb", "physfs_so.so"]
|
|
||||||
installer = Slimb::Installer.new.run files, ARGV
|
|
||||||
end
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
ruby extconf.rb
|
|
||||||
make
|
|
||||||
cd ..
|
|
||||||
ruby installer.rb
|
|
||||||
cd physfs
|
|
||||||
ruby install.rb
|
|
||||||
cd test
|
|
||||||
ruby test_physfs.rb
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
#
|
|
||||||
# PhysicsFS - ruby interface
|
|
||||||
#
|
|
||||||
# Author: Ed Sinjiashvili (slimb@vlinkmail.com)
|
|
||||||
# License: LGPL
|
|
||||||
#
|
|
||||||
|
|
||||||
require 'physfs_so'
|
|
||||||
|
|
||||||
module PhysicsFS
|
|
||||||
|
|
||||||
class Version
|
|
||||||
def initialize major, minor, patch
|
|
||||||
@major = major
|
|
||||||
@minor = minor
|
|
||||||
@patch = patch
|
|
||||||
end
|
|
||||||
|
|
||||||
attr_reader :major, :minor, :patch
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
"#@major.#@minor.#@patch"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class ArchiveInfo
|
|
||||||
def initialize ext, desc, author, url
|
|
||||||
@extension = ext
|
|
||||||
@description = desc
|
|
||||||
@author = author
|
|
||||||
@url = url
|
|
||||||
end
|
|
||||||
|
|
||||||
attr_reader :extension, :description
|
|
||||||
attr_reader :author, :url
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
" * #@extension: #@description\n Written by #@author.\n #@url\n"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
# convenience methods
|
|
||||||
#
|
|
||||||
class << self
|
|
||||||
|
|
||||||
def init argv0 = $0
|
|
||||||
init_internal argv0
|
|
||||||
end
|
|
||||||
|
|
||||||
def append_search_path str
|
|
||||||
add_to_search_path str, 1
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
def prepend_search_path str
|
|
||||||
add_to_search_path str, 0
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method :<<, :append_search_path
|
|
||||||
alias_method :push, :append_search_path
|
|
||||||
alias_method :unshift, :prepend_search_path
|
|
||||||
|
|
||||||
def ls path = ""
|
|
||||||
enumerate path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
# File - PhysicsFS abstract file - can be drawn from various sources
|
|
||||||
#
|
|
||||||
class File
|
|
||||||
def write_str str
|
|
||||||
write str, 1, str.length
|
|
||||||
end
|
|
||||||
|
|
||||||
def cat
|
|
||||||
prev_pos = tell
|
|
||||||
seek 0
|
|
||||||
r = read length, 1
|
|
||||||
seek prev_pos
|
|
||||||
r
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method :size, :length
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
# RWops - general stdio like operations on file-like creatures
|
|
||||||
#
|
|
||||||
class RWops
|
|
||||||
SEEK_SET = 0
|
|
||||||
SEEK_CUR = 1
|
|
||||||
SEEK_END = 2
|
|
||||||
|
|
||||||
# tell current position of RWopted entity
|
|
||||||
def tell
|
|
||||||
seek 0, SEEK_CUR
|
|
||||||
end
|
|
||||||
|
|
||||||
# length of RWops abstracted entity
|
|
||||||
def length
|
|
||||||
cur = tell
|
|
||||||
r = seek 0, SEEK_END
|
|
||||||
seek cur, SEEK_SET
|
|
||||||
r
|
|
||||||
end
|
|
||||||
|
|
||||||
alias_method :size, :length
|
|
||||||
|
|
||||||
#
|
|
||||||
# create rwops from PhysicsFS file object
|
|
||||||
#
|
|
||||||
def self.from_physfs file
|
|
||||||
file.to_rwops
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# physfs.rb ends here #
|
|
||||||
@@ -1,192 +0,0 @@
|
|||||||
/*
|
|
||||||
* This code provides a glue layer between PhysicsFS and Simple Directmedia
|
|
||||||
* Layer's (SDL) RWops i/o abstraction.
|
|
||||||
*
|
|
||||||
* License: this code is public domain. I make no warranty that it is useful,
|
|
||||||
* correct, harmless, or environmentally safe.
|
|
||||||
*
|
|
||||||
* This particular file may be used however you like, including copying it
|
|
||||||
* verbatim into a closed-source project, exploiting it commercially, and
|
|
||||||
* removing any trace of my name from the source (although I hope you won't
|
|
||||||
* do that). I welcome enhancements and corrections to this file, but I do
|
|
||||||
* not require you to send me patches if you make changes.
|
|
||||||
*
|
|
||||||
* Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser
|
|
||||||
* General Public License: http://www.gnu.org/licenses/lgpl.txt
|
|
||||||
*
|
|
||||||
* SDL falls under the LGPL, too. You can get SDL at http://www.libsdl.org/
|
|
||||||
*
|
|
||||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
|
|
||||||
#include "physfsrwops.h"
|
|
||||||
|
|
||||||
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
|
|
||||||
{
|
|
||||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
if (whence == SEEK_SET)
|
|
||||||
{
|
|
||||||
pos = offset;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
else if (whence == SEEK_CUR)
|
|
||||||
{
|
|
||||||
PHYSFS_sint64 current = PHYSFS_tell(handle);
|
|
||||||
if (current == -1)
|
|
||||||
{
|
|
||||||
SDL_SetError("Can't find position in file: %s",
|
|
||||||
PHYSFS_getLastError());
|
|
||||||
return(-1);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
pos = (int) current;
|
|
||||||
if ( ((PHYSFS_sint64) pos) != current )
|
|
||||||
{
|
|
||||||
SDL_SetError("Can't fit current file position in an int!");
|
|
||||||
return(-1);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (offset == 0) /* this is a "tell" call. We're done. */
|
|
||||||
return(pos);
|
|
||||||
|
|
||||||
pos += offset;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else if (whence == SEEK_END)
|
|
||||||
{
|
|
||||||
PHYSFS_sint64 len = PHYSFS_fileLength(handle);
|
|
||||||
if (len == -1)
|
|
||||||
{
|
|
||||||
SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
|
|
||||||
return(-1);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
pos = (int) len;
|
|
||||||
if ( ((PHYSFS_sint64) pos) != len )
|
|
||||||
{
|
|
||||||
SDL_SetError("Can't fit end-of-file position in an int!");
|
|
||||||
return(-1);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
pos += offset;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_SetError("Invalid 'whence' parameter.");
|
|
||||||
return(-1);
|
|
||||||
} /* else */
|
|
||||||
|
|
||||||
if ( pos < 0 )
|
|
||||||
{
|
|
||||||
SDL_SetError("Attempt to seek past start of file.");
|
|
||||||
return(-1);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos))
|
|
||||||
{
|
|
||||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
|
||||||
return(-1);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return(pos);
|
|
||||||
} /* physfsrwops_seek */
|
|
||||||
|
|
||||||
|
|
||||||
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
|
|
||||||
{
|
|
||||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
|
||||||
PHYSFS_sint64 rc = PHYSFS_read(handle, ptr, size, maxnum);
|
|
||||||
if (rc != maxnum)
|
|
||||||
{
|
|
||||||
if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
|
|
||||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return((int) rc);
|
|
||||||
} /* physfsrwops_read */
|
|
||||||
|
|
||||||
|
|
||||||
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
|
|
||||||
{
|
|
||||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
|
||||||
PHYSFS_sint64 rc = PHYSFS_write(handle, ptr, size, num);
|
|
||||||
if (rc != num)
|
|
||||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
|
||||||
|
|
||||||
return((int) rc);
|
|
||||||
} /* physfsrwops_write */
|
|
||||||
|
|
||||||
|
|
||||||
static int physfsrwops_close(SDL_RWops *rw)
|
|
||||||
{
|
|
||||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
|
||||||
if (!PHYSFS_close(handle))
|
|
||||||
{
|
|
||||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
|
||||||
return(-1);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
SDL_FreeRW(rw);
|
|
||||||
return(0);
|
|
||||||
} /* physfsrwops_close */
|
|
||||||
|
|
||||||
|
|
||||||
static SDL_RWops *create_rwops(PHYSFS_File *handle)
|
|
||||||
{
|
|
||||||
SDL_RWops *retval = NULL;
|
|
||||||
|
|
||||||
if (handle == NULL)
|
|
||||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retval = SDL_AllocRW();
|
|
||||||
if (retval != NULL)
|
|
||||||
{
|
|
||||||
retval->seek = physfsrwops_seek;
|
|
||||||
retval->read = physfsrwops_read;
|
|
||||||
retval->write = physfsrwops_write;
|
|
||||||
retval->close = physfsrwops_close;
|
|
||||||
retval->hidden.unknown.data1 = handle;
|
|
||||||
} /* if */
|
|
||||||
} /* else */
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* create_rwops */
|
|
||||||
|
|
||||||
|
|
||||||
SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle)
|
|
||||||
{
|
|
||||||
SDL_RWops *retval = NULL;
|
|
||||||
if (handle == NULL)
|
|
||||||
SDL_SetError("NULL pointer passed to PHYSFSRWOPS_makeRWops().");
|
|
||||||
else
|
|
||||||
retval = create_rwops(handle);
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
} /* PHYSFSRWOPS_makeRWops */
|
|
||||||
|
|
||||||
|
|
||||||
SDL_RWops *PHYSFSRWOPS_openRead(const char *fname)
|
|
||||||
{
|
|
||||||
return(create_rwops(PHYSFS_openRead(fname)));
|
|
||||||
} /* PHYSFSRWOPS_openRead */
|
|
||||||
|
|
||||||
|
|
||||||
SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname)
|
|
||||||
{
|
|
||||||
return(create_rwops(PHYSFS_openWrite(fname)));
|
|
||||||
} /* PHYSFSRWOPS_openWrite */
|
|
||||||
|
|
||||||
|
|
||||||
SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname)
|
|
||||||
{
|
|
||||||
return(create_rwops(PHYSFS_openAppend(fname)));
|
|
||||||
} /* PHYSFSRWOPS_openAppend */
|
|
||||||
|
|
||||||
|
|
||||||
/* end of physfsrwops.c ... */
|
|
||||||
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
* This code provides a glue layer between PhysicsFS and Simple Directmedia
|
|
||||||
* Layer's (SDL) RWops i/o abstraction.
|
|
||||||
*
|
|
||||||
* License: this code is public domain. I make no warranty that it is useful,
|
|
||||||
* correct, harmless, or environmentally safe.
|
|
||||||
*
|
|
||||||
* This particular file may be used however you like, including copying it
|
|
||||||
* verbatim into a closed-source project, exploiting it commercially, and
|
|
||||||
* removing any trace of my name from the source (although I hope you won't
|
|
||||||
* do that). I welcome enhancements and corrections to this file, but I do
|
|
||||||
* not require you to send me patches if you make changes.
|
|
||||||
*
|
|
||||||
* Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser
|
|
||||||
* General Public License: http://www.gnu.org/licenses/lgpl.txt
|
|
||||||
*
|
|
||||||
* SDL falls under the LGPL, too. You can get SDL at http://www.libsdl.org/
|
|
||||||
*
|
|
||||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_PHYSFSRWOPS_H_
|
|
||||||
#define _INCLUDE_PHYSFSRWOPS_H_
|
|
||||||
|
|
||||||
#include "physfs.h"
|
|
||||||
#include "SDL.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a platform-independent filename for reading, and make it accessible
|
|
||||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
|
||||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
|
||||||
* opening files through this method.
|
|
||||||
*
|
|
||||||
* @param filename File to open in platform-independent notation.
|
|
||||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
|
||||||
* of the error can be gleaned from PHYSFS_getLastError().
|
|
||||||
*/
|
|
||||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openRead(const char *fname);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a platform-independent filename for writing, and make it accessible
|
|
||||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
|
||||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
|
||||||
* opening files through this method.
|
|
||||||
*
|
|
||||||
* @param filename File to open in platform-independent notation.
|
|
||||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
|
||||||
* of the error can be gleaned from PHYSFS_getLastError().
|
|
||||||
*/
|
|
||||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a platform-independent filename for appending, and make it accessible
|
|
||||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
|
||||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
|
||||||
* opening files through this method.
|
|
||||||
*
|
|
||||||
* @param filename File to open in platform-independent notation.
|
|
||||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
|
||||||
* of the error can be gleaned from PHYSFS_getLastError().
|
|
||||||
*/
|
|
||||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a SDL_RWops from an existing PhysicsFS file handle. You should
|
|
||||||
* dispose of any references to the handle after successful creation of
|
|
||||||
* the RWops. The actual PhysicsFS handle will be destroyed when the
|
|
||||||
* RWops is closed.
|
|
||||||
*
|
|
||||||
* @param handle a valid PhysicsFS file handle.
|
|
||||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
|
||||||
* of the error can be gleaned from PHYSFS_getLastError().
|
|
||||||
*/
|
|
||||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_file *handle);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* include-once blocker */
|
|
||||||
|
|
||||||
/* end of physfsrwops.h ... */
|
|
||||||
|
|
||||||
@@ -1,462 +0,0 @@
|
|||||||
/*
|
|
||||||
* PhysicsFS - ruby interface
|
|
||||||
*
|
|
||||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
|
||||||
* License:: LGPL
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "physfs.h"
|
|
||||||
#include "ruby.h"
|
|
||||||
|
|
||||||
#include "rb_physfs.h"
|
|
||||||
#include "rb_physfs_file.h"
|
|
||||||
|
|
||||||
VALUE modulePhysfs;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::init str
|
|
||||||
*
|
|
||||||
* initialize PhysicsFS
|
|
||||||
*/
|
|
||||||
VALUE physfs_init (VALUE self, VALUE str)
|
|
||||||
{
|
|
||||||
int result = PHYSFS_init (STR2CSTR(str));
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::deinit
|
|
||||||
*/
|
|
||||||
VALUE physfs_deinit (VALUE self)
|
|
||||||
{
|
|
||||||
if (PHYSFS_deinit ())
|
|
||||||
return Qtrue;
|
|
||||||
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::version
|
|
||||||
*
|
|
||||||
* return PhysicsFS::Version object
|
|
||||||
*/
|
|
||||||
VALUE physfs_version (VALUE self)
|
|
||||||
{
|
|
||||||
char evalStr[200];
|
|
||||||
PHYSFS_Version ver;
|
|
||||||
|
|
||||||
PHYSFS_getLinkedVersion (&ver);
|
|
||||||
|
|
||||||
sprintf (evalStr, "PhysicsFS::Version.new %d, %d, %d",
|
|
||||||
ver.major, ver.minor, ver.patch);
|
|
||||||
return rb_eval_string (evalStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::supported_archives
|
|
||||||
*
|
|
||||||
* return Array of PhysicsFS::ArchiveInfo objects
|
|
||||||
*/
|
|
||||||
VALUE physfs_supported_archives (VALUE self)
|
|
||||||
{
|
|
||||||
const PHYSFS_ArchiveInfo **info = PHYSFS_supportedArchiveTypes();
|
|
||||||
VALUE klass = rb_const_get (modulePhysfs, rb_intern ("ArchiveInfo"));
|
|
||||||
VALUE ary = rb_ary_new ();
|
|
||||||
VALUE params[4];
|
|
||||||
|
|
||||||
while ( *info != 0 )
|
|
||||||
{
|
|
||||||
params[0] = rb_str_new2 ((*info)->extension);
|
|
||||||
params[1] = rb_str_new2 ((*info)->description);
|
|
||||||
params[2] = rb_str_new2 ((*info)->author);
|
|
||||||
params[3] = rb_str_new2 ((*info)->url);
|
|
||||||
|
|
||||||
rb_ary_push (ary, rb_class_new_instance (4, params, klass));
|
|
||||||
info++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::last_error
|
|
||||||
*
|
|
||||||
* return string representation of last PhysicsFS error
|
|
||||||
*/
|
|
||||||
VALUE physfs_last_error (VALUE self)
|
|
||||||
{
|
|
||||||
const char *last_error = PHYSFS_getLastError ();
|
|
||||||
|
|
||||||
if (last_error == 0)
|
|
||||||
last_error = "";
|
|
||||||
|
|
||||||
return rb_str_new2 (last_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::dir_separator
|
|
||||||
*
|
|
||||||
* return platform directory separator
|
|
||||||
*/
|
|
||||||
VALUE physfs_dir_separator (VALUE self)
|
|
||||||
{
|
|
||||||
return rb_str_new2 (PHYSFS_getDirSeparator ());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::permit_symlinks boolValue
|
|
||||||
*
|
|
||||||
* turn symlinks support on/off
|
|
||||||
*/
|
|
||||||
VALUE physfs_permit_symlinks (VALUE self, VALUE allow)
|
|
||||||
{
|
|
||||||
int p = 1;
|
|
||||||
|
|
||||||
if (allow == Qfalse || allow == Qnil)
|
|
||||||
p = 0;
|
|
||||||
|
|
||||||
PHYSFS_permitSymbolicLinks (p);
|
|
||||||
return Qtrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::cdrom_dirs
|
|
||||||
*
|
|
||||||
* return Array of strings containing available CDs
|
|
||||||
*/
|
|
||||||
VALUE physfs_cdrom_dirs (VALUE self)
|
|
||||||
{
|
|
||||||
char **cds = PHYSFS_getCdRomDirs();
|
|
||||||
char **i;
|
|
||||||
VALUE ary = rb_ary_new ();
|
|
||||||
|
|
||||||
for (i = cds; *i != 0; i++)
|
|
||||||
rb_ary_push (ary, rb_str_new2 (*i));
|
|
||||||
|
|
||||||
PHYSFS_freeList (cds);
|
|
||||||
return ary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::base_dir
|
|
||||||
*
|
|
||||||
* return base directory
|
|
||||||
*/
|
|
||||||
VALUE physfs_base_dir (VALUE self)
|
|
||||||
{
|
|
||||||
const char *base_dir = PHYSFS_getBaseDir ();
|
|
||||||
if (base_dir == 0)
|
|
||||||
base_dir = "";
|
|
||||||
|
|
||||||
return rb_str_new2 (base_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::user_dir
|
|
||||||
*
|
|
||||||
* return user directory
|
|
||||||
*/
|
|
||||||
VALUE physfs_user_dir (VALUE self)
|
|
||||||
{
|
|
||||||
const char *user_dir = PHYSFS_getBaseDir ();
|
|
||||||
if (user_dir == 0)
|
|
||||||
user_dir = "";
|
|
||||||
|
|
||||||
return rb_str_new2 (user_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::write_dir
|
|
||||||
*
|
|
||||||
* return write directory
|
|
||||||
*/
|
|
||||||
VALUE physfs_write_dir (VALUE self)
|
|
||||||
{
|
|
||||||
const char *write_dir = PHYSFS_getWriteDir ();
|
|
||||||
if (write_dir == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
return rb_str_new2 (write_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::write_dir= str
|
|
||||||
*
|
|
||||||
* set write directory to *str*
|
|
||||||
*/
|
|
||||||
VALUE physfs_set_write_dir (VALUE self, VALUE str)
|
|
||||||
{
|
|
||||||
int result = PHYSFS_setWriteDir (STR2CSTR(str));
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::add_to_search_path str, append
|
|
||||||
*
|
|
||||||
* if append > 0 - append str to search path, otherwise prepend it
|
|
||||||
*/
|
|
||||||
VALUE physfs_add_search_path (VALUE self, VALUE str, VALUE append)
|
|
||||||
{
|
|
||||||
int result = PHYSFS_addToSearchPath (STR2CSTR(str), FIX2INT(append));
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::remove_from_search_path str
|
|
||||||
*
|
|
||||||
* removes str from search path
|
|
||||||
*/
|
|
||||||
VALUE physfs_remove_search_path (VALUE self, VALUE str)
|
|
||||||
{
|
|
||||||
int result = PHYSFS_removeFromSearchPath (STR2CSTR(str));
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::search_path
|
|
||||||
*
|
|
||||||
* return current search_path - as array of strings
|
|
||||||
*/
|
|
||||||
VALUE physfs_search_path (VALUE self)
|
|
||||||
{
|
|
||||||
char **path = PHYSFS_getSearchPath ();
|
|
||||||
char **i;
|
|
||||||
VALUE ary = rb_ary_new ();
|
|
||||||
|
|
||||||
for (i = path ; *i != 0; i++)
|
|
||||||
rb_ary_push (ary, rb_str_new2 (*i));
|
|
||||||
|
|
||||||
PHYSFS_freeList (path);
|
|
||||||
return ary;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
VALUE physfs_setSaneConfig(VALUE self, VALUE org, VALUE app, VALUE ext,
|
|
||||||
VALUE includeCdroms, VALUE archivesFirst)
|
|
||||||
{
|
|
||||||
int res = PHYSFS_setSaneConfig (STR2CSTR(org), STR2CSTR(app), STR2CSTR(ext),
|
|
||||||
RTEST(includeCdroms), RTEST(archivesFirst));
|
|
||||||
if (res)
|
|
||||||
return Qtrue;
|
|
||||||
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::mkdir newdir
|
|
||||||
*
|
|
||||||
* create new directory
|
|
||||||
*/
|
|
||||||
VALUE physfs_mkdir (VALUE self, VALUE newdir)
|
|
||||||
{
|
|
||||||
int result = PHYSFS_mkdir (STR2CSTR(newdir));
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::delete name
|
|
||||||
*
|
|
||||||
* delete file with name
|
|
||||||
*/
|
|
||||||
VALUE physfs_delete (VALUE self, VALUE name)
|
|
||||||
{
|
|
||||||
int result = PHYSFS_delete (STR2CSTR(name));
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::real_dir name
|
|
||||||
*
|
|
||||||
* return real directory (in search path) of a name
|
|
||||||
*/
|
|
||||||
VALUE physfs_real_dir (VALUE self, VALUE name)
|
|
||||||
{
|
|
||||||
const char *path = PHYSFS_getRealDir (STR2CSTR(name));
|
|
||||||
if (path == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
return rb_str_new2 (path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::enumerate dir
|
|
||||||
*
|
|
||||||
* list a dir from a search path
|
|
||||||
*/
|
|
||||||
VALUE physfs_enumerate (VALUE self, VALUE dir)
|
|
||||||
{
|
|
||||||
char **files = PHYSFS_enumerateFiles (STR2CSTR(dir));
|
|
||||||
char **i;
|
|
||||||
VALUE ary = rb_ary_new ();
|
|
||||||
|
|
||||||
for (i = files; *i != 0; i++)
|
|
||||||
rb_ary_push (ary, rb_str_new2 (*i));
|
|
||||||
|
|
||||||
PHYSFS_freeList (files);
|
|
||||||
return ary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::exists? name
|
|
||||||
*
|
|
||||||
* does a file with name exist?
|
|
||||||
*/
|
|
||||||
VALUE physfs_exists (VALUE self, VALUE name)
|
|
||||||
{
|
|
||||||
int result = PHYSFS_exists (STR2CSTR(name));
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::is_directory? name
|
|
||||||
*
|
|
||||||
* return true if name is directory
|
|
||||||
*/
|
|
||||||
VALUE physfs_is_directory (VALUE self, VALUE name)
|
|
||||||
{
|
|
||||||
int result = PHYSFS_isDirectory (STR2CSTR(name));
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::is_symlink? name
|
|
||||||
*
|
|
||||||
* return true if name is symlink
|
|
||||||
*/
|
|
||||||
VALUE physfs_is_symlink (VALUE self, VALUE name)
|
|
||||||
{
|
|
||||||
int result = PHYSFS_isSymbolicLink (STR2CSTR(name));
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::last_mod_time name
|
|
||||||
*
|
|
||||||
* return last modification time of a file
|
|
||||||
*/
|
|
||||||
VALUE physfs_last_mod_time (VALUE self, VALUE name)
|
|
||||||
{
|
|
||||||
int result = PHYSFS_getLastModTime (STR2CSTR(name));
|
|
||||||
|
|
||||||
return INT2FIX(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::open_read name
|
|
||||||
*
|
|
||||||
* return +PhysicsFS::File+ ready for reading
|
|
||||||
*/
|
|
||||||
VALUE physfs_open_read (VALUE self, VALUE name)
|
|
||||||
{
|
|
||||||
PHYSFS_File *file = PHYSFS_openRead (STR2CSTR(name));
|
|
||||||
return physfs_file_new (file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::open_write name
|
|
||||||
*
|
|
||||||
* return PhysicsFS::File ready for writing
|
|
||||||
*/
|
|
||||||
VALUE physfs_open_write (VALUE self, VALUE name)
|
|
||||||
{
|
|
||||||
PHYSFS_File *file = PHYSFS_openWrite (STR2CSTR(name));
|
|
||||||
return physfs_file_new (file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::open_append name
|
|
||||||
*
|
|
||||||
* return PhysicsFS::File ready for appending
|
|
||||||
*/
|
|
||||||
VALUE physfs_open_append (VALUE self, VALUE name)
|
|
||||||
{
|
|
||||||
PHYSFS_File *file = PHYSFS_openAppend (STR2CSTR(name));
|
|
||||||
return physfs_file_new (file);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Init_physfs_so (void)
|
|
||||||
{
|
|
||||||
modulePhysfs = rb_define_module ("PhysicsFS");
|
|
||||||
|
|
||||||
rb_define_singleton_method (modulePhysfs, "init_internal", physfs_init, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "deinit", physfs_deinit, 0);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "version", physfs_version, 0);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "supported_archives",
|
|
||||||
physfs_supported_archives, 0);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "last_error",
|
|
||||||
physfs_last_error, 0);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "dir_separator",
|
|
||||||
physfs_dir_separator, 0);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "permit_symlinks",
|
|
||||||
physfs_permit_symlinks, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "cdrom_dirs",
|
|
||||||
physfs_cdrom_dirs, 0);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "base_dir", physfs_base_dir, 0);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "user_dir", physfs_user_dir, 0);
|
|
||||||
|
|
||||||
rb_define_singleton_method (modulePhysfs, "write_dir", physfs_write_dir, 0);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "write_dir=",
|
|
||||||
physfs_set_write_dir, 1);
|
|
||||||
|
|
||||||
rb_define_singleton_method (modulePhysfs, "add_to_search_path",
|
|
||||||
physfs_add_search_path, 2);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "remove_from_search_path",
|
|
||||||
physfs_remove_search_path, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "search_path",
|
|
||||||
physfs_search_path, 0);
|
|
||||||
|
|
||||||
rb_define_singleton_method (modulePhysfs, "set_sane_config",
|
|
||||||
physfs_setSaneConfig, 5);
|
|
||||||
|
|
||||||
rb_define_singleton_method (modulePhysfs, "mkdir", physfs_mkdir, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "delete", physfs_delete, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "real_dir",
|
|
||||||
physfs_real_dir, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "enumerate", physfs_enumerate, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "exists?", physfs_exists, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "is_directory?",
|
|
||||||
physfs_is_directory, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "is_symlink?",
|
|
||||||
physfs_is_symlink, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "last_mod_time",
|
|
||||||
physfs_last_mod_time, 1);
|
|
||||||
|
|
||||||
rb_define_singleton_method (modulePhysfs, "open_read",
|
|
||||||
physfs_open_read, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "open_write",
|
|
||||||
physfs_open_write, 1);
|
|
||||||
rb_define_singleton_method (modulePhysfs, "open_append",
|
|
||||||
physfs_open_append, 1);
|
|
||||||
|
|
||||||
init_physfs_file ();
|
|
||||||
init_sdl_rwops ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Local Variables:
|
|
||||||
// mode: C
|
|
||||||
// c-indentation-style: "stroustrup"
|
|
||||||
// indent-tabs-mode: nil
|
|
||||||
// End:
|
|
||||||
*/
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
/*
|
|
||||||
* PhysicsFS - ruby interface
|
|
||||||
*
|
|
||||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
|
||||||
* License:: LGPL
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __RB__PHYSFS__H__
|
|
||||||
#define __RB__PHYSFS__H__
|
|
||||||
|
|
||||||
extern VALUE modulePhysfs;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
/*
|
|
||||||
* PhysicsFS File abstraction - ruby interface
|
|
||||||
*
|
|
||||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
|
||||||
* License:: LGPL
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "physfs.h"
|
|
||||||
#include "ruby.h"
|
|
||||||
|
|
||||||
#include "rb_physfs.h"
|
|
||||||
#include "rb_physfs_file.h"
|
|
||||||
#include "physfsrwops.h"
|
|
||||||
|
|
||||||
VALUE classPhysfsFile;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* construct new PhysicsFS::File object
|
|
||||||
*/
|
|
||||||
VALUE physfs_file_new (PHYSFS_File *file)
|
|
||||||
{
|
|
||||||
if (file == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
return Data_Wrap_Struct (classPhysfsFile, 0, 0, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::File#close
|
|
||||||
*
|
|
||||||
* Close the file. It's illegal to use the object after its closure.
|
|
||||||
*/
|
|
||||||
VALUE physfs_file_close (VALUE self)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
PHYSFS_File *file;
|
|
||||||
Data_Get_Struct (self, PHYSFS_File, file);
|
|
||||||
|
|
||||||
if (file == 0)
|
|
||||||
return Qfalse;
|
|
||||||
|
|
||||||
result = PHYSFS_close (file);
|
|
||||||
DATA_PTR(self) = 0;
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::File#read obj_size, num_objects
|
|
||||||
*
|
|
||||||
* Read *objCount* objects which are *objSize* each.
|
|
||||||
* return String instance containing raw data or nil if failure.
|
|
||||||
* #length of string will reflect real number of objects read.
|
|
||||||
*/
|
|
||||||
VALUE physfs_file_read (VALUE self, VALUE objSize, VALUE objCount)
|
|
||||||
{
|
|
||||||
int objRead;
|
|
||||||
void *buffer;
|
|
||||||
VALUE result;
|
|
||||||
PHYSFS_File *file;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, PHYSFS_File, file);
|
|
||||||
if (file == 0)
|
|
||||||
return Qnil; //wasted file - no read possible
|
|
||||||
|
|
||||||
buffer = malloc (FIX2UINT(objSize) * FIX2UINT(objCount));
|
|
||||||
if (buffer == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
objRead = PHYSFS_read (file, buffer, FIX2UINT(objSize), FIX2UINT(objCount));
|
|
||||||
if (objRead == -1)
|
|
||||||
{
|
|
||||||
free (buffer);
|
|
||||||
return Qnil;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = rb_str_new (buffer, objRead * FIX2UINT(objSize));
|
|
||||||
free (buffer);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::File#write buffer, obj_size, num_objects
|
|
||||||
*
|
|
||||||
* return nil on failure or number of objects written.
|
|
||||||
*/
|
|
||||||
VALUE physfs_file_write (VALUE self, VALUE buf, VALUE objSize, VALUE objCount)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
PHYSFS_File *file;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, PHYSFS_File, file);
|
|
||||||
if (file == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
result = PHYSFS_write (file, STR2CSTR(buf),
|
|
||||||
FIX2UINT(objSize), FIX2UINT(objCount));
|
|
||||||
if (result == -1)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
return INT2FIX(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::File#eof?
|
|
||||||
*/
|
|
||||||
VALUE physfs_file_eof (VALUE self)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
PHYSFS_File *file;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, PHYSFS_File, file);
|
|
||||||
if (file == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
result = PHYSFS_eof (file);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::File#tell
|
|
||||||
*
|
|
||||||
* tells current position in file
|
|
||||||
*/
|
|
||||||
VALUE physfs_file_tell (VALUE self)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
PHYSFS_File *file;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, PHYSFS_File, file);
|
|
||||||
if (file == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
result = PHYSFS_tell (file);
|
|
||||||
|
|
||||||
if (result == -1)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
return INT2FIX(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::File#seek pos
|
|
||||||
*
|
|
||||||
* seek to pos in file
|
|
||||||
*/
|
|
||||||
VALUE physfs_file_seek (VALUE self, VALUE pos)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
PHYSFS_File *file;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, PHYSFS_File, file);
|
|
||||||
if (file == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
result = PHYSFS_seek (file, FIX2LONG(pos));
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
return Qtrue;
|
|
||||||
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::File#length
|
|
||||||
*/
|
|
||||||
VALUE physfs_file_length (VALUE self)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
PHYSFS_File *file;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, PHYSFS_File, file);
|
|
||||||
if (file == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
result = PHYSFS_fileLength (file);
|
|
||||||
|
|
||||||
if (result == -1)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
return INT2FIX(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::File#to_rwops
|
|
||||||
*
|
|
||||||
* File object is converted to RWops object.
|
|
||||||
* File object becomes unusable after that - every operation
|
|
||||||
* should be done through new-born RWops object.
|
|
||||||
*/
|
|
||||||
VALUE physfs_file_to_rwops (VALUE self)
|
|
||||||
{
|
|
||||||
PHYSFS_File *file;
|
|
||||||
SDL_RWops *rwops;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, PHYSFS_File, file);
|
|
||||||
if (file == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
rwops = PHYSFSRWOPS_makeRWops (file);
|
|
||||||
if (rwops == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
DATA_PTR(self) = 0; // oh, gosh, we've sacrificed ourselves!
|
|
||||||
return sdl_rwops_new (rwops);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_physfs_file (void)
|
|
||||||
{
|
|
||||||
classPhysfsFile = rb_define_class_under (modulePhysfs, "File", rb_cObject);
|
|
||||||
|
|
||||||
rb_define_method (classPhysfsFile, "close", physfs_file_close, 0);
|
|
||||||
rb_define_method (classPhysfsFile, "eof?", physfs_file_eof, 0);
|
|
||||||
rb_define_method (classPhysfsFile, "tell", physfs_file_tell, 0);
|
|
||||||
rb_define_method (classPhysfsFile, "seek", physfs_file_seek, 1);
|
|
||||||
rb_define_method (classPhysfsFile, "length", physfs_file_length, 0);
|
|
||||||
rb_define_method (classPhysfsFile, "read", physfs_file_read, 2);
|
|
||||||
rb_define_method (classPhysfsFile, "write", physfs_file_write, 3);
|
|
||||||
rb_define_method (classPhysfsFile, "to_rwops", physfs_file_to_rwops, 0);
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* PhysicsFS File abstraction - ruby interface
|
|
||||||
*
|
|
||||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
|
||||||
* License:: LGPL
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __RB__PHYSFS__FILE__H__
|
|
||||||
#define __RB__PHYSFS__FILE__H__
|
|
||||||
|
|
||||||
extern VALUE classPhysfsFile;
|
|
||||||
|
|
||||||
VALUE physfs_file_new (PHYSFS_file *file);
|
|
||||||
VALUE physfs_file_close (VALUE self);
|
|
||||||
VALUE physfs_file_read (VALUE self, VALUE objSize, VALUE objCount);
|
|
||||||
VALUE physfs_file_write (VALUE self, VALUE buf, VALUE objSize, VALUE objCount);
|
|
||||||
VALUE physfs_file_eof (VALUE self);
|
|
||||||
VALUE physfs_file_tell (VALUE self);
|
|
||||||
VALUE physfs_file_seek (VALUE self, VALUE pos);
|
|
||||||
VALUE physfs_file_length (VALUE self);
|
|
||||||
|
|
||||||
void init_physfs_file (void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
/*
|
|
||||||
* SDL_RWops - ruby interface
|
|
||||||
*
|
|
||||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
|
||||||
* License:: LGPL
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "SDL_rwops.h"
|
|
||||||
#include "ruby.h"
|
|
||||||
|
|
||||||
#include "rb_physfs.h"
|
|
||||||
#include "rb_sdl_rwops.h"
|
|
||||||
|
|
||||||
VALUE classRWops;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* RWops constructor
|
|
||||||
*/
|
|
||||||
VALUE sdl_rwops_new (SDL_RWops *ops)
|
|
||||||
{
|
|
||||||
VALUE result;
|
|
||||||
|
|
||||||
if (ops == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
result = Data_Wrap_Struct (classRWops, 0, SDL_FreeRW, ops);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::RWops::from_file name, mode
|
|
||||||
*
|
|
||||||
* create RWops object from file
|
|
||||||
*/
|
|
||||||
VALUE sdl_rwops_from_file (VALUE self, VALUE name, VALUE mode)
|
|
||||||
{
|
|
||||||
SDL_RWops *ops = SDL_RWFromFile(STR2CSTR(name), STR2CSTR(mode));
|
|
||||||
return sdl_rwops_new (ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::RWops::from_memory string
|
|
||||||
*
|
|
||||||
* create RWops object from memory
|
|
||||||
*/
|
|
||||||
VALUE sdl_rwops_from_mem (VALUE self, VALUE str)
|
|
||||||
{
|
|
||||||
int len = RSTRING(str)->len;
|
|
||||||
void *mem = STR2CSTR(str);
|
|
||||||
SDL_RWops *ops = SDL_RWFromMem(mem, len);
|
|
||||||
|
|
||||||
return sdl_rwops_new (ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::RWops#seek offset, whence
|
|
||||||
*
|
|
||||||
* position RWops object
|
|
||||||
*/
|
|
||||||
VALUE sdl_rwops_seek (VALUE self, VALUE offset, VALUE whence)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
SDL_RWops *ops;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, SDL_RWops, ops);
|
|
||||||
if (ops == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
result = SDL_RWseek(ops, FIX2INT(offset), FIX2INT(whence));
|
|
||||||
return INT2FIX(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::RWops#close
|
|
||||||
*
|
|
||||||
* close RWops. No use of the object is possible after that.
|
|
||||||
*/
|
|
||||||
VALUE sdl_rwops_close (VALUE self)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
SDL_RWops *ops;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, SDL_RWops, ops);
|
|
||||||
if (ops == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
result = SDL_RWclose (ops);
|
|
||||||
DATA_PTR(self) = 0;
|
|
||||||
|
|
||||||
return INT2FIX(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::RWops#read
|
|
||||||
*
|
|
||||||
* read from RWops object objCount objSize'd entities.
|
|
||||||
* return string containing raw data or nil
|
|
||||||
*/
|
|
||||||
VALUE sdl_rwops_read (VALUE self, VALUE objSize, VALUE objCount)
|
|
||||||
{
|
|
||||||
int objRead;
|
|
||||||
void *buffer;
|
|
||||||
VALUE result;
|
|
||||||
SDL_RWops *ops;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, SDL_RWops, ops);
|
|
||||||
if (ops == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
buffer = malloc (FIX2UINT(objSize) * FIX2UINT(objCount));
|
|
||||||
if (buffer == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
objRead = SDL_RWread (ops, buffer, FIX2UINT(objSize), FIX2UINT(objCount));
|
|
||||||
if (objRead == -1)
|
|
||||||
{
|
|
||||||
free (buffer);
|
|
||||||
return Qnil;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = rb_str_new (buffer, objRead * FIX2UINT(objSize));
|
|
||||||
free (buffer);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhysicsFS::RWops#write buffer, size, n
|
|
||||||
*
|
|
||||||
* write raw string containing n objects size length each.
|
|
||||||
* return number of objects written or nil
|
|
||||||
*/
|
|
||||||
VALUE sdl_rwops_write (VALUE self, VALUE buffer, VALUE size, VALUE n)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
SDL_RWops *ops;
|
|
||||||
|
|
||||||
Data_Get_Struct (self, SDL_RWops, ops);
|
|
||||||
if (ops == 0)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
result = SDL_RWwrite (ops, STR2CSTR(buffer), FIX2INT(size), FIX2INT(n));
|
|
||||||
|
|
||||||
if (result == -1)
|
|
||||||
return Qnil;
|
|
||||||
|
|
||||||
return INT2FIX(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_sdl_rwops (void)
|
|
||||||
{
|
|
||||||
classRWops = rb_define_class_under (modulePhysfs, "RWops", rb_cObject);
|
|
||||||
|
|
||||||
rb_define_method (classRWops, "seek", sdl_rwops_seek, 2);
|
|
||||||
rb_define_method (classRWops, "read", sdl_rwops_read, 2);
|
|
||||||
rb_define_method (classRWops, "write", sdl_rwops_write, 3);
|
|
||||||
rb_define_method (classRWops, "close", sdl_rwops_close, 0);
|
|
||||||
|
|
||||||
rb_define_singleton_method (classRWops, "from_file",
|
|
||||||
sdl_rwops_from_file, 2);
|
|
||||||
rb_define_singleton_method (classRWops, "from_memory",
|
|
||||||
sdl_rwops_from_mem, 1);
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
* SDL_RWops - ruby interface
|
|
||||||
*
|
|
||||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
|
||||||
* License:: LGPL
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __RB__SDL__RWOPS__H__
|
|
||||||
#define __RB__SDL__RWOPS__H__
|
|
||||||
|
|
||||||
extern VALUE classRWops;
|
|
||||||
|
|
||||||
VALUE sdl_rwops_new (SDL_RWops *ops);
|
|
||||||
void init_sdl_rwops (void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,358 +0,0 @@
|
|||||||
#
|
|
||||||
# PhysicsFS test program - mimics real physfs_test
|
|
||||||
#
|
|
||||||
require 'readline'
|
|
||||||
require 'physfs'
|
|
||||||
|
|
||||||
def die msg
|
|
||||||
puts "#{msg} - reason: #{PhysicsFS.last_error}"
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
# parse line to command and args
|
|
||||||
#
|
|
||||||
def parse line
|
|
||||||
return false if line.nil?
|
|
||||||
|
|
||||||
if line.strip =~ /^(.*?) (?: (?:\s+(.*)) | $)/x
|
|
||||||
run $1, $2
|
|
||||||
else
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
|
||||||
# parse command args
|
|
||||||
#
|
|
||||||
def parse_args args
|
|
||||||
args.strip!
|
|
||||||
|
|
||||||
dquoted = /^ " (.*?) "/x
|
|
||||||
squoted = /^ ' (.*?) '/x
|
|
||||||
unquoted = /^([^\s\'\"]+)/
|
|
||||||
|
|
||||||
regexps = [dquoted, squoted, unquoted]
|
|
||||||
|
|
||||||
result = []
|
|
||||||
while args != ""
|
|
||||||
regexps.each do |r|
|
|
||||||
if args =~ r
|
|
||||||
result << $1
|
|
||||||
args.sub! r, ""
|
|
||||||
args.sub!(/\s+/, "")
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
def usage cmd, prefix = "usage: "
|
|
||||||
print prefix
|
|
||||||
args = Commands::HELP[cmd]
|
|
||||||
if args
|
|
||||||
print cmd
|
|
||||||
args.scan(/\w+/).each {|x|
|
|
||||||
print " <#{x}>"
|
|
||||||
}
|
|
||||||
puts
|
|
||||||
else
|
|
||||||
puts %|#{cmd} (no arguments)|
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# commands go below
|
|
||||||
module Commands
|
|
||||||
HELP = {
|
|
||||||
"init" => "argv0",
|
|
||||||
"addarchive" => "archiveLocation append",
|
|
||||||
"removearchive" => "archiveLocation",
|
|
||||||
"enumerate" => "dirToEnumerate",
|
|
||||||
"ls" => "dirToEnumerate",
|
|
||||||
"setwritedir" => "newWriteDir",
|
|
||||||
"permitsymlinks" => "1or0",
|
|
||||||
"setsaneconfig" => "org appName arcExt includeCdRoms archivesFirst",
|
|
||||||
"mkdir" => "dirToMk",
|
|
||||||
"delete" => "dirToDelete",
|
|
||||||
"getrealdir" => "fileToFind",
|
|
||||||
"exists" => "fileToCheck",
|
|
||||||
"isdir" => "fileToCheck",
|
|
||||||
"issymlink" => "fileToCheck",
|
|
||||||
"cat" => "fileToCat",
|
|
||||||
"filelength" => "fileToCheck",
|
|
||||||
"append" => "fileToAppend",
|
|
||||||
"write" => "fileToCreateOrTrash",
|
|
||||||
"getlastmodtime" => "fileToExamine"
|
|
||||||
}
|
|
||||||
|
|
||||||
def quit_cmd
|
|
||||||
exit
|
|
||||||
end
|
|
||||||
|
|
||||||
alias q_cmd quit_cmd
|
|
||||||
|
|
||||||
def help_cmd
|
|
||||||
commands = ::Commands.instance_methods.grep(/_cmd$/).sort
|
|
||||||
puts "Commands:"
|
|
||||||
commands.each do |c|
|
|
||||||
usage c.sub("_cmd", ""), " - "
|
|
||||||
end
|
|
||||||
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def e val
|
|
||||||
if val
|
|
||||||
puts "Successful."
|
|
||||||
else
|
|
||||||
puts "Failure. reason: #{PhysicsFS.last_error}"
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def init_cmd arg
|
|
||||||
e PhysicsFS.init(arg)
|
|
||||||
end
|
|
||||||
|
|
||||||
def deinit_cmd
|
|
||||||
e PhysicsFS.deinit
|
|
||||||
end
|
|
||||||
|
|
||||||
def addarchive_cmd archive, append
|
|
||||||
e PhysicsFS.add_to_search_path(archive, append)
|
|
||||||
end
|
|
||||||
|
|
||||||
def removearchive_cmd archive
|
|
||||||
e PhysicsFS.remove_from_search_path archive
|
|
||||||
end
|
|
||||||
|
|
||||||
def enumerate_cmd path
|
|
||||||
entries = PhysicsFS.enumerate(path)
|
|
||||||
entries.each {|x|
|
|
||||||
puts x
|
|
||||||
}
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
alias ls_cmd enumerate_cmd
|
|
||||||
|
|
||||||
def getlasterror_cmd
|
|
||||||
puts "Last error is [#{PhysicsFS.last_error}]"
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def getdirsep_cmd
|
|
||||||
puts "Directory separator is [#{PhysicsFS.dir_separator}]"
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def getcdromdirs_cmd
|
|
||||||
dirs = PhysicsFS.cdrom_dirs
|
|
||||||
dirs.each {|x|
|
|
||||||
puts x
|
|
||||||
}
|
|
||||||
puts " total [#{dirs.length}] drives."
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def getsearchpath_cmd
|
|
||||||
spath = PhysicsFS.search_path
|
|
||||||
spath.each {|x|
|
|
||||||
puts x
|
|
||||||
}
|
|
||||||
puts "total [#{spath.length}] directories."
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def getbasedir_cmd
|
|
||||||
dir = PhysicsFS.base_dir
|
|
||||||
puts dir if dir
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def getuserdir_cmd
|
|
||||||
puts PhysicsFS.user_dir
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def getwritedir_cmd
|
|
||||||
dir = PhysicsFS.write_dir
|
|
||||||
if dir
|
|
||||||
puts "Write directory is [#{dir}]."
|
|
||||||
else
|
|
||||||
puts "No write directory defined."
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def setwritedir_cmd dir
|
|
||||||
e(PhysicsFS.write_dir = dir)
|
|
||||||
end
|
|
||||||
|
|
||||||
def permitsymlinks_cmd val
|
|
||||||
if val.to_i == 1
|
|
||||||
PhysicsFS.permit_symlinks true
|
|
||||||
puts "Symlinks are now permitted"
|
|
||||||
else
|
|
||||||
PhysicsFS.permit_symlinks false
|
|
||||||
puts "Symlinks are now forbidden"
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def setsaneconfig_cmd org, appname, ext, includeCdroms, archivesFirst
|
|
||||||
includeCdroms = includeCdroms.to_i == 1
|
|
||||||
archiveFirst = archivesFirst == 1
|
|
||||||
e PhysicsFS.set_sane_config(org, appname, ext, includeCdroms, archivesFirst)
|
|
||||||
end
|
|
||||||
|
|
||||||
def mkdir_cmd dir
|
|
||||||
e PhysicsFS.mkdir(dir)
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete_cmd dir
|
|
||||||
e PhysicsFS.delete(dir)
|
|
||||||
end
|
|
||||||
|
|
||||||
def getrealdir_cmd file
|
|
||||||
dir = PhysicsFS.real_dir file
|
|
||||||
if dir
|
|
||||||
puts "Found at [#{dir}]"
|
|
||||||
else
|
|
||||||
puts "Not found."
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def exists_cmd file
|
|
||||||
if PhysicsFS.exists? file
|
|
||||||
puts "File exists"
|
|
||||||
else
|
|
||||||
puts "File does not exist"
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def isdir_cmd file
|
|
||||||
if PhysicsFS.is_directory? file
|
|
||||||
puts "File is a directory"
|
|
||||||
else
|
|
||||||
puts "File is NOT a directory"
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def issymlink_cmd file
|
|
||||||
if PhysicsFS.is_symlink? file
|
|
||||||
puts "File is a symlink"
|
|
||||||
else
|
|
||||||
puts "File is NOT a symlink"
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def cat_cmd filename
|
|
||||||
file = PhysicsFS.open_read filename
|
|
||||||
if file.nil?
|
|
||||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
puts file.cat
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def filelength_cmd filename
|
|
||||||
file = PhysicsFS.open_read filename
|
|
||||||
if file.nil?
|
|
||||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
puts file.length
|
|
||||||
file.close
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
WRITE_STR = "Rubyfied PhysicsFS works just fine.\n\n"
|
|
||||||
|
|
||||||
def append_cmd filename
|
|
||||||
file = PhysicsFS.open_append filename
|
|
||||||
if file.nil?
|
|
||||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
file.write WRITE_STR, 1, WRITE_STR.length
|
|
||||||
file.close
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def write_cmd filename
|
|
||||||
file = PhysicsFS.open_write filename
|
|
||||||
if file.nil?
|
|
||||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
file.write_str WRITE_STR
|
|
||||||
file.close
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def getlastmodtime_cmd filename
|
|
||||||
t = PhysicsFS.last_mod_time filename
|
|
||||||
if t == -1
|
|
||||||
puts "failed to determin. reason: #{PhysicsFS.last_error}"
|
|
||||||
else
|
|
||||||
puts "Last modified: #{Time.at(t)}"
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
include Commands
|
|
||||||
|
|
||||||
def run command, args
|
|
||||||
if args
|
|
||||||
args = parse_args args
|
|
||||||
else
|
|
||||||
args = []
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
|
||||||
cmd = method "#{command}_cmd"
|
|
||||||
if args.length == cmd.arity
|
|
||||||
return cmd.call *args
|
|
||||||
else
|
|
||||||
usage command
|
|
||||||
true
|
|
||||||
end
|
|
||||||
rescue NameError
|
|
||||||
puts 'Unknown command. Enter "help" for instructions.'
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if __FILE__ == $0
|
|
||||||
|
|
||||||
PhysicsFS.init($0) or die "PhysicsFS init failed"
|
|
||||||
|
|
||||||
puts "PhysicsFS version: #{PhysicsFS.version}"
|
|
||||||
puts
|
|
||||||
|
|
||||||
puts "Supported archives: "
|
|
||||||
puts PhysicsFS.supported_archives
|
|
||||||
puts
|
|
||||||
|
|
||||||
puts 'Enter commands. Enter "help" for instructions.'
|
|
||||||
|
|
||||||
loop {
|
|
||||||
line = Readline::readline "physfs_rb> ", true
|
|
||||||
break unless parse line
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,237 +0,0 @@
|
|||||||
7z ANSI-C Decoder 4.48
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
7z ANSI-C Decoder 4.48 Copyright (C) 1999-2006 Igor Pavlov
|
|
||||||
|
|
||||||
7z ANSI-C provides 7z/LZMA decoding.
|
|
||||||
7z ANSI-C version is simplified version ported from C++ code.
|
|
||||||
|
|
||||||
LZMA is default and general compression method of 7z format
|
|
||||||
in 7-Zip compression program (www.7-zip.org). LZMA provides high
|
|
||||||
compression ratio and very fast decompression.
|
|
||||||
|
|
||||||
|
|
||||||
LICENSE
|
|
||||||
-------
|
|
||||||
|
|
||||||
Read lzma.txt for information about license.
|
|
||||||
|
|
||||||
|
|
||||||
Files
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
7zAlloc.* - Allocate and Free
|
|
||||||
7zBuffer.* - Buffer structure
|
|
||||||
7zCrc.* - CRC32 code
|
|
||||||
7zDecode.* - Low level memory->memory decoding
|
|
||||||
7zExtract.* - High level stream->memory decoding
|
|
||||||
7zHeader.* - .7z format constants
|
|
||||||
7zIn.* - .7z archive opening
|
|
||||||
7zItem.* - .7z structures
|
|
||||||
7zMain.c - Test application
|
|
||||||
7zMethodID.* - MethodID structure
|
|
||||||
7zTypes.h - Base types and constants
|
|
||||||
|
|
||||||
|
|
||||||
How To Use
|
|
||||||
----------
|
|
||||||
|
|
||||||
You must download 7-Zip program from www.7-zip.org.
|
|
||||||
|
|
||||||
You can create .7z archive with 7z.exe or 7za.exe:
|
|
||||||
|
|
||||||
7za.exe a archive.7z *.htm -r -mx -m0fb=255
|
|
||||||
|
|
||||||
If you have big number of files in archive, and you need fast extracting,
|
|
||||||
you can use partly-solid archives:
|
|
||||||
|
|
||||||
7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K
|
|
||||||
|
|
||||||
In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only
|
|
||||||
512KB for extracting one file from such archive.
|
|
||||||
|
|
||||||
|
|
||||||
Limitations of current version of 7z ANSI-C Decoder
|
|
||||||
---------------------------------------------------
|
|
||||||
|
|
||||||
- It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive.
|
|
||||||
- It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters.
|
|
||||||
- It converts original UTF-16 Unicode file names to UTF-8 Unicode file names.
|
|
||||||
|
|
||||||
These limitations will be fixed in future versions.
|
|
||||||
|
|
||||||
|
|
||||||
Using 7z ANSI-C Decoder Test application:
|
|
||||||
-----------------------------------------
|
|
||||||
|
|
||||||
Usage: 7zDec <command> <archive_name>
|
|
||||||
|
|
||||||
<Command>:
|
|
||||||
e: Extract files from archive
|
|
||||||
l: List contents of archive
|
|
||||||
t: Test integrity of archive
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
7zDec l archive.7z
|
|
||||||
|
|
||||||
lists contents of archive.7z
|
|
||||||
|
|
||||||
7zDec e archive.7z
|
|
||||||
|
|
||||||
extracts files from archive.7z to current folder.
|
|
||||||
|
|
||||||
|
|
||||||
How to use .7z Decoder
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
.7z Decoder can be compiled in one of two modes:
|
|
||||||
|
|
||||||
1) Default mode. In that mode 7z Decoder will read full compressed
|
|
||||||
block to RAM before decompressing.
|
|
||||||
|
|
||||||
2) Mode with defined _LZMA_IN_CB. In that mode 7z Decoder can read
|
|
||||||
compressed block by parts. And you can specify desired buffer size.
|
|
||||||
So memory requirements can be reduced. But decompressing speed will
|
|
||||||
be 5-10% lower and code size is slightly larger.
|
|
||||||
|
|
||||||
|
|
||||||
Memory allocation
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
7z Decoder uses two memory pools:
|
|
||||||
1) Temporary pool
|
|
||||||
2) Main pool
|
|
||||||
Such scheme can allow you to avoid fragmentation of allocated blocks.
|
|
||||||
|
|
||||||
Steps for using 7z decoder
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
Use code at 7zMain.c as example.
|
|
||||||
|
|
||||||
1) Declare variables:
|
|
||||||
inStream /* implements ISzInStream interface */
|
|
||||||
CArchiveDatabaseEx db; /* 7z archive database structure */
|
|
||||||
ISzAlloc allocImp; /* memory functions for main pool */
|
|
||||||
ISzAlloc allocTempImp; /* memory functions for temporary pool */
|
|
||||||
|
|
||||||
2) call InitCrcTable(); function to initialize CRC structures.
|
|
||||||
|
|
||||||
3) call SzArDbExInit(&db); function to initialize db structures.
|
|
||||||
|
|
||||||
4) call SzArchiveOpen(inStream, &db, &allocMain, &allocTemp) to open archive
|
|
||||||
|
|
||||||
This function opens archive "inStream" and reads headers to "db".
|
|
||||||
All items in "db" will be allocated with "allocMain" functions.
|
|
||||||
SzArchiveOpen function allocates and frees temporary structures by "allocTemp" functions.
|
|
||||||
|
|
||||||
5) List items or Extract items
|
|
||||||
|
|
||||||
Listing code:
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < db.Database.NumFiles; i++)
|
|
||||||
{
|
|
||||||
CFileItem *f = db.Database.Files + i;
|
|
||||||
printf("%10d %s\n", (int)f->Size, f->Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Extracting code:
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
SZ_RESULT SzExtract(
|
|
||||||
ISzInStream *inStream,
|
|
||||||
CArchiveDatabaseEx *db,
|
|
||||||
UInt32 fileIndex, /* index of file */
|
|
||||||
UInt32 *blockIndex, /* index of solid block */
|
|
||||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
|
||||||
size_t *outBufferSize, /* buffer size for output buffer */
|
|
||||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
|
||||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
|
||||||
ISzAlloc *allocMain,
|
|
||||||
ISzAlloc *allocTemp);
|
|
||||||
|
|
||||||
If you need to decompress more than one file, you can send these values from previous call:
|
|
||||||
blockIndex,
|
|
||||||
outBuffer,
|
|
||||||
outBufferSize,
|
|
||||||
You can consider "outBuffer" as cache of solid block. If your archive is solid,
|
|
||||||
it will increase decompression speed.
|
|
||||||
|
|
||||||
After decompressing you must free "outBuffer":
|
|
||||||
allocImp.Free(outBuffer);
|
|
||||||
|
|
||||||
6) call SzArDbExFree(&db, allocImp.Free) to free allocated items in "db".
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Memory requirements for .7z decoding
|
|
||||||
------------------------------------
|
|
||||||
|
|
||||||
Memory usage for Archive opening:
|
|
||||||
- Temporary pool:
|
|
||||||
- Memory for compressed .7z headers (if _LZMA_IN_CB is not defined)
|
|
||||||
- Memory for uncompressed .7z headers
|
|
||||||
- some other temporary blocks
|
|
||||||
- Main pool:
|
|
||||||
- Memory for database:
|
|
||||||
Estimated size of one file structures in solid archive:
|
|
||||||
- Size (4 or 8 Bytes)
|
|
||||||
- CRC32 (4 bytes)
|
|
||||||
- LastWriteTime (8 bytes)
|
|
||||||
- Some file information (4 bytes)
|
|
||||||
- File Name (variable length) + pointer + allocation structures
|
|
||||||
|
|
||||||
Memory usage for archive Decompressing:
|
|
||||||
- Temporary pool:
|
|
||||||
- Memory for compressed solid block (if _LZMA_IN_CB is not defined)
|
|
||||||
- Memory for LZMA decompressing structures
|
|
||||||
- Main pool:
|
|
||||||
- Memory for decompressed solid block
|
|
||||||
- Memory for temprorary buffers, if BCJ2 fileter is used. Usually these
|
|
||||||
temprorary buffers can be about 15% of solid block size.
|
|
||||||
|
|
||||||
|
|
||||||
If _LZMA_IN_CB is defined, 7z Decoder will not allocate memory for
|
|
||||||
compressed blocks. Instead of this, you must allocate buffer with desired
|
|
||||||
size before calling 7z Decoder. Use 7zMain.c as example.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EXIT codes
|
|
||||||
-----------
|
|
||||||
|
|
||||||
7z Decoder functions can return one of the following codes:
|
|
||||||
|
|
||||||
#define SZ_OK (0)
|
|
||||||
#define SZE_DATA_ERROR (1)
|
|
||||||
#define SZE_OUTOFMEMORY (2)
|
|
||||||
#define SZE_CRC_ERROR (3)
|
|
||||||
|
|
||||||
#define SZE_NOTIMPL (4)
|
|
||||||
#define SZE_FAIL (5)
|
|
||||||
|
|
||||||
#define SZE_ARCHIVE_ERROR (6)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LZMA Defines
|
|
||||||
------------
|
|
||||||
|
|
||||||
_LZMA_IN_CB - Use special callback mode for input stream to reduce memory requirements
|
|
||||||
|
|
||||||
_SZ_FILE_SIZE_32 - define it if you need only support for files smaller than 4 GB
|
|
||||||
_SZ_NO_INT_64 - define it if your compiler doesn't support long long int or __int64.
|
|
||||||
|
|
||||||
_LZMA_PROB32 - it can increase LZMA decompressing speed on some 32-bit CPUs.
|
|
||||||
|
|
||||||
_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr.
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
http://www.7-zip.org
|
|
||||||
http://www.7-zip.org/support.html
|
|
||||||
@@ -1,471 +0,0 @@
|
|||||||
7z Format description (2.30 Beta 25)
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
This file contains description of 7z archive format.
|
|
||||||
7z archive can contain files compressed with any method.
|
|
||||||
See "Methods.txt" for description for defined compressing methods.
|
|
||||||
|
|
||||||
|
|
||||||
Format structure Overview
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Some fields can be optional.
|
|
||||||
|
|
||||||
Archive structure
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
SignatureHeader
|
|
||||||
[PackedStreams]
|
|
||||||
[PackedStreamsForHeaders]
|
|
||||||
[
|
|
||||||
Header
|
|
||||||
or
|
|
||||||
{
|
|
||||||
Packed Header
|
|
||||||
HeaderInfo
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Header structure
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
{
|
|
||||||
ArchiveProperties
|
|
||||||
AdditionalStreams
|
|
||||||
{
|
|
||||||
PackInfo
|
|
||||||
{
|
|
||||||
PackPos
|
|
||||||
NumPackStreams
|
|
||||||
Sizes[NumPackStreams]
|
|
||||||
CRCs[NumPackStreams]
|
|
||||||
}
|
|
||||||
CodersInfo
|
|
||||||
{
|
|
||||||
NumFolders
|
|
||||||
Folders[NumFolders]
|
|
||||||
{
|
|
||||||
NumCoders
|
|
||||||
CodersInfo[NumCoders]
|
|
||||||
{
|
|
||||||
ID
|
|
||||||
NumInStreams;
|
|
||||||
NumOutStreams;
|
|
||||||
PropertiesSize
|
|
||||||
Properties[PropertiesSize]
|
|
||||||
}
|
|
||||||
NumBindPairs
|
|
||||||
BindPairsInfo[NumBindPairs]
|
|
||||||
{
|
|
||||||
InIndex;
|
|
||||||
OutIndex;
|
|
||||||
}
|
|
||||||
PackedIndices
|
|
||||||
}
|
|
||||||
UnPackSize[Folders][Folders.NumOutstreams]
|
|
||||||
CRCs[NumFolders]
|
|
||||||
}
|
|
||||||
SubStreamsInfo
|
|
||||||
{
|
|
||||||
NumUnPackStreamsInFolders[NumFolders];
|
|
||||||
UnPackSizes[]
|
|
||||||
CRCs[]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MainStreamsInfo
|
|
||||||
{
|
|
||||||
(Same as in AdditionalStreams)
|
|
||||||
}
|
|
||||||
FilesInfo
|
|
||||||
{
|
|
||||||
NumFiles
|
|
||||||
Properties[]
|
|
||||||
{
|
|
||||||
ID
|
|
||||||
Size
|
|
||||||
Data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HeaderInfo structure
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
{
|
|
||||||
(Same as in AdditionalStreams)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Notes about Notation and encoding
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
7z uses little endian encoding.
|
|
||||||
|
|
||||||
7z archive format has optional headers that are marked as
|
|
||||||
[]
|
|
||||||
Header
|
|
||||||
[]
|
|
||||||
|
|
||||||
REAL_UINT64 means real UINT64.
|
|
||||||
|
|
||||||
UINT64 means real UINT64 encoded with the following scheme:
|
|
||||||
|
|
||||||
Size of encoding sequence depends from first byte:
|
|
||||||
First_Byte Extra_Bytes Value
|
|
||||||
(binary)
|
|
||||||
0xxxxxxx : ( xxxxxxx )
|
|
||||||
10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y
|
|
||||||
110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y
|
|
||||||
...
|
|
||||||
1111110x BYTE y[6] : ( x << (8 * 6)) + y
|
|
||||||
11111110 BYTE y[7] : y
|
|
||||||
11111111 BYTE y[8] : y
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Property IDs
|
|
||||||
------------
|
|
||||||
|
|
||||||
0x00 = kEnd,
|
|
||||||
|
|
||||||
0x01 = kHeader,
|
|
||||||
|
|
||||||
0x02 = kArchiveProperties,
|
|
||||||
|
|
||||||
0x03 = kAdditionalStreamsInfo,
|
|
||||||
0x04 = kMainStreamsInfo,
|
|
||||||
0x05 = kFilesInfo,
|
|
||||||
|
|
||||||
0x06 = kPackInfo,
|
|
||||||
0x07 = kUnPackInfo,
|
|
||||||
0x08 = kSubStreamsInfo,
|
|
||||||
|
|
||||||
0x09 = kSize,
|
|
||||||
0x0A = kCRC,
|
|
||||||
|
|
||||||
0x0B = kFolder,
|
|
||||||
|
|
||||||
0x0C = kCodersUnPackSize,
|
|
||||||
0x0D = kNumUnPackStream,
|
|
||||||
|
|
||||||
0x0E = kEmptyStream,
|
|
||||||
0x0F = kEmptyFile,
|
|
||||||
0x10 = kAnti,
|
|
||||||
|
|
||||||
0x11 = kName,
|
|
||||||
0x12 = kCreationTime,
|
|
||||||
0x13 = kLastAccessTime,
|
|
||||||
0x14 = kLastWriteTime,
|
|
||||||
0x15 = kWinAttributes,
|
|
||||||
0x16 = kComment,
|
|
||||||
|
|
||||||
0x17 = kEncodedHeader,
|
|
||||||
|
|
||||||
|
|
||||||
7z format headers
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
SignatureHeader
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
|
||||||
|
|
||||||
ArchiveVersion
|
|
||||||
{
|
|
||||||
BYTE Major; // now = 0
|
|
||||||
BYTE Minor; // now = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
UINT32 StartHeaderCRC;
|
|
||||||
|
|
||||||
StartHeader
|
|
||||||
{
|
|
||||||
REAL_UINT64 NextHeaderOffset
|
|
||||||
REAL_UINT64 NextHeaderSize
|
|
||||||
UINT32 NextHeaderCRC
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
...........................
|
|
||||||
|
|
||||||
|
|
||||||
ArchiveProperties
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
BYTE NID::kArchiveProperties (0x02)
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
BYTE PropertyType;
|
|
||||||
if (aType == 0)
|
|
||||||
break;
|
|
||||||
UINT64 PropertySize;
|
|
||||||
BYTE PropertyData[PropertySize];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Digests (NumStreams)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
BYTE AllAreDefined
|
|
||||||
if (AllAreDefined == 0)
|
|
||||||
{
|
|
||||||
for(NumStreams)
|
|
||||||
BIT Defined
|
|
||||||
}
|
|
||||||
UINT32 CRCs[NumDefined]
|
|
||||||
|
|
||||||
|
|
||||||
PackInfo
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
BYTE NID::kPackInfo (0x06)
|
|
||||||
UINT64 PackPos
|
|
||||||
UINT64 NumPackStreams
|
|
||||||
|
|
||||||
[]
|
|
||||||
BYTE NID::kSize (0x09)
|
|
||||||
UINT64 PackSizes[NumPackStreams]
|
|
||||||
[]
|
|
||||||
|
|
||||||
[]
|
|
||||||
BYTE NID::kCRC (0x0A)
|
|
||||||
PackStreamDigests[NumPackStreams]
|
|
||||||
[]
|
|
||||||
|
|
||||||
BYTE NID::kEnd
|
|
||||||
|
|
||||||
|
|
||||||
Folder
|
|
||||||
~~~~~~
|
|
||||||
UINT64 NumCoders;
|
|
||||||
for (NumCoders)
|
|
||||||
{
|
|
||||||
BYTE
|
|
||||||
{
|
|
||||||
0:3 DecompressionMethod.IDSize
|
|
||||||
4:
|
|
||||||
0 - IsSimple
|
|
||||||
1 - Is not simple
|
|
||||||
5:
|
|
||||||
0 - No Attributes
|
|
||||||
1 - There Are Attributes
|
|
||||||
7:
|
|
||||||
0 - Last Method in Alternative_Method_List
|
|
||||||
1 - There are more alternative methods
|
|
||||||
}
|
|
||||||
BYTE DecompressionMethod.ID[DecompressionMethod.IDSize]
|
|
||||||
if (!IsSimple)
|
|
||||||
{
|
|
||||||
UINT64 NumInStreams;
|
|
||||||
UINT64 NumOutStreams;
|
|
||||||
}
|
|
||||||
if (DecompressionMethod[0] != 0)
|
|
||||||
{
|
|
||||||
UINT64 PropertiesSize
|
|
||||||
BYTE Properties[PropertiesSize]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NumBindPairs = NumOutStreamsTotal - 1;
|
|
||||||
|
|
||||||
for (NumBindPairs)
|
|
||||||
{
|
|
||||||
UINT64 InIndex;
|
|
||||||
UINT64 OutIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
NumPackedStreams = NumInStreamsTotal - NumBindPairs;
|
|
||||||
if (NumPackedStreams > 1)
|
|
||||||
for(NumPackedStreams)
|
|
||||||
{
|
|
||||||
UINT64 Index;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Coders Info
|
|
||||||
~~~~~~~~~~~
|
|
||||||
|
|
||||||
BYTE NID::kUnPackInfo (0x07)
|
|
||||||
|
|
||||||
|
|
||||||
BYTE NID::kFolder (0x0B)
|
|
||||||
UINT64 NumFolders
|
|
||||||
BYTE External
|
|
||||||
switch(External)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
Folders[NumFolders]
|
|
||||||
case 1:
|
|
||||||
UINT64 DataStreamIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BYTE ID::kCodersUnPackSize (0x0C)
|
|
||||||
for(Folders)
|
|
||||||
for(Folder.NumOutStreams)
|
|
||||||
UINT64 UnPackSize;
|
|
||||||
|
|
||||||
|
|
||||||
[]
|
|
||||||
BYTE NID::kCRC (0x0A)
|
|
||||||
UnPackDigests[NumFolders]
|
|
||||||
[]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BYTE NID::kEnd
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SubStreams Info
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
BYTE NID::kSubStreamsInfo; (0x08)
|
|
||||||
|
|
||||||
[]
|
|
||||||
BYTE NID::kNumUnPackStream; (0x0D)
|
|
||||||
UINT64 NumUnPackStreamsInFolders[NumFolders];
|
|
||||||
[]
|
|
||||||
|
|
||||||
|
|
||||||
[]
|
|
||||||
BYTE NID::kSize (0x09)
|
|
||||||
UINT64 UnPackSizes[]
|
|
||||||
[]
|
|
||||||
|
|
||||||
|
|
||||||
[]
|
|
||||||
BYTE NID::kCRC (0x0A)
|
|
||||||
Digests[Number of streams with unknown CRC]
|
|
||||||
[]
|
|
||||||
|
|
||||||
|
|
||||||
BYTE NID::kEnd
|
|
||||||
|
|
||||||
|
|
||||||
Streams Info
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
|
|
||||||
[]
|
|
||||||
PackInfo
|
|
||||||
[]
|
|
||||||
|
|
||||||
|
|
||||||
[]
|
|
||||||
CodersInfo
|
|
||||||
[]
|
|
||||||
|
|
||||||
|
|
||||||
[]
|
|
||||||
SubStreamsInfo
|
|
||||||
[]
|
|
||||||
|
|
||||||
BYTE NID::kEnd
|
|
||||||
|
|
||||||
|
|
||||||
FilesInfo
|
|
||||||
~~~~~~~~~
|
|
||||||
BYTE NID::kFilesInfo; (0x05)
|
|
||||||
UINT64 NumFiles
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
BYTE PropertyType;
|
|
||||||
if (aType == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
UINT64 Size;
|
|
||||||
|
|
||||||
switch(PropertyType)
|
|
||||||
{
|
|
||||||
kEmptyStream: (0x0E)
|
|
||||||
for(NumFiles)
|
|
||||||
BIT IsEmptyStream
|
|
||||||
|
|
||||||
kEmptyFile: (0x0F)
|
|
||||||
for(EmptyStreams)
|
|
||||||
BIT IsEmptyFile
|
|
||||||
|
|
||||||
kAnti: (0x10)
|
|
||||||
for(EmptyStreams)
|
|
||||||
BIT IsAntiFile
|
|
||||||
|
|
||||||
case kCreationTime: (0x12)
|
|
||||||
case kLastAccessTime: (0x13)
|
|
||||||
case kLastWriteTime: (0x14)
|
|
||||||
BYTE AllAreDefined
|
|
||||||
if (AllAreDefined == 0)
|
|
||||||
{
|
|
||||||
for(NumFiles)
|
|
||||||
BIT TimeDefined
|
|
||||||
}
|
|
||||||
BYTE External;
|
|
||||||
if(External != 0)
|
|
||||||
UINT64 DataIndex
|
|
||||||
[]
|
|
||||||
for(Definded Items)
|
|
||||||
UINT32 Time
|
|
||||||
[]
|
|
||||||
|
|
||||||
kNames: (0x11)
|
|
||||||
BYTE External;
|
|
||||||
if(External != 0)
|
|
||||||
UINT64 DataIndex
|
|
||||||
[]
|
|
||||||
for(Files)
|
|
||||||
{
|
|
||||||
wchar_t Names[NameSize];
|
|
||||||
wchar_t 0;
|
|
||||||
}
|
|
||||||
[]
|
|
||||||
|
|
||||||
kAttributes: (0x15)
|
|
||||||
BYTE AllAreDefined
|
|
||||||
if (AllAreDefined == 0)
|
|
||||||
{
|
|
||||||
for(NumFiles)
|
|
||||||
BIT AttributesAreDefined
|
|
||||||
}
|
|
||||||
BYTE External;
|
|
||||||
if(External != 0)
|
|
||||||
UINT64 DataIndex
|
|
||||||
[]
|
|
||||||
for(Definded Attributes)
|
|
||||||
UINT32 Attributes
|
|
||||||
[]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Header
|
|
||||||
~~~~~~
|
|
||||||
BYTE NID::kHeader (0x01)
|
|
||||||
|
|
||||||
[]
|
|
||||||
ArchiveProperties
|
|
||||||
[]
|
|
||||||
|
|
||||||
[]
|
|
||||||
BYTE NID::kAdditionalStreamsInfo; (0x03)
|
|
||||||
StreamsInfo
|
|
||||||
[]
|
|
||||||
|
|
||||||
[]
|
|
||||||
BYTE NID::kMainStreamsInfo; (0x04)
|
|
||||||
StreamsInfo
|
|
||||||
[]
|
|
||||||
|
|
||||||
[]
|
|
||||||
FilesInfo
|
|
||||||
[]
|
|
||||||
|
|
||||||
BYTE NID::kEnd
|
|
||||||
|
|
||||||
|
|
||||||
HeaderInfo
|
|
||||||
~~~~~~~~~~
|
|
||||||
[]
|
|
||||||
BYTE NID::kEncodedHeader; (0x17)
|
|
||||||
StreamsInfo for Encoded Header
|
|
||||||
[]
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
End of document
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/* 7zCrc.c */
|
|
||||||
|
|
||||||
#include "7zCrc.h"
|
|
||||||
|
|
||||||
#define kCrcPoly 0xEDB88320
|
|
||||||
UInt32 g_CrcTable[256];
|
|
||||||
|
|
||||||
void MY_FAST_CALL CrcGenerateTable(void)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
UInt32 r = i;
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < 8; j++)
|
|
||||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
|
||||||
g_CrcTable[i] = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
|
||||||
{
|
|
||||||
const Byte *p = (const Byte *)data;
|
|
||||||
for (; size > 0 ; size--, p++)
|
|
||||||
v = CRC_UPDATE_BYTE(v, *p);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
|
||||||
{
|
|
||||||
return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/* 7zCrc.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_CRC_H
|
|
||||||
#define __7Z_CRC_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "Types.h"
|
|
||||||
|
|
||||||
extern UInt32 g_CrcTable[];
|
|
||||||
|
|
||||||
void MY_FAST_CALL CrcGenerateTable(void);
|
|
||||||
|
|
||||||
#define CRC_INIT_VAL 0xFFFFFFFF
|
|
||||||
#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF)
|
|
||||||
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
|
|
||||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/* 7zCrcT8.c */
|
|
||||||
|
|
||||||
#include "7zCrc.h"
|
|
||||||
|
|
||||||
#define kCrcPoly 0xEDB88320
|
|
||||||
#define CRC_NUM_TABLES 8
|
|
||||||
|
|
||||||
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
|
|
||||||
|
|
||||||
void MY_FAST_CALL CrcGenerateTable()
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
UInt32 r = i;
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < 8; j++)
|
|
||||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
|
||||||
g_CrcTable[i] = r;
|
|
||||||
}
|
|
||||||
#if CRC_NUM_TABLES > 1
|
|
||||||
for (; i < 256 * CRC_NUM_TABLES; i++)
|
|
||||||
{
|
|
||||||
UInt32 r = g_CrcTable[i - 256];
|
|
||||||
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
|
||||||
{
|
|
||||||
return CrcUpdateT8(v, data, size, g_CrcTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
|
||||||
{
|
|
||||||
return CrcUpdateT8(CRC_INIT_VAL, data, size, g_CrcTable) ^ 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
/* Alloc.c */
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "Alloc.h"
|
|
||||||
|
|
||||||
/* #define _SZ_ALLOC_DEBUG */
|
|
||||||
|
|
||||||
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
#include <stdio.h>
|
|
||||||
int g_allocCount = 0;
|
|
||||||
int g_allocCountMid = 0;
|
|
||||||
int g_allocCountBig = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *MyAlloc(size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++);
|
|
||||||
#endif
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyFree(void *address)
|
|
||||||
{
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
if (address != 0)
|
|
||||||
fprintf(stderr, "\nFree; count = %10d", --g_allocCount);
|
|
||||||
#endif
|
|
||||||
free(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
void *MidAlloc(size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);
|
|
||||||
#endif
|
|
||||||
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MidFree(void *address)
|
|
||||||
{
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
if (address != 0)
|
|
||||||
fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
|
|
||||||
#endif
|
|
||||||
if (address == 0)
|
|
||||||
return;
|
|
||||||
VirtualFree(address, 0, MEM_RELEASE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef MEM_LARGE_PAGES
|
|
||||||
#undef _7ZIP_LARGE_PAGES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _7ZIP_LARGE_PAGES
|
|
||||||
SIZE_T g_LargePageSize = 0;
|
|
||||||
typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SetLargePageSize()
|
|
||||||
{
|
|
||||||
#ifdef _7ZIP_LARGE_PAGES
|
|
||||||
SIZE_T size = 0;
|
|
||||||
GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
|
|
||||||
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
|
|
||||||
if (largePageMinimum == 0)
|
|
||||||
return;
|
|
||||||
size = largePageMinimum();
|
|
||||||
if (size == 0 || (size & (size - 1)) != 0)
|
|
||||||
return;
|
|
||||||
g_LargePageSize = size;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *BigAlloc(size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _7ZIP_LARGE_PAGES
|
|
||||||
if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
|
|
||||||
{
|
|
||||||
void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
|
|
||||||
MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
|
|
||||||
if (res != 0)
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BigFree(void *address)
|
|
||||||
{
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
if (address != 0)
|
|
||||||
fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (address == 0)
|
|
||||||
return;
|
|
||||||
VirtualFree(address, 0, MEM_RELEASE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/* Alloc.h */
|
|
||||||
|
|
||||||
#ifndef __COMMON_ALLOC_H
|
|
||||||
#define __COMMON_ALLOC_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
void *MyAlloc(size_t size);
|
|
||||||
void MyFree(void *address);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
void SetLargePageSize();
|
|
||||||
|
|
||||||
void *MidAlloc(size_t size);
|
|
||||||
void MidFree(void *address);
|
|
||||||
void *BigAlloc(size_t size);
|
|
||||||
void BigFree(void *address);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define MidAlloc(size) MyAlloc(size)
|
|
||||||
#define MidFree(address) MyFree(address)
|
|
||||||
#define BigAlloc(size) MyAlloc(size)
|
|
||||||
#define BigFree(address) MyFree(address)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
/* 7zAlloc.c */
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "7zAlloc.h"
|
|
||||||
|
|
||||||
/* #define _SZ_ALLOC_DEBUG */
|
|
||||||
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
|
||||||
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
int g_allocCount = 0;
|
|
||||||
int g_allocCountTemp = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *SzAlloc(size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
|
|
||||||
g_allocCount++;
|
|
||||||
#endif
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzFree(void *address)
|
|
||||||
{
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
if (address != 0)
|
|
||||||
{
|
|
||||||
g_allocCount--;
|
|
||||||
fprintf(stderr, "\nFree; count = %10d", g_allocCount);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
free(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *SzAllocTemp(size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
|
|
||||||
g_allocCountTemp++;
|
|
||||||
#ifdef _WIN32
|
|
||||||
return HeapAlloc(GetProcessHeap(), 0, size);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzFreeTemp(void *address)
|
|
||||||
{
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
|
||||||
if (address != 0)
|
|
||||||
{
|
|
||||||
g_allocCountTemp--;
|
|
||||||
fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
|
|
||||||
}
|
|
||||||
#ifdef _WIN32
|
|
||||||
HeapFree(GetProcessHeap(), 0, address);
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
free(address);
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
/* 7zAlloc.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_ALLOC_H
|
|
||||||
#define __7Z_ALLOC_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
typedef struct _ISzAlloc
|
|
||||||
{
|
|
||||||
void *(*Alloc)(size_t size);
|
|
||||||
void (*Free)(void *address); /* address can be 0 */
|
|
||||||
} ISzAlloc;
|
|
||||||
|
|
||||||
void *SzAlloc(size_t size);
|
|
||||||
void SzFree(void *address);
|
|
||||||
|
|
||||||
void *SzAllocTemp(size_t size);
|
|
||||||
void SzFreeTemp(void *address);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/* 7zBuffer.c */
|
|
||||||
|
|
||||||
#include "7zBuffer.h"
|
|
||||||
#include "7zAlloc.h"
|
|
||||||
|
|
||||||
void SzByteBufferInit(CSzByteBuffer *buffer)
|
|
||||||
{
|
|
||||||
buffer->Capacity = 0;
|
|
||||||
buffer->Items = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size))
|
|
||||||
{
|
|
||||||
buffer->Capacity = newCapacity;
|
|
||||||
if (newCapacity == 0)
|
|
||||||
{
|
|
||||||
buffer->Items = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
buffer->Items = (Byte *)allocFunc(newCapacity);
|
|
||||||
return (buffer->Items != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *))
|
|
||||||
{
|
|
||||||
freeFunc(buffer->Items);
|
|
||||||
buffer->Items = 0;
|
|
||||||
buffer->Capacity = 0;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/* 7zBuffer.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_BUFFER_H
|
|
||||||
#define __7Z_BUFFER_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "../../Types.h"
|
|
||||||
|
|
||||||
typedef struct _CSzByteBuffer
|
|
||||||
{
|
|
||||||
size_t Capacity;
|
|
||||||
Byte *Items;
|
|
||||||
}CSzByteBuffer;
|
|
||||||
|
|
||||||
void SzByteBufferInit(CSzByteBuffer *buffer);
|
|
||||||
int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size));
|
|
||||||
void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *));
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,345 +0,0 @@
|
|||||||
/* 7zDecode.c */
|
|
||||||
|
|
||||||
#include <memory.h>
|
|
||||||
|
|
||||||
/* BEGIN PHYSFS CHANGE */
|
|
||||||
#include <string.h>
|
|
||||||
/* END PHYSFS CHANGE */
|
|
||||||
|
|
||||||
#include "7zDecode.h"
|
|
||||||
#ifdef _SZ_ONE_DIRECTORY
|
|
||||||
#include "LzmaDecode.h"
|
|
||||||
#else
|
|
||||||
#include "../../Compress/Lzma/LzmaDecode.h"
|
|
||||||
#include "../../Compress/Branch/BranchX86.h"
|
|
||||||
#include "../../Compress/Branch/BranchX86_2.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define k_Copy 0
|
|
||||||
#define k_LZMA 0x30101
|
|
||||||
#define k_BCJ 0x03030103
|
|
||||||
#define k_BCJ2 0x0303011B
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
|
|
||||||
typedef struct _CLzmaInCallbackImp
|
|
||||||
{
|
|
||||||
ILzmaInCallback InCallback;
|
|
||||||
ISzInStream *InStream;
|
|
||||||
CFileSize Size;
|
|
||||||
} CLzmaInCallbackImp;
|
|
||||||
|
|
||||||
int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size)
|
|
||||||
{
|
|
||||||
CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
|
|
||||||
size_t processedSize;
|
|
||||||
SZ_RESULT res;
|
|
||||||
size_t curSize = (1 << 20);
|
|
||||||
if (curSize > cb->Size)
|
|
||||||
curSize = (size_t)cb->Size;
|
|
||||||
*size = 0;
|
|
||||||
res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &processedSize);
|
|
||||||
*size = (SizeT)processedSize;
|
|
||||||
if (processedSize > curSize)
|
|
||||||
return (int)SZE_FAIL;
|
|
||||||
cb->Size -= processedSize;
|
|
||||||
if (res == SZ_OK)
|
|
||||||
return 0;
|
|
||||||
return (int)res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ISzInStream *inStream,
|
|
||||||
#else
|
|
||||||
const Byte *inBuffer,
|
|
||||||
#endif
|
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
CLzmaInCallbackImp lzmaCallback;
|
|
||||||
#else
|
|
||||||
SizeT inProcessed;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
|
|
||||||
int result;
|
|
||||||
SizeT outSizeProcessedLoc;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
lzmaCallback.Size = inSize;
|
|
||||||
lzmaCallback.InStream = inStream;
|
|
||||||
lzmaCallback.InCallback.Read = LzmaReadImp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
|
|
||||||
(unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK)
|
|
||||||
return SZE_FAIL;
|
|
||||||
|
|
||||||
state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
|
|
||||||
if (state.Probs == 0)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (state.Properties.DictionarySize == 0)
|
|
||||||
state.Dictionary = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
|
|
||||||
if (state.Dictionary == 0)
|
|
||||||
{
|
|
||||||
allocMain->Free(state.Probs);
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LzmaDecoderInit(&state);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
result = LzmaDecode(&state,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
&lzmaCallback.InCallback,
|
|
||||||
#else
|
|
||||||
inBuffer, (SizeT)inSize, &inProcessed,
|
|
||||||
#endif
|
|
||||||
outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
|
|
||||||
allocMain->Free(state.Probs);
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
allocMain->Free(state.Dictionary);
|
|
||||||
#endif
|
|
||||||
if (result == LZMA_RESULT_DATA_ERROR)
|
|
||||||
return SZE_DATA_ERROR;
|
|
||||||
if (result != LZMA_RESULT_OK)
|
|
||||||
return SZE_FAIL;
|
|
||||||
return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer)
|
|
||||||
{
|
|
||||||
while (inSize > 0)
|
|
||||||
{
|
|
||||||
void *inBuffer;
|
|
||||||
size_t processedSize, curSize = (1 << 18);
|
|
||||||
if (curSize > inSize)
|
|
||||||
curSize = (size_t)(inSize);
|
|
||||||
RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &processedSize));
|
|
||||||
if (processedSize == 0)
|
|
||||||
return SZE_DATA_ERROR;
|
|
||||||
if (processedSize > curSize)
|
|
||||||
return SZE_FAIL;
|
|
||||||
memcpy(outBuffer, inBuffer, processedSize);
|
|
||||||
outBuffer += processedSize;
|
|
||||||
inSize -= processedSize;
|
|
||||||
}
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
|
|
||||||
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
|
||||||
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
|
||||||
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
|
|
||||||
|
|
||||||
SZ_RESULT CheckSupportedFolder(const CFolder *f)
|
|
||||||
{
|
|
||||||
if (f->NumCoders < 1 || f->NumCoders > 4)
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
if (IS_UNSUPPORTED_CODER(f->Coders[0]))
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
if (f->NumCoders == 1)
|
|
||||||
{
|
|
||||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
if (f->NumCoders == 2)
|
|
||||||
{
|
|
||||||
if (IS_NO_BCJ(f->Coders[1]) ||
|
|
||||||
f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
|
|
||||||
f->NumBindPairs != 1 ||
|
|
||||||
f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
if (f->NumCoders == 4)
|
|
||||||
{
|
|
||||||
if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
|
|
||||||
IS_UNSUPPORTED_CODER(f->Coders[2]) ||
|
|
||||||
IS_NO_BCJ2(f->Coders[3]))
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
if (f->NumPackStreams != 4 ||
|
|
||||||
f->PackStreams[0] != 2 ||
|
|
||||||
f->PackStreams[1] != 6 ||
|
|
||||||
f->PackStreams[2] != 1 ||
|
|
||||||
f->PackStreams[3] != 0 ||
|
|
||||||
f->NumBindPairs != 3 ||
|
|
||||||
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
|
|
||||||
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
|
|
||||||
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFileSize GetSum(const CFileSize *values, UInt32 index)
|
|
||||||
{
|
|
||||||
CFileSize sum = 0;
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < index; i++)
|
|
||||||
sum += values[i];
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ISzInStream *inStream, CFileSize startPos,
|
|
||||||
#else
|
|
||||||
const Byte *inBuffer,
|
|
||||||
#endif
|
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain,
|
|
||||||
Byte *tempBuf[])
|
|
||||||
{
|
|
||||||
UInt32 ci;
|
|
||||||
size_t tempSizes[3] = { 0, 0, 0};
|
|
||||||
size_t tempSize3 = 0;
|
|
||||||
Byte *tempBuf3 = 0;
|
|
||||||
|
|
||||||
RINOK(CheckSupportedFolder(folder));
|
|
||||||
|
|
||||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
|
||||||
{
|
|
||||||
CCoderInfo *coder = &folder->Coders[ci];
|
|
||||||
|
|
||||||
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
|
|
||||||
{
|
|
||||||
UInt32 si = 0;
|
|
||||||
CFileSize offset;
|
|
||||||
CFileSize inSize;
|
|
||||||
Byte *outBufCur = outBuffer;
|
|
||||||
size_t outSizeCur = outSize;
|
|
||||||
if (folder->NumCoders == 4)
|
|
||||||
{
|
|
||||||
UInt32 indices[] = { 3, 2, 0 };
|
|
||||||
CFileSize unpackSize = folder->UnPackSizes[ci];
|
|
||||||
si = indices[ci];
|
|
||||||
if (ci < 2)
|
|
||||||
{
|
|
||||||
Byte *temp;
|
|
||||||
outSizeCur = (size_t)unpackSize;
|
|
||||||
if (outSizeCur != unpackSize)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
temp = (Byte *)allocMain->Alloc(outSizeCur);
|
|
||||||
if (temp == 0 && outSizeCur != 0)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
outBufCur = tempBuf[1 - ci] = temp;
|
|
||||||
tempSizes[1 - ci] = outSizeCur;
|
|
||||||
}
|
|
||||||
else if (ci == 2)
|
|
||||||
{
|
|
||||||
if (unpackSize > outSize)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
|
||||||
tempSize3 = outSizeCur = (size_t)unpackSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
}
|
|
||||||
offset = GetSum(packSizes, si);
|
|
||||||
inSize = packSizes[si];
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
RINOK(inStream->Seek(inStream, startPos + offset));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (coder->MethodID == k_Copy)
|
|
||||||
{
|
|
||||||
if (inSize != outSizeCur)
|
|
||||||
return SZE_DATA_ERROR;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
|
||||||
#else
|
|
||||||
memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SZ_RESULT res = SzDecodeLzma(coder, inSize,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
inStream,
|
|
||||||
#else
|
|
||||||
inBuffer + (size_t)offset,
|
|
||||||
#endif
|
|
||||||
outBufCur, outSizeCur, allocMain);
|
|
||||||
RINOK(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (coder->MethodID == k_BCJ)
|
|
||||||
{
|
|
||||||
UInt32 state;
|
|
||||||
if (ci != 1)
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
x86_Convert_Init(state);
|
|
||||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
|
||||||
}
|
|
||||||
else if (coder->MethodID == k_BCJ2)
|
|
||||||
{
|
|
||||||
CFileSize offset = GetSum(packSizes, 1);
|
|
||||||
CFileSize s3Size = packSizes[1];
|
|
||||||
SZ_RESULT res;
|
|
||||||
if (ci != 3)
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
RINOK(inStream->Seek(inStream, startPos + offset));
|
|
||||||
tempSizes[2] = (size_t)s3Size;
|
|
||||||
if (tempSizes[2] != s3Size)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]);
|
|
||||||
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
|
||||||
RINOK(res)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
res = x86_2_Decode(
|
|
||||||
tempBuf3, tempSize3,
|
|
||||||
tempBuf[0], tempSizes[0],
|
|
||||||
tempBuf[1], tempSizes[1],
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
tempBuf[2], tempSizes[2],
|
|
||||||
#else
|
|
||||||
inBuffer + (size_t)offset, (size_t)s3Size,
|
|
||||||
#endif
|
|
||||||
outBuffer, outSize);
|
|
||||||
RINOK(res)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return SZE_NOTIMPL;
|
|
||||||
}
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ISzInStream *inStream, CFileSize startPos,
|
|
||||||
#else
|
|
||||||
const Byte *inBuffer,
|
|
||||||
#endif
|
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
|
||||||
{
|
|
||||||
Byte *tempBuf[3] = { 0, 0, 0};
|
|
||||||
int i;
|
|
||||||
SZ_RESULT res = SzDecode2(packSizes, folder,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
inStream, startPos,
|
|
||||||
#else
|
|
||||||
inBuffer,
|
|
||||||
#endif
|
|
||||||
outBuffer, outSize, allocMain, tempBuf);
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
allocMain->Free(tempBuf[i]);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
/* 7zDecode.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_DECODE_H
|
|
||||||
#define __7Z_DECODE_H
|
|
||||||
|
|
||||||
#include "7zItem.h"
|
|
||||||
#include "7zAlloc.h"
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
#include "7zIn.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ISzInStream *stream, CFileSize startPos,
|
|
||||||
#else
|
|
||||||
const Byte *inBuffer,
|
|
||||||
#endif
|
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
/* 7zExtract.c */
|
|
||||||
|
|
||||||
#include "7zExtract.h"
|
|
||||||
#include "7zDecode.h"
|
|
||||||
#include "../../7zCrc.h"
|
|
||||||
|
|
||||||
SZ_RESULT SzExtract(
|
|
||||||
ISzInStream *inStream,
|
|
||||||
CArchiveDatabaseEx *db,
|
|
||||||
UInt32 fileIndex,
|
|
||||||
UInt32 *blockIndex,
|
|
||||||
Byte **outBuffer,
|
|
||||||
size_t *outBufferSize,
|
|
||||||
size_t *offset,
|
|
||||||
size_t *outSizeProcessed,
|
|
||||||
ISzAlloc *allocMain,
|
|
||||||
ISzAlloc *allocTemp)
|
|
||||||
{
|
|
||||||
UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
|
|
||||||
SZ_RESULT res = SZ_OK;
|
|
||||||
*offset = 0;
|
|
||||||
*outSizeProcessed = 0;
|
|
||||||
if (folderIndex == (UInt32)-1)
|
|
||||||
{
|
|
||||||
allocMain->Free(*outBuffer);
|
|
||||||
*blockIndex = folderIndex;
|
|
||||||
*outBuffer = 0;
|
|
||||||
*outBufferSize = 0;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*outBuffer == 0 || *blockIndex != folderIndex)
|
|
||||||
{
|
|
||||||
CFolder *folder = db->Database.Folders + folderIndex;
|
|
||||||
CFileSize unPackSizeSpec = SzFolderGetUnPackSize(folder);
|
|
||||||
size_t unPackSize = (size_t)unPackSizeSpec;
|
|
||||||
CFileSize startOffset = SzArDbGetFolderStreamPos(db, folderIndex, 0);
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
Byte *inBuffer = 0;
|
|
||||||
size_t processedSize;
|
|
||||||
CFileSize packSizeSpec;
|
|
||||||
size_t packSize;
|
|
||||||
RINOK(SzArDbGetFolderFullPackSize(db, folderIndex, &packSizeSpec));
|
|
||||||
packSize = (size_t)packSizeSpec;
|
|
||||||
if (packSize != packSizeSpec)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
#endif
|
|
||||||
if (unPackSize != unPackSizeSpec)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
*blockIndex = folderIndex;
|
|
||||||
allocMain->Free(*outBuffer);
|
|
||||||
*outBuffer = 0;
|
|
||||||
|
|
||||||
RINOK(inStream->Seek(inStream, startOffset));
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
if (packSize != 0)
|
|
||||||
{
|
|
||||||
inBuffer = (Byte *)allocTemp->Alloc(packSize);
|
|
||||||
if (inBuffer == 0)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
res = inStream->Read(inStream, inBuffer, packSize, &processedSize);
|
|
||||||
if (res == SZ_OK && processedSize != packSize)
|
|
||||||
res = SZE_FAIL;
|
|
||||||
#endif
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
*outBufferSize = unPackSize;
|
|
||||||
if (unPackSize != 0)
|
|
||||||
{
|
|
||||||
*outBuffer = (Byte *)allocMain->Alloc(unPackSize);
|
|
||||||
if (*outBuffer == 0)
|
|
||||||
res = SZE_OUTOFMEMORY;
|
|
||||||
}
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
res = SzDecode(db->Database.PackSizes +
|
|
||||||
db->FolderStartPackStreamIndex[folderIndex], folder,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
inStream, startOffset,
|
|
||||||
#else
|
|
||||||
inBuffer,
|
|
||||||
#endif
|
|
||||||
*outBuffer, unPackSize, allocTemp);
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
if (folder->UnPackCRCDefined)
|
|
||||||
{
|
|
||||||
if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC)
|
|
||||||
res = SZE_CRC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
allocTemp->Free(inBuffer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
CFileItem *fileItem = db->Database.Files + fileIndex;
|
|
||||||
*offset = 0;
|
|
||||||
for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
|
|
||||||
*offset += (UInt32)db->Database.Files[i].Size;
|
|
||||||
*outSizeProcessed = (size_t)fileItem->Size;
|
|
||||||
if (*offset + *outSizeProcessed > *outBufferSize)
|
|
||||||
return SZE_FAIL;
|
|
||||||
{
|
|
||||||
if (fileItem->IsFileCRCDefined)
|
|
||||||
{
|
|
||||||
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
|
|
||||||
res = SZE_CRC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/* 7zExtract.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_EXTRACT_H
|
|
||||||
#define __7Z_EXTRACT_H
|
|
||||||
|
|
||||||
#include "7zIn.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
SzExtract extracts file from archive
|
|
||||||
|
|
||||||
*outBuffer must be 0 before first call for each new archive.
|
|
||||||
|
|
||||||
Extracting cache:
|
|
||||||
If you need to decompress more than one file, you can send
|
|
||||||
these values from previous call:
|
|
||||||
*blockIndex,
|
|
||||||
*outBuffer,
|
|
||||||
*outBufferSize
|
|
||||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
|
||||||
it will increase decompression speed.
|
|
||||||
|
|
||||||
If you use external function, you can declare these 3 cache variables
|
|
||||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
|
||||||
|
|
||||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
|
||||||
*/
|
|
||||||
|
|
||||||
SZ_RESULT SzExtract(
|
|
||||||
ISzInStream *inStream,
|
|
||||||
CArchiveDatabaseEx *db,
|
|
||||||
UInt32 fileIndex, /* index of file */
|
|
||||||
UInt32 *blockIndex, /* index of solid block */
|
|
||||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
|
||||||
size_t *outBufferSize, /* buffer size for output buffer */
|
|
||||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
|
||||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
|
||||||
ISzAlloc *allocMain,
|
|
||||||
ISzAlloc *allocTemp);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
/* 7zHeader.c */
|
|
||||||
|
|
||||||
#include "7zHeader.h"
|
|
||||||
|
|
||||||
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/* 7zHeader.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_HEADER_H
|
|
||||||
#define __7Z_HEADER_H
|
|
||||||
|
|
||||||
#include "../../Types.h"
|
|
||||||
|
|
||||||
#define k7zSignatureSize 6
|
|
||||||
extern Byte k7zSignature[k7zSignatureSize];
|
|
||||||
|
|
||||||
#define k7zMajorVersion 0
|
|
||||||
|
|
||||||
#define k7zStartHeaderSize 0x20
|
|
||||||
|
|
||||||
enum EIdEnum
|
|
||||||
{
|
|
||||||
k7zIdEnd,
|
|
||||||
|
|
||||||
k7zIdHeader,
|
|
||||||
|
|
||||||
k7zIdArchiveProperties,
|
|
||||||
|
|
||||||
k7zIdAdditionalStreamsInfo,
|
|
||||||
k7zIdMainStreamsInfo,
|
|
||||||
k7zIdFilesInfo,
|
|
||||||
|
|
||||||
k7zIdPackInfo,
|
|
||||||
k7zIdUnPackInfo,
|
|
||||||
k7zIdSubStreamsInfo,
|
|
||||||
|
|
||||||
k7zIdSize,
|
|
||||||
k7zIdCRC,
|
|
||||||
|
|
||||||
k7zIdFolder,
|
|
||||||
|
|
||||||
k7zIdCodersUnPackSize,
|
|
||||||
k7zIdNumUnPackStream,
|
|
||||||
|
|
||||||
k7zIdEmptyStream,
|
|
||||||
k7zIdEmptyFile,
|
|
||||||
k7zIdAnti,
|
|
||||||
|
|
||||||
k7zIdName,
|
|
||||||
k7zIdCreationTime,
|
|
||||||
k7zIdLastAccessTime,
|
|
||||||
k7zIdLastWriteTime,
|
|
||||||
k7zIdWinAttributes,
|
|
||||||
k7zIdComment,
|
|
||||||
|
|
||||||
k7zIdEncodedHeader,
|
|
||||||
|
|
||||||
k7zIdStartPos
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
|||||||
/* 7zIn.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_IN_H
|
|
||||||
#define __7Z_IN_H
|
|
||||||
|
|
||||||
#include "7zHeader.h"
|
|
||||||
#include "7zItem.h"
|
|
||||||
#include "7zAlloc.h"
|
|
||||||
|
|
||||||
typedef struct _CInArchiveInfo
|
|
||||||
{
|
|
||||||
CFileSize StartPositionAfterHeader;
|
|
||||||
CFileSize DataStartPosition;
|
|
||||||
}CInArchiveInfo;
|
|
||||||
|
|
||||||
typedef struct _CArchiveDatabaseEx
|
|
||||||
{
|
|
||||||
CArchiveDatabase Database;
|
|
||||||
CInArchiveInfo ArchiveInfo;
|
|
||||||
UInt32 *FolderStartPackStreamIndex;
|
|
||||||
CFileSize *PackStreamStartPositions;
|
|
||||||
UInt32 *FolderStartFileIndex;
|
|
||||||
UInt32 *FileIndexToFolderIndexMap;
|
|
||||||
}CArchiveDatabaseEx;
|
|
||||||
|
|
||||||
void SzArDbExInit(CArchiveDatabaseEx *db);
|
|
||||||
void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *));
|
|
||||||
CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder);
|
|
||||||
int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize);
|
|
||||||
|
|
||||||
typedef struct _ISzInStream
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
SZ_RESULT (*Read)(
|
|
||||||
void *object, /* pointer to ISzInStream itself */
|
|
||||||
void **buffer, /* out: pointer to buffer with data */
|
|
||||||
size_t maxRequiredSize, /* max required size to read */
|
|
||||||
size_t *processedSize); /* real processed size.
|
|
||||||
processedSize can be less than maxRequiredSize.
|
|
||||||
If processedSize == 0, then there are no more
|
|
||||||
bytes in stream. */
|
|
||||||
#else
|
|
||||||
SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize);
|
|
||||||
#endif
|
|
||||||
SZ_RESULT (*Seek)(void *object, CFileSize pos);
|
|
||||||
} ISzInStream;
|
|
||||||
|
|
||||||
|
|
||||||
int SzArchiveOpen(
|
|
||||||
ISzInStream *inStream,
|
|
||||||
CArchiveDatabaseEx *db,
|
|
||||||
ISzAlloc *allocMain,
|
|
||||||
ISzAlloc *allocTemp);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
/* 7zItem.c */
|
|
||||||
|
|
||||||
#include "7zItem.h"
|
|
||||||
#include "7zAlloc.h"
|
|
||||||
|
|
||||||
void SzCoderInfoInit(CCoderInfo *coder)
|
|
||||||
{
|
|
||||||
SzByteBufferInit(&coder->Properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p))
|
|
||||||
{
|
|
||||||
SzByteBufferFree(&coder->Properties, freeFunc);
|
|
||||||
SzCoderInfoInit(coder);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzFolderInit(CFolder *folder)
|
|
||||||
{
|
|
||||||
folder->NumCoders = 0;
|
|
||||||
folder->Coders = 0;
|
|
||||||
folder->NumBindPairs = 0;
|
|
||||||
folder->BindPairs = 0;
|
|
||||||
folder->NumPackStreams = 0;
|
|
||||||
folder->PackStreams = 0;
|
|
||||||
folder->UnPackSizes = 0;
|
|
||||||
folder->UnPackCRCDefined = 0;
|
|
||||||
folder->UnPackCRC = 0;
|
|
||||||
folder->NumUnPackStreams = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p))
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < folder->NumCoders; i++)
|
|
||||||
SzCoderInfoFree(&folder->Coders[i], freeFunc);
|
|
||||||
freeFunc(folder->Coders);
|
|
||||||
freeFunc(folder->BindPairs);
|
|
||||||
freeFunc(folder->PackStreams);
|
|
||||||
freeFunc(folder->UnPackSizes);
|
|
||||||
SzFolderInit(folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 SzFolderGetNumOutStreams(CFolder *folder)
|
|
||||||
{
|
|
||||||
UInt32 result = 0;
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < folder->NumCoders; i++)
|
|
||||||
result += folder->Coders[i].NumOutStreams;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for(i = 0; i < folder->NumBindPairs; i++)
|
|
||||||
if (folder->BindPairs[i].InIndex == inStreamIndex)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for(i = 0; i < folder->NumBindPairs; i++)
|
|
||||||
if (folder->BindPairs[i].OutIndex == outStreamIndex)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFileSize SzFolderGetUnPackSize(CFolder *folder)
|
|
||||||
{
|
|
||||||
int i = (int)SzFolderGetNumOutStreams(folder);
|
|
||||||
if (i == 0)
|
|
||||||
return 0;
|
|
||||||
for (i--; i >= 0; i--)
|
|
||||||
if (SzFolderFindBindPairForOutStream(folder, i) < 0)
|
|
||||||
return folder->UnPackSizes[i];
|
|
||||||
/* throw 1; */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
int FindPackStreamArrayIndex(int inStreamIndex) const
|
|
||||||
{
|
|
||||||
for(int i = 0; i < PackStreams.Size(); i++)
|
|
||||||
if (PackStreams[i] == inStreamIndex)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void SzFileInit(CFileItem *fileItem)
|
|
||||||
{
|
|
||||||
fileItem->IsFileCRCDefined = 0;
|
|
||||||
fileItem->HasStream = 1;
|
|
||||||
fileItem->IsDirectory = 0;
|
|
||||||
fileItem->IsAnti = 0;
|
|
||||||
fileItem->IsLastWriteTimeDefined = 0;
|
|
||||||
fileItem->Name = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p))
|
|
||||||
{
|
|
||||||
freeFunc(fileItem->Name);
|
|
||||||
SzFileInit(fileItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzArchiveDatabaseInit(CArchiveDatabase *db)
|
|
||||||
{
|
|
||||||
db->NumPackStreams = 0;
|
|
||||||
db->PackSizes = 0;
|
|
||||||
db->PackCRCsDefined = 0;
|
|
||||||
db->PackCRCs = 0;
|
|
||||||
db->NumFolders = 0;
|
|
||||||
db->Folders = 0;
|
|
||||||
db->NumFiles = 0;
|
|
||||||
db->Files = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *))
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < db->NumFolders; i++)
|
|
||||||
SzFolderFree(&db->Folders[i], freeFunc);
|
|
||||||
for (i = 0; i < db->NumFiles; i++)
|
|
||||||
SzFileFree(&db->Files[i], freeFunc);
|
|
||||||
freeFunc(db->PackSizes);
|
|
||||||
freeFunc(db->PackCRCsDefined);
|
|
||||||
freeFunc(db->PackCRCs);
|
|
||||||
freeFunc(db->Folders);
|
|
||||||
freeFunc(db->Files);
|
|
||||||
SzArchiveDatabaseInit(db);
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/* 7zItem.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_ITEM_H
|
|
||||||
#define __7Z_ITEM_H
|
|
||||||
|
|
||||||
#include "7zMethodID.h"
|
|
||||||
#include "7zHeader.h"
|
|
||||||
#include "7zBuffer.h"
|
|
||||||
|
|
||||||
typedef struct _CCoderInfo
|
|
||||||
{
|
|
||||||
UInt32 NumInStreams;
|
|
||||||
UInt32 NumOutStreams;
|
|
||||||
CMethodID MethodID;
|
|
||||||
CSzByteBuffer Properties;
|
|
||||||
}CCoderInfo;
|
|
||||||
|
|
||||||
void SzCoderInfoInit(CCoderInfo *coder);
|
|
||||||
void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p));
|
|
||||||
|
|
||||||
typedef struct _CBindPair
|
|
||||||
{
|
|
||||||
UInt32 InIndex;
|
|
||||||
UInt32 OutIndex;
|
|
||||||
}CBindPair;
|
|
||||||
|
|
||||||
typedef struct _CFolder
|
|
||||||
{
|
|
||||||
UInt32 NumCoders;
|
|
||||||
CCoderInfo *Coders;
|
|
||||||
UInt32 NumBindPairs;
|
|
||||||
CBindPair *BindPairs;
|
|
||||||
UInt32 NumPackStreams;
|
|
||||||
UInt32 *PackStreams;
|
|
||||||
CFileSize *UnPackSizes;
|
|
||||||
int UnPackCRCDefined;
|
|
||||||
UInt32 UnPackCRC;
|
|
||||||
|
|
||||||
UInt32 NumUnPackStreams;
|
|
||||||
}CFolder;
|
|
||||||
|
|
||||||
void SzFolderInit(CFolder *folder);
|
|
||||||
CFileSize SzFolderGetUnPackSize(CFolder *folder);
|
|
||||||
int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex);
|
|
||||||
UInt32 SzFolderGetNumOutStreams(CFolder *folder);
|
|
||||||
CFileSize SzFolderGetUnPackSize(CFolder *folder);
|
|
||||||
|
|
||||||
typedef struct _CArchiveFileTime
|
|
||||||
{
|
|
||||||
UInt32 Low;
|
|
||||||
UInt32 High;
|
|
||||||
} CArchiveFileTime;
|
|
||||||
|
|
||||||
typedef struct _CFileItem
|
|
||||||
{
|
|
||||||
CArchiveFileTime LastWriteTime;
|
|
||||||
/*
|
|
||||||
CFileSize StartPos;
|
|
||||||
UInt32 Attributes;
|
|
||||||
*/
|
|
||||||
CFileSize Size;
|
|
||||||
UInt32 FileCRC;
|
|
||||||
char *Name;
|
|
||||||
|
|
||||||
Byte IsFileCRCDefined;
|
|
||||||
Byte HasStream;
|
|
||||||
Byte IsDirectory;
|
|
||||||
Byte IsAnti;
|
|
||||||
Byte IsLastWriteTimeDefined;
|
|
||||||
/*
|
|
||||||
int AreAttributesDefined;
|
|
||||||
int IsLastWriteTimeDefined;
|
|
||||||
int IsStartPosDefined;
|
|
||||||
*/
|
|
||||||
}CFileItem;
|
|
||||||
|
|
||||||
void SzFileInit(CFileItem *fileItem);
|
|
||||||
|
|
||||||
typedef struct _CArchiveDatabase
|
|
||||||
{
|
|
||||||
UInt32 NumPackStreams;
|
|
||||||
CFileSize *PackSizes;
|
|
||||||
Byte *PackCRCsDefined;
|
|
||||||
UInt32 *PackCRCs;
|
|
||||||
UInt32 NumFolders;
|
|
||||||
CFolder *Folders;
|
|
||||||
UInt32 NumFiles;
|
|
||||||
CFileItem *Files;
|
|
||||||
}CArchiveDatabase;
|
|
||||||
|
|
||||||
void SzArchiveDatabaseInit(CArchiveDatabase *db);
|
|
||||||
void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *));
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,428 +0,0 @@
|
|||||||
/*
|
|
||||||
7zMain.c
|
|
||||||
Test application for 7z Decoder
|
|
||||||
LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define USE_WINDOWS_FUNCTIONS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "7zIn.h"
|
|
||||||
#include "7zExtract.h"
|
|
||||||
|
|
||||||
#include "../../7zCrc.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
typedef HANDLE MY_FILE_HANDLE;
|
|
||||||
#else
|
|
||||||
typedef FILE *MY_FILE_HANDLE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ConvertNumberToString(CFileSize value, char *s)
|
|
||||||
{
|
|
||||||
char temp[32];
|
|
||||||
int pos = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
temp[pos++] = (char)('0' + (int)(value % 10));
|
|
||||||
value /= 10;
|
|
||||||
}
|
|
||||||
while (value != 0);
|
|
||||||
do
|
|
||||||
*s++ = temp[--pos];
|
|
||||||
while(pos > 0);
|
|
||||||
*s = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PERIOD_4 (4 * 365 + 1)
|
|
||||||
#define PERIOD_100 (PERIOD_4 * 25 - 1)
|
|
||||||
#define PERIOD_400 (PERIOD_100 * 4 + 1)
|
|
||||||
|
|
||||||
void ConvertFileTimeToString(CArchiveFileTime *ft, char *s)
|
|
||||||
{
|
|
||||||
unsigned year, mon, day, hour, min, sec;
|
|
||||||
UInt64 v64 = ft->Low | ((UInt64)ft->High << 32);
|
|
||||||
Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
|
||||||
unsigned temp;
|
|
||||||
UInt32 v;
|
|
||||||
v64 /= 10000000;
|
|
||||||
sec = (unsigned)(v64 % 60);
|
|
||||||
v64 /= 60;
|
|
||||||
min = (unsigned)(v64 % 60);
|
|
||||||
v64 /= 60;
|
|
||||||
hour = (unsigned)(v64 % 24);
|
|
||||||
v64 /= 24;
|
|
||||||
|
|
||||||
v = (UInt32)v64;
|
|
||||||
|
|
||||||
year = (unsigned)(1601 + v / PERIOD_400 * 400);
|
|
||||||
v %= PERIOD_400;
|
|
||||||
|
|
||||||
temp = (unsigned)(v / PERIOD_100);
|
|
||||||
if (temp == 4)
|
|
||||||
temp = 3;
|
|
||||||
year += temp * 100;
|
|
||||||
v -= temp * PERIOD_100;
|
|
||||||
|
|
||||||
temp = v / PERIOD_4;
|
|
||||||
if (temp == 25)
|
|
||||||
temp = 24;
|
|
||||||
year += temp * 4;
|
|
||||||
v -= temp * PERIOD_4;
|
|
||||||
|
|
||||||
temp = v / 365;
|
|
||||||
if (temp == 4)
|
|
||||||
temp = 3;
|
|
||||||
year += temp;
|
|
||||||
v -= temp * 365;
|
|
||||||
|
|
||||||
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
|
|
||||||
ms[1] = 29;
|
|
||||||
for (mon = 1; mon <= 12; mon++)
|
|
||||||
{
|
|
||||||
unsigned s = ms[mon - 1];
|
|
||||||
if (v < s)
|
|
||||||
break;
|
|
||||||
v -= s;
|
|
||||||
}
|
|
||||||
day = (unsigned)v + 1;
|
|
||||||
sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
/*
|
|
||||||
ReadFile and WriteFile functions in Windows have BUG:
|
|
||||||
If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
|
|
||||||
from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
|
|
||||||
(Insufficient system resources exist to complete the requested service).
|
|
||||||
*/
|
|
||||||
#define kChunkSizeMax (1 << 24)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t MyReadFile(MY_FILE_HANDLE file, void *data, size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
{
|
|
||||||
size_t processedSize = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
|
|
||||||
DWORD processedLoc = 0;
|
|
||||||
BOOL res = ReadFile(file, data, curSize, &processedLoc, NULL);
|
|
||||||
data = (void *)((unsigned char *)data + processedLoc);
|
|
||||||
size -= processedLoc;
|
|
||||||
processedSize += processedLoc;
|
|
||||||
if (!res || processedLoc == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (size > 0);
|
|
||||||
return processedSize;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return fread(data, 1, size, file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MyWriteFile(MY_FILE_HANDLE file, void *data, size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
{
|
|
||||||
size_t processedSize = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
|
|
||||||
DWORD processedLoc = 0;
|
|
||||||
BOOL res = WriteFile(file, data, curSize, &processedLoc, NULL);
|
|
||||||
data = (void *)((unsigned char *)data + processedLoc);
|
|
||||||
size -= processedLoc;
|
|
||||||
processedSize += processedLoc;
|
|
||||||
if (!res)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
while (size > 0);
|
|
||||||
return processedSize;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return fwrite(data, 1, size, file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int MyCloseFile(MY_FILE_HANDLE file)
|
|
||||||
{
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
return (CloseHandle(file) != FALSE) ? 0 : 1;
|
|
||||||
#else
|
|
||||||
return fclose(file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct _CFileInStream
|
|
||||||
{
|
|
||||||
ISzInStream InStream;
|
|
||||||
MY_FILE_HANDLE File;
|
|
||||||
} CFileInStream;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
|
|
||||||
#define kBufferSize (1 << 12)
|
|
||||||
Byte g_Buffer[kBufferSize];
|
|
||||||
|
|
||||||
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize)
|
|
||||||
{
|
|
||||||
CFileInStream *s = (CFileInStream *)object;
|
|
||||||
size_t processedSizeLoc;
|
|
||||||
if (maxRequiredSize > kBufferSize)
|
|
||||||
maxRequiredSize = kBufferSize;
|
|
||||||
processedSizeLoc = MyReadFile(s->File, g_Buffer, maxRequiredSize);
|
|
||||||
*buffer = g_Buffer;
|
|
||||||
if (processedSize != 0)
|
|
||||||
*processedSize = processedSizeLoc;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize)
|
|
||||||
{
|
|
||||||
CFileInStream *s = (CFileInStream *)object;
|
|
||||||
size_t processedSizeLoc = MyReadFile(s->File, buffer, size);
|
|
||||||
if (processedSize != 0)
|
|
||||||
*processedSize = processedSizeLoc;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
|
|
||||||
{
|
|
||||||
CFileInStream *s = (CFileInStream *)object;
|
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
{
|
|
||||||
LARGE_INTEGER value;
|
|
||||||
value.LowPart = (DWORD)pos;
|
|
||||||
value.HighPart = (LONG)((UInt64)pos >> 32);
|
|
||||||
#ifdef _SZ_FILE_SIZE_32
|
|
||||||
/* VC 6.0 has bug with >> 32 shifts. */
|
|
||||||
value.HighPart = 0;
|
|
||||||
#endif
|
|
||||||
value.LowPart = SetFilePointer(s->File, value.LowPart, &value.HighPart, FILE_BEGIN);
|
|
||||||
if (value.LowPart == 0xFFFFFFFF)
|
|
||||||
if(GetLastError() != NO_ERROR)
|
|
||||||
return SZE_FAIL;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int res = fseek(s->File, (long)pos, SEEK_SET);
|
|
||||||
if (res == 0)
|
|
||||||
return SZ_OK;
|
|
||||||
return SZE_FAIL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrintError(char *sz)
|
|
||||||
{
|
|
||||||
printf("\nERROR: %s\n", sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int numargs, char *args[])
|
|
||||||
{
|
|
||||||
CFileInStream archiveStream;
|
|
||||||
CArchiveDatabaseEx db;
|
|
||||||
SZ_RESULT res;
|
|
||||||
ISzAlloc allocImp;
|
|
||||||
ISzAlloc allocTempImp;
|
|
||||||
|
|
||||||
printf("\n7z ANSI-C Decoder 4.48 Copyright (c) 1999-2007 Igor Pavlov 2007-06-21\n");
|
|
||||||
if (numargs == 1)
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"\nUsage: 7zDec <command> <archive_name>\n\n"
|
|
||||||
"<Commands>\n"
|
|
||||||
" e: Extract files from archive\n"
|
|
||||||
" l: List contents of archive\n"
|
|
||||||
" t: Test integrity of archive\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (numargs < 3)
|
|
||||||
{
|
|
||||||
PrintError("incorrect command");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
archiveStream.File =
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ,
|
|
||||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (archiveStream.File == INVALID_HANDLE_VALUE)
|
|
||||||
#else
|
|
||||||
archiveStream.File = fopen(args[2], "rb");
|
|
||||||
if (archiveStream.File == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
PrintError("can not open input file");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
archiveStream.InStream.Read = SzFileReadImp;
|
|
||||||
archiveStream.InStream.Seek = SzFileSeekImp;
|
|
||||||
|
|
||||||
allocImp.Alloc = SzAlloc;
|
|
||||||
allocImp.Free = SzFree;
|
|
||||||
|
|
||||||
allocTempImp.Alloc = SzAllocTemp;
|
|
||||||
allocTempImp.Free = SzFreeTemp;
|
|
||||||
|
|
||||||
CrcGenerateTable();
|
|
||||||
|
|
||||||
SzArDbExInit(&db);
|
|
||||||
res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
char *command = args[1];
|
|
||||||
int listCommand = 0;
|
|
||||||
int testCommand = 0;
|
|
||||||
int extractCommand = 0;
|
|
||||||
if (strcmp(command, "l") == 0)
|
|
||||||
listCommand = 1;
|
|
||||||
if (strcmp(command, "t") == 0)
|
|
||||||
testCommand = 1;
|
|
||||||
else if (strcmp(command, "e") == 0)
|
|
||||||
extractCommand = 1;
|
|
||||||
|
|
||||||
if (listCommand)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < db.Database.NumFiles; i++)
|
|
||||||
{
|
|
||||||
CFileItem *f = db.Database.Files + i;
|
|
||||||
char s[32], t[32];
|
|
||||||
ConvertNumberToString(f->Size, s);
|
|
||||||
if (f->IsLastWriteTimeDefined)
|
|
||||||
ConvertFileTimeToString(&f->LastWriteTime, t);
|
|
||||||
else
|
|
||||||
strcpy(t, " ");
|
|
||||||
|
|
||||||
printf("%10s %s %s\n", s, t, f->Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (testCommand || extractCommand)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
|
|
||||||
/*
|
|
||||||
if you need cache, use these 3 variables.
|
|
||||||
if you use external function, you can make these variable as static.
|
|
||||||
*/
|
|
||||||
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
|
|
||||||
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
|
||||||
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
for (i = 0; i < db.Database.NumFiles; i++)
|
|
||||||
{
|
|
||||||
size_t offset;
|
|
||||||
size_t outSizeProcessed;
|
|
||||||
CFileItem *f = db.Database.Files + i;
|
|
||||||
if (f->IsDirectory)
|
|
||||||
printf("Directory ");
|
|
||||||
else
|
|
||||||
printf(testCommand ?
|
|
||||||
"Testing ":
|
|
||||||
"Extracting");
|
|
||||||
printf(" %s", f->Name);
|
|
||||||
if (f->IsDirectory)
|
|
||||||
{
|
|
||||||
printf("\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
res = SzExtract(&archiveStream.InStream, &db, i,
|
|
||||||
&blockIndex, &outBuffer, &outBufferSize,
|
|
||||||
&offset, &outSizeProcessed,
|
|
||||||
&allocImp, &allocTempImp);
|
|
||||||
if (res != SZ_OK)
|
|
||||||
break;
|
|
||||||
if (!testCommand)
|
|
||||||
{
|
|
||||||
MY_FILE_HANDLE outputHandle;
|
|
||||||
size_t processedSize;
|
|
||||||
char *fileName = f->Name;
|
|
||||||
size_t nameLen = strlen(f->Name);
|
|
||||||
for (; nameLen > 0; nameLen--)
|
|
||||||
if (f->Name[nameLen - 1] == '/')
|
|
||||||
{
|
|
||||||
fileName = f->Name + nameLen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
outputHandle =
|
|
||||||
#ifdef USE_WINDOWS_FUNCTIONS
|
|
||||||
CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ,
|
|
||||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (outputHandle == INVALID_HANDLE_VALUE)
|
|
||||||
#else
|
|
||||||
fopen(fileName, "wb+");
|
|
||||||
if (outputHandle == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
PrintError("can not open output file");
|
|
||||||
res = SZE_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed);
|
|
||||||
if (processedSize != outSizeProcessed)
|
|
||||||
{
|
|
||||||
PrintError("can not write output file");
|
|
||||||
res = SZE_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (MyCloseFile(outputHandle))
|
|
||||||
{
|
|
||||||
PrintError("can not close output file");
|
|
||||||
res = SZE_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
allocImp.Free(outBuffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PrintError("incorrect command");
|
|
||||||
res = SZE_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SzArDbExFree(&db, allocImp.Free);
|
|
||||||
|
|
||||||
MyCloseFile(archiveStream.File);
|
|
||||||
if (res == SZ_OK)
|
|
||||||
{
|
|
||||||
printf("\nEverything is Ok\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (res == (SZ_RESULT)SZE_NOTIMPL)
|
|
||||||
PrintError("decoder doesn't support this archive");
|
|
||||||
else if (res == (SZ_RESULT)SZE_OUTOFMEMORY)
|
|
||||||
PrintError("can not allocate memory");
|
|
||||||
else if (res == (SZ_RESULT)SZE_CRC_ERROR)
|
|
||||||
PrintError("CRC error");
|
|
||||||
else
|
|
||||||
printf("\nERROR #%d\n", res);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* 7zMethodID.c */
|
|
||||||
|
|
||||||
#include "7zMethodID.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
int AreMethodsEqual(CMethodID *a1, CMethodID *a2)
|
|
||||||
{
|
|
||||||
return (*a1 == *a2) ? 1 : 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* 7zMethodID.h */
|
|
||||||
|
|
||||||
#ifndef __7Z_METHOD_ID_H
|
|
||||||
#define __7Z_METHOD_ID_H
|
|
||||||
|
|
||||||
#include "../../Types.h"
|
|
||||||
|
|
||||||
typedef UInt64 CMethodID;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,211 +0,0 @@
|
|||||||
# Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4>
|
|
||||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
|
||||||
# ** DO NOT EDIT **
|
|
||||||
|
|
||||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
|
||||||
|
|
||||||
CFG=7z_C - Win32 Debug
|
|
||||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
|
||||||
!MESSAGE use the Export Makefile command and run
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "7z_C.mak".
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE You can specify a configuration when running NMAKE
|
|
||||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug"
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE Possible choices for configuration are:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application")
|
|
||||||
!MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application")
|
|
||||||
!MESSAGE
|
|
||||||
|
|
||||||
# Begin Project
|
|
||||||
# PROP AllowPerConfigDependencies 0
|
|
||||||
# PROP Scc_ProjName ""
|
|
||||||
# PROP Scc_LocalPath ""
|
|
||||||
CPP=cl.exe
|
|
||||||
RSC=rc.exe
|
|
||||||
|
|
||||||
!IF "$(CFG)" == "7z_C - Win32 Release"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 0
|
|
||||||
# PROP BASE Output_Dir "Release"
|
|
||||||
# PROP BASE Intermediate_Dir "Release"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 0
|
|
||||||
# PROP Output_Dir "Release"
|
|
||||||
# PROP Intermediate_Dir "Release"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
|
||||||
# ADD CPP /nologo /MD /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c
|
|
||||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
|
||||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98
|
|
||||||
# SUBTRACT LINK32 /pdb:none
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "7z_C - Win32 Debug"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "Debug"
|
|
||||||
# PROP BASE Intermediate_Dir "Debug"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "Debug"
|
|
||||||
# PROP Intermediate_Dir "Debug"
|
|
||||||
# PROP Ignore_Export_Lib 0
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c
|
|
||||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# Begin Target
|
|
||||||
|
|
||||||
# Name "7z_C - Win32 Release"
|
|
||||||
# Name "7z_C - Win32 Debug"
|
|
||||||
# Begin Group "LZMA"
|
|
||||||
|
|
||||||
# PROP Default_Filter ""
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\Lzma\LzmaDecode.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\Lzma\LzmaDecode.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\Lzma\LzmaTypes.h
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Common"
|
|
||||||
|
|
||||||
# PROP Default_Filter ""
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\7zCrc.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\7zCrc.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Types.h
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Branch"
|
|
||||||
|
|
||||||
# PROP Default_Filter ""
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\Branch\BranchTypes.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\Branch\BranchX86.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\Branch\BranchX86.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\Branch\BranchX86_2.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=..\..\Compress\Branch\BranchX86_2.h
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zAlloc.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zAlloc.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zBuffer.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zBuffer.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zDecode.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zDecode.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zExtract.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zExtract.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zHeader.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zHeader.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zIn.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zIn.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zItem.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zItem.h
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zMain.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zMethodID.c
|
|
||||||
# End Source File
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\7zMethodID.h
|
|
||||||
# End Source File
|
|
||||||
# End Target
|
|
||||||
# End Project
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
|
||||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Project: "7z_C"=.\7z_C.dsp - Package Owner=<4>
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<4>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Global:
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<3>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
PROG = 7zDec.exe
|
|
||||||
|
|
||||||
!IFDEF CPU
|
|
||||||
LIBS = $(LIBS) bufferoverflowU.lib
|
|
||||||
CFLAGS = $(CFLAGS) -GS- -Zc:forScope -WX -GS- -Gy -W4
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
!IFNDEF O
|
|
||||||
!IFDEF CPU
|
|
||||||
O=$(CPU)
|
|
||||||
!ELSE
|
|
||||||
O=O
|
|
||||||
!ENDIF
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -D_LZMA_IN_CB
|
|
||||||
CFLAGS_O1 = $(CFLAGS) -O1
|
|
||||||
CFLAGS_O2 = $(CFLAGS) -O2
|
|
||||||
|
|
||||||
LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF
|
|
||||||
|
|
||||||
PROGPATH = $O\$(PROG)
|
|
||||||
|
|
||||||
COMPL_O1 = $(CPP) $(CFLAGS_O1) $**
|
|
||||||
COMPL_O2 = $(CPP) $(CFLAGS_O2) $**
|
|
||||||
COMPL = $(CPP) $(CFLAGS_O1) $**
|
|
||||||
|
|
||||||
C_OBJS = \
|
|
||||||
$O\7zCrc.obj \
|
|
||||||
|
|
||||||
|
|
||||||
7Z_OBJS = \
|
|
||||||
$O\7zAlloc.obj \
|
|
||||||
$O\7zBuffer.obj \
|
|
||||||
$O\7zDecode.obj \
|
|
||||||
$O\7zExtract.obj \
|
|
||||||
$O\7zHeader.obj \
|
|
||||||
$O\7zIn.obj \
|
|
||||||
$O\7zItem.obj \
|
|
||||||
$O\7zMain.obj \
|
|
||||||
$O\7zMethodID.obj \
|
|
||||||
|
|
||||||
OBJS = \
|
|
||||||
$(7Z_OBJS) \
|
|
||||||
$O\LzmaDecode.obj \
|
|
||||||
$O\BranchX86.obj \
|
|
||||||
$O\BranchX86_2.obj \
|
|
||||||
$(C_OBJS) \
|
|
||||||
|
|
||||||
all: $(PROGPATH)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch
|
|
||||||
|
|
||||||
$O:
|
|
||||||
if not exist "$O" mkdir "$O"
|
|
||||||
|
|
||||||
$(PROGPATH): $O $(OBJS)
|
|
||||||
link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
|
|
||||||
|
|
||||||
|
|
||||||
$(7Z_OBJS): $(*B).c
|
|
||||||
$(COMPL)
|
|
||||||
$O\LzmaDecode.obj: ../../Compress/Lzma/$(*B).c
|
|
||||||
$(COMPL_O2)
|
|
||||||
|
|
||||||
$O\BranchX86.obj: ../../Compress/Branch/$(*B).c
|
|
||||||
$(COMPL_O2)
|
|
||||||
|
|
||||||
$O\BranchX86_2.obj: ../../Compress/Branch/$(*B).c
|
|
||||||
$(COMPL_O2)
|
|
||||||
|
|
||||||
$(C_OBJS): ../../$(*B).c
|
|
||||||
$(COMPL_O2)
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
PROG = 7zDec
|
|
||||||
CXX = g++
|
|
||||||
LIB =
|
|
||||||
RM = rm -f
|
|
||||||
CFLAGS = -c -O2 -Wall -D_LZMA_IN_CB
|
|
||||||
|
|
||||||
OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o BranchX86.o BranchX86_2.o
|
|
||||||
|
|
||||||
all: $(PROG)
|
|
||||||
|
|
||||||
$(PROG): $(OBJS)
|
|
||||||
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
|
|
||||||
|
|
||||||
7zAlloc.o: 7zAlloc.c
|
|
||||||
$(CXX) $(CFLAGS) 7zAlloc.c
|
|
||||||
|
|
||||||
7zBuffer.o: 7zBuffer.c
|
|
||||||
$(CXX) $(CFLAGS) 7zBuffer.c
|
|
||||||
|
|
||||||
7zCrc.o: ../../7zCrc.c
|
|
||||||
$(CXX) $(CFLAGS) ../../7zCrc.c
|
|
||||||
|
|
||||||
7zDecode.o: 7zDecode.c
|
|
||||||
$(CXX) $(CFLAGS) 7zDecode.c
|
|
||||||
|
|
||||||
7zExtract.o: 7zExtract.c
|
|
||||||
$(CXX) $(CFLAGS) 7zExtract.c
|
|
||||||
|
|
||||||
7zHeader.o: 7zHeader.c
|
|
||||||
$(CXX) $(CFLAGS) 7zHeader.c
|
|
||||||
|
|
||||||
7zIn.o: 7zIn.c
|
|
||||||
$(CXX) $(CFLAGS) 7zIn.c
|
|
||||||
|
|
||||||
7zItem.o: 7zItem.c
|
|
||||||
$(CXX) $(CFLAGS) 7zItem.c
|
|
||||||
|
|
||||||
7zMain.o: 7zMain.c
|
|
||||||
$(CXX) $(CFLAGS) 7zMain.c
|
|
||||||
|
|
||||||
7zMethodID.o: 7zMethodID.c
|
|
||||||
$(CXX) $(CFLAGS) 7zMethodID.c
|
|
||||||
|
|
||||||
LzmaDecode.o: ../../Compress/Lzma/LzmaDecode.c
|
|
||||||
$(CXX) $(CFLAGS) ../../Compress/Lzma/LzmaDecode.c
|
|
||||||
|
|
||||||
BranchX86.o: ../../Compress/Branch/BranchX86.c
|
|
||||||
$(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86.c
|
|
||||||
|
|
||||||
BranchX86_2.o: ../../Compress/Branch/BranchX86_2.c
|
|
||||||
$(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86_2.c
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-$(RM) $(PROG) $(OBJS)
|
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
/* BranchARM.c */
|
|
||||||
|
|
||||||
#include "BranchARM.h"
|
|
||||||
|
|
||||||
UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i + 4 <= size; i += 4)
|
|
||||||
{
|
|
||||||
if (data[i + 3] == 0xEB)
|
|
||||||
{
|
|
||||||
UInt32 dest;
|
|
||||||
UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]);
|
|
||||||
src <<= 2;
|
|
||||||
if (encoding)
|
|
||||||
dest = nowPos + i + 8 + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + i + 8);
|
|
||||||
dest >>= 2;
|
|
||||||
data[i + 2] = (Byte)(dest >> 16);
|
|
||||||
data[i + 1] = (Byte)(dest >> 8);
|
|
||||||
data[i + 0] = (Byte)dest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* BranchARM.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCH_ARM_H
|
|
||||||
#define __BRANCH_ARM_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/* BranchARMThumb.c */
|
|
||||||
|
|
||||||
#include "BranchARMThumb.h"
|
|
||||||
|
|
||||||
UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i + 4 <= size; i += 2)
|
|
||||||
{
|
|
||||||
if ((data[i + 1] & 0xF8) == 0xF0 &&
|
|
||||||
(data[i + 3] & 0xF8) == 0xF8)
|
|
||||||
{
|
|
||||||
UInt32 dest;
|
|
||||||
UInt32 src =
|
|
||||||
((data[i + 1] & 0x7) << 19) |
|
|
||||||
(data[i + 0] << 11) |
|
|
||||||
((data[i + 3] & 0x7) << 8) |
|
|
||||||
(data[i + 2]);
|
|
||||||
|
|
||||||
src <<= 1;
|
|
||||||
if (encoding)
|
|
||||||
dest = nowPos + i + 4 + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + i + 4);
|
|
||||||
dest >>= 1;
|
|
||||||
|
|
||||||
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
|
|
||||||
data[i + 0] = (Byte)(dest >> 11);
|
|
||||||
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
|
|
||||||
data[i + 2] = (Byte)dest;
|
|
||||||
i += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* BranchARMThumb.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCH_ARM_THUMB_H
|
|
||||||
#define __BRANCH_ARM_THUMB_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
/* BranchIA64.c */
|
|
||||||
|
|
||||||
#include "BranchIA64.h"
|
|
||||||
|
|
||||||
const Byte kBranchTable[32] =
|
|
||||||
{
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
4, 4, 6, 6, 0, 0, 7, 7,
|
|
||||||
4, 4, 0, 0, 4, 4, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i + 16 <= size; i += 16)
|
|
||||||
{
|
|
||||||
UInt32 instrTemplate = data[i] & 0x1F;
|
|
||||||
UInt32 mask = kBranchTable[instrTemplate];
|
|
||||||
UInt32 bitPos = 5;
|
|
||||||
int slot;
|
|
||||||
for (slot = 0; slot < 3; slot++, bitPos += 41)
|
|
||||||
{
|
|
||||||
UInt32 bytePos, bitRes;
|
|
||||||
UInt64 instruction, instNorm;
|
|
||||||
int j;
|
|
||||||
if (((mask >> slot) & 1) == 0)
|
|
||||||
continue;
|
|
||||||
bytePos = (bitPos >> 3);
|
|
||||||
bitRes = bitPos & 0x7;
|
|
||||||
instruction = 0;
|
|
||||||
for (j = 0; j < 6; j++)
|
|
||||||
instruction += (UInt64)(data[i + j + bytePos]) << (8 * j);
|
|
||||||
|
|
||||||
instNorm = instruction >> bitRes;
|
|
||||||
if (((instNorm >> 37) & 0xF) == 0x5
|
|
||||||
&& ((instNorm >> 9) & 0x7) == 0
|
|
||||||
/* && (instNorm & 0x3F)== 0 */
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF);
|
|
||||||
UInt32 dest;
|
|
||||||
src |= ((UInt32)(instNorm >> 36) & 1) << 20;
|
|
||||||
|
|
||||||
src <<= 4;
|
|
||||||
|
|
||||||
if (encoding)
|
|
||||||
dest = nowPos + i + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + i);
|
|
||||||
|
|
||||||
dest >>= 4;
|
|
||||||
|
|
||||||
instNorm &= ~((UInt64)(0x8FFFFF) << 13);
|
|
||||||
instNorm |= ((UInt64)(dest & 0xFFFFF) << 13);
|
|
||||||
instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20));
|
|
||||||
|
|
||||||
instruction &= (1 << bitRes) - 1;
|
|
||||||
instruction |= (instNorm << bitRes);
|
|
||||||
for (j = 0; j < 6; j++)
|
|
||||||
data[i + j + bytePos] = (Byte)(instruction >> (8 * j));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* BranchIA64.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCH_IA64_H
|
|
||||||
#define __BRANCH_IA64_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/* BranchPPC.c */
|
|
||||||
|
|
||||||
#include "BranchPPC.h"
|
|
||||||
|
|
||||||
UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i + 4 <= size; i += 4)
|
|
||||||
{
|
|
||||||
/* PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) */
|
|
||||||
if ((data[i] >> 2) == 0x12 &&
|
|
||||||
(
|
|
||||||
(data[i + 3] & 3) == 1
|
|
||||||
/* || (data[i+3] & 3) == 3 */
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UInt32 src = ((data[i + 0] & 3) << 24) |
|
|
||||||
(data[i + 1] << 16) |
|
|
||||||
(data[i + 2] << 8) |
|
|
||||||
(data[i + 3] & (~3));
|
|
||||||
|
|
||||||
UInt32 dest;
|
|
||||||
if (encoding)
|
|
||||||
dest = nowPos + i + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + i);
|
|
||||||
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
|
|
||||||
data[i + 1] = (Byte)(dest >> 16);
|
|
||||||
data[i + 2] = (Byte)(dest >> 8);
|
|
||||||
data[i + 3] &= 0x3;
|
|
||||||
data[i + 3] |= dest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* BranchPPC.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCH_PPC_H
|
|
||||||
#define __BRANCH_PPC_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/* BranchSPARC.c */
|
|
||||||
|
|
||||||
#include "BranchSPARC.h"
|
|
||||||
|
|
||||||
UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i + 4 <= size; i += 4)
|
|
||||||
{
|
|
||||||
if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 ||
|
|
||||||
data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)
|
|
||||||
{
|
|
||||||
UInt32 src =
|
|
||||||
((UInt32)data[i + 0] << 24) |
|
|
||||||
((UInt32)data[i + 1] << 16) |
|
|
||||||
((UInt32)data[i + 2] << 8) |
|
|
||||||
((UInt32)data[i + 3]);
|
|
||||||
UInt32 dest;
|
|
||||||
|
|
||||||
src <<= 2;
|
|
||||||
if (encoding)
|
|
||||||
dest = nowPos + i + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + i);
|
|
||||||
dest >>= 2;
|
|
||||||
|
|
||||||
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
|
|
||||||
|
|
||||||
data[i + 0] = (Byte)(dest >> 24);
|
|
||||||
data[i + 1] = (Byte)(dest >> 16);
|
|
||||||
data[i + 2] = (Byte)(dest >> 8);
|
|
||||||
data[i + 3] = (Byte)dest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
/* BranchSPARC.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCH_SPARC_H
|
|
||||||
#define __BRANCH_SPARC_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/* BranchTypes.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCHTYPES_H
|
|
||||||
#define __BRANCHTYPES_H
|
|
||||||
|
|
||||||
#ifndef _7ZIP_BYTE_DEFINED
|
|
||||||
#define _7ZIP_BYTE_DEFINED
|
|
||||||
typedef unsigned char Byte;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _7ZIP_UINT16_DEFINED
|
|
||||||
#define _7ZIP_UINT16_DEFINED
|
|
||||||
typedef unsigned short UInt16;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _7ZIP_UINT32_DEFINED
|
|
||||||
#define _7ZIP_UINT32_DEFINED
|
|
||||||
#ifdef _LZMA_UINT32_IS_ULONG
|
|
||||||
typedef unsigned long UInt32;
|
|
||||||
#else
|
|
||||||
typedef unsigned int UInt32;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _7ZIP_UINT64_DEFINED
|
|
||||||
#define _7ZIP_UINT64_DEFINED
|
|
||||||
#ifdef _SZ_NO_INT_64
|
|
||||||
typedef unsigned long UInt64;
|
|
||||||
#else
|
|
||||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
|
||||||
typedef unsigned __int64 UInt64;
|
|
||||||
#else
|
|
||||||
typedef unsigned long long int UInt64;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* #define _LZMA_NO_SYSTEM_SIZE_T */
|
|
||||||
/* You can use it, if you don't want <stddef.h> */
|
|
||||||
|
|
||||||
#ifndef _7ZIP_SIZET_DEFINED
|
|
||||||
#define _7ZIP_SIZET_DEFINED
|
|
||||||
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
|
||||||
typedef UInt32 SizeT;
|
|
||||||
#else
|
|
||||||
#include <stddef.h>
|
|
||||||
typedef size_t SizeT;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
/* BranchX86.c */
|
|
||||||
|
|
||||||
#include "BranchX86.h"
|
|
||||||
|
|
||||||
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
|
|
||||||
|
|
||||||
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
|
|
||||||
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
|
|
||||||
|
|
||||||
SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *prevMaskMix, int encoding)
|
|
||||||
{
|
|
||||||
SizeT bufferPos = 0, prevPosT;
|
|
||||||
UInt32 prevMask = *prevMaskMix & 0x7;
|
|
||||||
if (endPos < 5)
|
|
||||||
return 0;
|
|
||||||
nowPos += 5;
|
|
||||||
prevPosT = (SizeT)0 - 1;
|
|
||||||
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
Byte *p = buffer + bufferPos;
|
|
||||||
Byte *limit = buffer + endPos - 4;
|
|
||||||
for (; p < limit; p++)
|
|
||||||
if ((*p & 0xFE) == 0xE8)
|
|
||||||
break;
|
|
||||||
bufferPos = (SizeT)(p - buffer);
|
|
||||||
if (p >= limit)
|
|
||||||
break;
|
|
||||||
prevPosT = bufferPos - prevPosT;
|
|
||||||
if (prevPosT > 3)
|
|
||||||
prevMask = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
|
||||||
if (prevMask != 0)
|
|
||||||
{
|
|
||||||
Byte b = p[4 - kMaskToBitNumber[prevMask]];
|
|
||||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
|
|
||||||
{
|
|
||||||
prevPosT = bufferPos;
|
|
||||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
|
||||||
bufferPos++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prevPosT = bufferPos;
|
|
||||||
|
|
||||||
if (Test86MSByte(p[4]))
|
|
||||||
{
|
|
||||||
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
|
||||||
UInt32 dest;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
Byte b;
|
|
||||||
int index;
|
|
||||||
if (encoding)
|
|
||||||
dest = (nowPos + (UInt32)bufferPos) + src;
|
|
||||||
else
|
|
||||||
dest = src - (nowPos + (UInt32)bufferPos);
|
|
||||||
if (prevMask == 0)
|
|
||||||
break;
|
|
||||||
index = kMaskToBitNumber[prevMask] * 8;
|
|
||||||
b = (Byte)(dest >> (24 - index));
|
|
||||||
if (!Test86MSByte(b))
|
|
||||||
break;
|
|
||||||
src = dest ^ ((1 << (32 - index)) - 1);
|
|
||||||
}
|
|
||||||
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
|
|
||||||
p[3] = (Byte)(dest >> 16);
|
|
||||||
p[2] = (Byte)(dest >> 8);
|
|
||||||
p[1] = (Byte)dest;
|
|
||||||
bufferPos += 5;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
|
||||||
bufferPos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prevPosT = bufferPos - prevPosT;
|
|
||||||
*prevMaskMix = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
|
||||||
return bufferPos;
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
/* BranchX86.h */
|
|
||||||
|
|
||||||
#ifndef __BRANCHX86_H
|
|
||||||
#define __BRANCHX86_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
#define x86_Convert_Init(state) { state = 0; }
|
|
||||||
|
|
||||||
SizeT x86_Convert(Byte *buffer, SizeT endPos, UInt32 nowPos, UInt32 *state, int encoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
// BranchX86_2.c
|
|
||||||
|
|
||||||
#include "BranchX86_2.h"
|
|
||||||
|
|
||||||
#include "../../Alloc.h"
|
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
|
||||||
#define CProb UInt32
|
|
||||||
#else
|
|
||||||
#define CProb UInt16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
|
|
||||||
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
|
|
||||||
|
|
||||||
#define kNumTopBits 24
|
|
||||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
|
||||||
|
|
||||||
#define kNumBitModelTotalBits 11
|
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
|
||||||
#define kNumMoveBits 5
|
|
||||||
|
|
||||||
#define RC_READ_BYTE (*Buffer++)
|
|
||||||
|
|
||||||
#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
|
|
||||||
{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
|
|
||||||
|
|
||||||
#define RC_TEST { if (Buffer == BufferLim) return BCJ2_RESULT_DATA_ERROR; }
|
|
||||||
|
|
||||||
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
|
|
||||||
|
|
||||||
#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
|
|
||||||
|
|
||||||
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
|
|
||||||
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
|
|
||||||
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
|
|
||||||
// #define UpdateBit0(p) Range = bound; *(p) = (CProb)(*(p) + ((kBitModelTotal - *(p)) >> kNumMoveBits));
|
|
||||||
// #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) = (CProb)(*(p) - (*(p) >> kNumMoveBits));
|
|
||||||
|
|
||||||
int x86_2_Decode(
|
|
||||||
const Byte *buf0, SizeT size0,
|
|
||||||
const Byte *buf1, SizeT size1,
|
|
||||||
const Byte *buf2, SizeT size2,
|
|
||||||
const Byte *buf3, SizeT size3,
|
|
||||||
Byte *outBuf, SizeT outSize)
|
|
||||||
{
|
|
||||||
CProb p[256 + 2];
|
|
||||||
SizeT inPos = 0, outPos = 0;
|
|
||||||
|
|
||||||
const Byte *Buffer, *BufferLim;
|
|
||||||
UInt32 Range, Code;
|
|
||||||
Byte prevByte = 0;
|
|
||||||
|
|
||||||
unsigned int i;
|
|
||||||
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
RC_INIT(buf3, size3);
|
|
||||||
|
|
||||||
if (outSize == 0)
|
|
||||||
return BCJ2_RESULT_OK;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
Byte b;
|
|
||||||
CProb *prob;
|
|
||||||
UInt32 bound;
|
|
||||||
|
|
||||||
SizeT limit = size0 - inPos;
|
|
||||||
if (outSize - outPos < limit)
|
|
||||||
limit = outSize - outPos;
|
|
||||||
while (limit != 0)
|
|
||||||
{
|
|
||||||
Byte b = buf0[inPos];
|
|
||||||
outBuf[outPos++] = b;
|
|
||||||
if (IsJ(prevByte, b))
|
|
||||||
break;
|
|
||||||
inPos++;
|
|
||||||
prevByte = b;
|
|
||||||
limit--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (limit == 0 || outPos == outSize)
|
|
||||||
break;
|
|
||||||
|
|
||||||
b = buf0[inPos++];
|
|
||||||
|
|
||||||
if (b == 0xE8)
|
|
||||||
prob = p + prevByte;
|
|
||||||
else if (b == 0xE9)
|
|
||||||
prob = p + 256;
|
|
||||||
else
|
|
||||||
prob = p + 257;
|
|
||||||
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob)
|
|
||||||
prevByte = b;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 dest;
|
|
||||||
const Byte *v;
|
|
||||||
UpdateBit1(prob)
|
|
||||||
if (b == 0xE8)
|
|
||||||
{
|
|
||||||
v = buf1;
|
|
||||||
if (size1 < 4)
|
|
||||||
return BCJ2_RESULT_DATA_ERROR;
|
|
||||||
buf1 += 4;
|
|
||||||
size1 -= 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v = buf2;
|
|
||||||
if (size2 < 4)
|
|
||||||
return BCJ2_RESULT_DATA_ERROR;
|
|
||||||
buf2 += 4;
|
|
||||||
size2 -= 4;
|
|
||||||
}
|
|
||||||
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
|
|
||||||
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
|
|
||||||
outBuf[outPos++] = (Byte)dest;
|
|
||||||
if (outPos == outSize)
|
|
||||||
break;
|
|
||||||
outBuf[outPos++] = (Byte)(dest >> 8);
|
|
||||||
if (outPos == outSize)
|
|
||||||
break;
|
|
||||||
outBuf[outPos++] = (Byte)(dest >> 16);
|
|
||||||
if (outPos == outSize)
|
|
||||||
break;
|
|
||||||
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (outPos == outSize) ? BCJ2_RESULT_OK : BCJ2_RESULT_DATA_ERROR;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
// BranchX86_2.h
|
|
||||||
|
|
||||||
#ifndef __BRANCHX86_2_H
|
|
||||||
#define __BRANCHX86_2_H
|
|
||||||
|
|
||||||
#include "BranchTypes.h"
|
|
||||||
|
|
||||||
#define BCJ2_RESULT_OK 0
|
|
||||||
#define BCJ2_RESULT_DATA_ERROR 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
Conditions:
|
|
||||||
outSize <= FullOutputSize,
|
|
||||||
where FullOutputSize is full size of output stream of x86_2 filter.
|
|
||||||
|
|
||||||
If buf0 overlaps outBuf, there are two required conditions:
|
|
||||||
1) (buf0 >= outBuf)
|
|
||||||
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
|
||||||
*/
|
|
||||||
|
|
||||||
int x86_2_Decode(
|
|
||||||
const Byte *buf0, SizeT size0,
|
|
||||||
const Byte *buf1, SizeT size1,
|
|
||||||
const Byte *buf2, SizeT size2,
|
|
||||||
const Byte *buf3, SizeT size3,
|
|
||||||
Byte *outBuf, SizeT outSize);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
/* Compress/HuffmanEncode.c */
|
|
||||||
|
|
||||||
#include "HuffmanEncode.h"
|
|
||||||
#include "../../Sort.h"
|
|
||||||
|
|
||||||
#define kMaxLen 16
|
|
||||||
#define NUM_BITS 10
|
|
||||||
#define MASK ((1 << NUM_BITS) - 1)
|
|
||||||
|
|
||||||
#define NUM_COUNTERS 64
|
|
||||||
|
|
||||||
/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M */
|
|
||||||
#define HUFFMAN_SPEED_OPT
|
|
||||||
|
|
||||||
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen)
|
|
||||||
{
|
|
||||||
UInt32 num = 0;
|
|
||||||
/* if (maxLen > 10) maxLen = 10; */
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
|
|
||||||
#ifdef HUFFMAN_SPEED_OPT
|
|
||||||
|
|
||||||
UInt32 counters[NUM_COUNTERS];
|
|
||||||
for (i = 0; i < NUM_COUNTERS; i++)
|
|
||||||
counters[i] = 0;
|
|
||||||
for (i = 0; i < numSymbols; i++)
|
|
||||||
{
|
|
||||||
UInt32 freq = freqs[i];
|
|
||||||
counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 1; i < NUM_COUNTERS; i++)
|
|
||||||
{
|
|
||||||
UInt32 temp = counters[i];
|
|
||||||
counters[i] = num;
|
|
||||||
num += temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < numSymbols; i++)
|
|
||||||
{
|
|
||||||
UInt32 freq = freqs[i];
|
|
||||||
if (freq == 0)
|
|
||||||
lens[i] = 0;
|
|
||||||
else
|
|
||||||
p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS);
|
|
||||||
}
|
|
||||||
counters[0] = 0;
|
|
||||||
HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
for (i = 0; i < numSymbols; i++)
|
|
||||||
{
|
|
||||||
UInt32 freq = freqs[i];
|
|
||||||
if (freq == 0)
|
|
||||||
lens[i] = 0;
|
|
||||||
else
|
|
||||||
p[num++] = i | (freq << NUM_BITS);
|
|
||||||
}
|
|
||||||
HeapSort(p, num);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num < 2)
|
|
||||||
{
|
|
||||||
int minCode = 0;
|
|
||||||
int maxCode = 1;
|
|
||||||
if (num == 1)
|
|
||||||
{
|
|
||||||
maxCode = p[0] & MASK;
|
|
||||||
if (maxCode == 0)
|
|
||||||
maxCode++;
|
|
||||||
}
|
|
||||||
p[minCode] = 0;
|
|
||||||
p[maxCode] = 1;
|
|
||||||
lens[minCode] = lens[maxCode] = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 b, e, i;
|
|
||||||
|
|
||||||
i = b = e = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UInt32 n, m, freq;
|
|
||||||
n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
|
|
||||||
freq = (p[n] & ~MASK);
|
|
||||||
p[n] = (p[n] & MASK) | (e << NUM_BITS);
|
|
||||||
m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
|
|
||||||
freq += (p[m] & ~MASK);
|
|
||||||
p[m] = (p[m] & MASK) | (e << NUM_BITS);
|
|
||||||
p[e] = (p[e] & MASK) | freq;
|
|
||||||
e++;
|
|
||||||
}
|
|
||||||
while (num - e > 1);
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 lenCounters[kMaxLen + 1];
|
|
||||||
for (i = 0; i <= kMaxLen; i++)
|
|
||||||
lenCounters[i] = 0;
|
|
||||||
|
|
||||||
p[--e] &= MASK;
|
|
||||||
lenCounters[1] = 2;
|
|
||||||
while (e > 0)
|
|
||||||
{
|
|
||||||
UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1;
|
|
||||||
p[e] = (p[e] & MASK) | (len << NUM_BITS);
|
|
||||||
if (len >= maxLen)
|
|
||||||
for (len = maxLen - 1; lenCounters[len] == 0; len--);
|
|
||||||
lenCounters[len]--;
|
|
||||||
lenCounters[len + 1] += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 len;
|
|
||||||
i = 0;
|
|
||||||
for (len = maxLen; len != 0; len--)
|
|
||||||
{
|
|
||||||
UInt32 num;
|
|
||||||
for (num = lenCounters[len]; num != 0; num--)
|
|
||||||
lens[p[i++] & MASK] = (Byte)len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 nextCodes[kMaxLen + 1];
|
|
||||||
{
|
|
||||||
UInt32 code = 0;
|
|
||||||
UInt32 len;
|
|
||||||
for (len = 1; len <= kMaxLen; len++)
|
|
||||||
nextCodes[len] = code = (code + lenCounters[len - 1]) << 1;
|
|
||||||
}
|
|
||||||
/* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < numSymbols; i++)
|
|
||||||
p[i] = nextCodes[lens[i]]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
/* Compress/HuffmanEncode.h */
|
|
||||||
|
|
||||||
#ifndef __COMPRESS_HUFFMANENCODE_H
|
|
||||||
#define __COMPRESS_HUFFMANENCODE_H
|
|
||||||
|
|
||||||
#include "../../Types.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
Conditions:
|
|
||||||
num <= 1024 = 2 ^ NUM_BITS
|
|
||||||
Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS)
|
|
||||||
maxLen <= 16 = kMaxLen
|
|
||||||
Num_Items(p) >= HUFFMAN_TEMP_SIZE(num)
|
|
||||||
*/
|
|
||||||
|
|
||||||
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
/* LzHash.h */
|
|
||||||
|
|
||||||
#ifndef __C_LZHASH_H
|
|
||||||
#define __C_LZHASH_H
|
|
||||||
|
|
||||||
#define kHash2Size (1 << 10)
|
|
||||||
#define kHash3Size (1 << 16)
|
|
||||||
#define kHash4Size (1 << 20)
|
|
||||||
|
|
||||||
#define kFix3HashSize (kHash2Size)
|
|
||||||
#define kFix4HashSize (kHash2Size + kHash3Size)
|
|
||||||
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
|
||||||
|
|
||||||
#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
|
|
||||||
|
|
||||||
#define HASH3_CALC { \
|
|
||||||
UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
|
|
||||||
hash2Value = temp & (kHash2Size - 1); \
|
|
||||||
hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
|
||||||
|
|
||||||
#define HASH4_CALC { \
|
|
||||||
UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
|
|
||||||
hash2Value = temp & (kHash2Size - 1); \
|
|
||||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
|
||||||
hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & p->hashMask; }
|
|
||||||
|
|
||||||
#define HASH5_CALC { \
|
|
||||||
UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
|
|
||||||
hash2Value = temp & (kHash2Size - 1); \
|
|
||||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
|
||||||
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)); \
|
|
||||||
hashValue = (hash4Value ^ (g_CrcTable[cur[4]] << 3)) & p->hashMask; \
|
|
||||||
hash4Value &= (kHash4Size - 1); }
|
|
||||||
|
|
||||||
/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ g_CrcTable[cur[2]]) & 0xFFFF; */
|
|
||||||
#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ g_CrcTable[cur[1]]) & 0xFFFF;
|
|
||||||
|
|
||||||
|
|
||||||
#define MT_HASH2_CALC \
|
|
||||||
hash2Value = (g_CrcTable[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
|
||||||
|
|
||||||
#define MT_HASH3_CALC { \
|
|
||||||
UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
|
|
||||||
hash2Value = temp & (kHash2Size - 1); \
|
|
||||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
|
||||||
|
|
||||||
#define MT_HASH4_CALC { \
|
|
||||||
UInt32 temp = g_CrcTable[cur[0]] ^ cur[1]; \
|
|
||||||
hash2Value = temp & (kHash2Size - 1); \
|
|
||||||
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
|
|
||||||
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (g_CrcTable[cur[3]] << 5)) & (kHash4Size - 1); }
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,742 +0,0 @@
|
|||||||
/* MatchFinder.c */
|
|
||||||
/* Please call InitCrcTable before */
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "MatchFinder.h"
|
|
||||||
#include "LzHash.h"
|
|
||||||
|
|
||||||
#include "../../7zCrc.h"
|
|
||||||
|
|
||||||
#define kEmptyHashValue 0
|
|
||||||
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
|
|
||||||
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
|
|
||||||
#define kNormalizeMask (~(kNormalizeStepMin - 1))
|
|
||||||
#define kMaxHistorySize ((UInt32)3 << 30)
|
|
||||||
|
|
||||||
#define kStartMaxLen 3
|
|
||||||
|
|
||||||
void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
if (!p->directInput)
|
|
||||||
{
|
|
||||||
alloc->Free(p->bufferBase);
|
|
||||||
p->bufferBase = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
|
|
||||||
|
|
||||||
int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
|
|
||||||
if (p->directInput)
|
|
||||||
{
|
|
||||||
p->blockSize = blockSize;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (p->bufferBase == 0 || p->blockSize != blockSize)
|
|
||||||
{
|
|
||||||
LzInWindow_Free(p, alloc);
|
|
||||||
p->blockSize = blockSize;
|
|
||||||
p->bufferBase = (Byte *)alloc->Alloc(blockSize);
|
|
||||||
}
|
|
||||||
return (p->bufferBase != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
|
|
||||||
Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
|
|
||||||
|
|
||||||
UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
|
|
||||||
|
|
||||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
|
|
||||||
{
|
|
||||||
p->posLimit -= subValue;
|
|
||||||
p->pos -= subValue;
|
|
||||||
p->streamPos -= subValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_ReadBlock(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
if (p->streamEndWasReached || p->result != SZ_OK)
|
|
||||||
return;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
Byte *dest = p->buffer + (p->streamPos - p->pos);
|
|
||||||
UInt32 numReadBytes;
|
|
||||||
UInt32 size = (UInt32)(p->bufferBase + p->blockSize - dest);
|
|
||||||
if (size == 0)
|
|
||||||
return;
|
|
||||||
p->result = p->stream->Read(p->stream, dest, size, &numReadBytes);
|
|
||||||
if (p->result != SZ_OK)
|
|
||||||
return;
|
|
||||||
if (numReadBytes == 0)
|
|
||||||
{
|
|
||||||
p->streamEndWasReached = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
p->streamPos += numReadBytes;
|
|
||||||
if (p->streamPos - p->pos > p->keepSizeAfter)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_MoveBlock(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
memmove(p->bufferBase,
|
|
||||||
p->buffer - p->keepSizeBefore,
|
|
||||||
p->streamPos - p->pos + p->keepSizeBefore);
|
|
||||||
p->buffer = p->bufferBase + p->keepSizeBefore;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MatchFinder_NeedMove(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
/* if (p->streamEndWasReached) return 0; */
|
|
||||||
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_ReadIfRequired(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
if (p->streamEndWasReached)
|
|
||||||
return;
|
|
||||||
if (p->keepSizeAfter >= p->streamPos - p->pos)
|
|
||||||
MatchFinder_ReadBlock(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
if (MatchFinder_NeedMove(p))
|
|
||||||
MatchFinder_MoveBlock(p);
|
|
||||||
MatchFinder_ReadBlock(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_SetDefaultSettings(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
p->cutValue = 32;
|
|
||||||
p->btMode = 1;
|
|
||||||
p->numHashBytes = 4;
|
|
||||||
/* p->skipModeBits = 0; */
|
|
||||||
p->directInput = 0;
|
|
||||||
p->bigHash = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_Construct(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
p->bufferBase = 0;
|
|
||||||
p->directInput = 0;
|
|
||||||
p->hash = 0;
|
|
||||||
MatchFinder_SetDefaultSettings(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
alloc->Free(p->hash);
|
|
||||||
p->hash = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
MatchFinder_FreeThisClassMemory(p, alloc);
|
|
||||||
LzInWindow_Free(p, alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
|
|
||||||
if (sizeInBytes / sizeof(CLzRef) != num)
|
|
||||||
return 0;
|
|
||||||
return (CLzRef *)alloc->Alloc(sizeInBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
|
||||||
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
|
|
||||||
ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
UInt32 sizeReserv;
|
|
||||||
if (historySize > kMaxHistorySize)
|
|
||||||
{
|
|
||||||
MatchFinder_Free(p, alloc);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sizeReserv = historySize >> 1;
|
|
||||||
if (historySize > ((UInt32)2 << 30))
|
|
||||||
sizeReserv = historySize >> 2;
|
|
||||||
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
|
|
||||||
|
|
||||||
p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
|
|
||||||
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
|
|
||||||
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
|
|
||||||
if (LzInWindow_Create(p, sizeReserv, alloc))
|
|
||||||
{
|
|
||||||
UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
|
|
||||||
UInt32 hs;
|
|
||||||
p->matchMaxLen = matchMaxLen;
|
|
||||||
{
|
|
||||||
p->fixedHashSize = 0;
|
|
||||||
if (p->numHashBytes == 2)
|
|
||||||
hs = (1 << 16) - 1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hs = historySize - 1;
|
|
||||||
hs |= (hs >> 1);
|
|
||||||
hs |= (hs >> 2);
|
|
||||||
hs |= (hs >> 4);
|
|
||||||
hs |= (hs >> 8);
|
|
||||||
hs >>= 1;
|
|
||||||
/* hs >>= p->skipModeBits; */
|
|
||||||
hs |= 0xFFFF; /* don't change it! It's required for Deflate */
|
|
||||||
if (hs > (1 << 24))
|
|
||||||
{
|
|
||||||
if (p->numHashBytes == 3)
|
|
||||||
hs = (1 << 24) - 1;
|
|
||||||
else
|
|
||||||
hs >>= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p->hashMask = hs;
|
|
||||||
hs++;
|
|
||||||
if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
|
|
||||||
if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
|
|
||||||
if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
|
|
||||||
hs += p->fixedHashSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 prevSize = p->hashSizeSum + p->numSons;
|
|
||||||
UInt32 newSize;
|
|
||||||
p->historySize = historySize;
|
|
||||||
p->hashSizeSum = hs;
|
|
||||||
p->cyclicBufferSize = newCyclicBufferSize;
|
|
||||||
p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
|
|
||||||
newSize = p->hashSizeSum + p->numSons;
|
|
||||||
if (p->hash != 0 && prevSize == newSize)
|
|
||||||
return 1;
|
|
||||||
MatchFinder_FreeThisClassMemory(p, alloc);
|
|
||||||
p->hash = AllocRefs(newSize, alloc);
|
|
||||||
if (p->hash != 0)
|
|
||||||
{
|
|
||||||
p->son = p->hash + p->hashSizeSum;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MatchFinder_Free(p, alloc);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_SetLimits(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
UInt32 limit = kMaxValForNormalize - p->pos;
|
|
||||||
UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
|
|
||||||
if (limit2 < limit)
|
|
||||||
limit = limit2;
|
|
||||||
limit2 = p->streamPos - p->pos;
|
|
||||||
if (limit2 <= p->keepSizeAfter)
|
|
||||||
{
|
|
||||||
if (limit2 > 0)
|
|
||||||
limit2 = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
limit2 -= p->keepSizeAfter;
|
|
||||||
if (limit2 < limit)
|
|
||||||
limit = limit2;
|
|
||||||
{
|
|
||||||
UInt32 lenLimit = p->streamPos - p->pos;
|
|
||||||
if (lenLimit > p->matchMaxLen)
|
|
||||||
lenLimit = p->matchMaxLen;
|
|
||||||
p->lenLimit = lenLimit;
|
|
||||||
}
|
|
||||||
p->posLimit = p->pos + limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_Init(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for(i = 0; i < p->hashSizeSum; i++)
|
|
||||||
p->hash[i] = kEmptyHashValue;
|
|
||||||
p->cyclicBufferPos = 0;
|
|
||||||
p->buffer = p->bufferBase;
|
|
||||||
p->pos = p->streamPos = p->cyclicBufferSize;
|
|
||||||
p->result = SZ_OK;
|
|
||||||
p->streamEndWasReached = 0;
|
|
||||||
MatchFinder_ReadBlock(p);
|
|
||||||
MatchFinder_SetLimits(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
return (p->pos - p->historySize - 1) & kNormalizeMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < numItems; i++)
|
|
||||||
{
|
|
||||||
UInt32 value = items[i];
|
|
||||||
if (value <= subValue)
|
|
||||||
value = kEmptyHashValue;
|
|
||||||
else
|
|
||||||
value -= subValue;
|
|
||||||
items[i] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_Normalize(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
UInt32 subValue = MatchFinder_GetSubValue(p);
|
|
||||||
MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
|
|
||||||
MatchFinder_ReduceOffsets(p, subValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_CheckLimits(CMatchFinder *p)
|
|
||||||
{
|
|
||||||
if (p->pos == kMaxValForNormalize)
|
|
||||||
MatchFinder_Normalize(p);
|
|
||||||
if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
|
|
||||||
MatchFinder_CheckAndMoveAndRead(p);
|
|
||||||
if (p->cyclicBufferPos == p->cyclicBufferSize)
|
|
||||||
p->cyclicBufferPos = 0;
|
|
||||||
MatchFinder_SetLimits(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
|
||||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
|
|
||||||
UInt32 *distances, UInt32 maxLen)
|
|
||||||
{
|
|
||||||
son[_cyclicBufferPos] = curMatch;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
UInt32 delta = pos - curMatch;
|
|
||||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
|
||||||
return distances;
|
|
||||||
{
|
|
||||||
const Byte *pb = cur - delta;
|
|
||||||
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
|
|
||||||
if (pb[maxLen] == cur[maxLen] && *pb == *cur)
|
|
||||||
{
|
|
||||||
UInt32 len = 0;
|
|
||||||
while(++len != lenLimit)
|
|
||||||
if (pb[len] != cur[len])
|
|
||||||
break;
|
|
||||||
if (maxLen < len)
|
|
||||||
{
|
|
||||||
*distances++ = maxLen = len;
|
|
||||||
*distances++ = delta - 1;
|
|
||||||
if (len == lenLimit)
|
|
||||||
return distances;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
|
||||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
|
|
||||||
UInt32 *distances, UInt32 maxLen)
|
|
||||||
{
|
|
||||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
|
||||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
|
||||||
UInt32 len0 = 0, len1 = 0;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
UInt32 delta = pos - curMatch;
|
|
||||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
|
||||||
{
|
|
||||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
|
||||||
return distances;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
|
||||||
const Byte *pb = cur - delta;
|
|
||||||
UInt32 len = (len0 < len1 ? len0 : len1);
|
|
||||||
if (pb[len] == cur[len])
|
|
||||||
{
|
|
||||||
if (++len != lenLimit && pb[len] == cur[len])
|
|
||||||
while(++len != lenLimit)
|
|
||||||
if (pb[len] != cur[len])
|
|
||||||
break;
|
|
||||||
if (maxLen < len)
|
|
||||||
{
|
|
||||||
*distances++ = maxLen = len;
|
|
||||||
*distances++ = delta - 1;
|
|
||||||
if (len == lenLimit)
|
|
||||||
{
|
|
||||||
*ptr1 = pair[0];
|
|
||||||
*ptr0 = pair[1];
|
|
||||||
return distances;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pb[len] < cur[len])
|
|
||||||
{
|
|
||||||
*ptr1 = curMatch;
|
|
||||||
ptr1 = pair + 1;
|
|
||||||
curMatch = *ptr1;
|
|
||||||
len1 = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*ptr0 = curMatch;
|
|
||||||
ptr0 = pair;
|
|
||||||
curMatch = *ptr0;
|
|
||||||
len0 = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
|
|
||||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
|
|
||||||
{
|
|
||||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
|
||||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
|
||||||
UInt32 len0 = 0, len1 = 0;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
UInt32 delta = pos - curMatch;
|
|
||||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
|
||||||
{
|
|
||||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
|
||||||
const Byte *pb = cur - delta;
|
|
||||||
UInt32 len = (len0 < len1 ? len0 : len1);
|
|
||||||
if (pb[len] == cur[len])
|
|
||||||
{
|
|
||||||
while(++len != lenLimit)
|
|
||||||
if (pb[len] != cur[len])
|
|
||||||
break;
|
|
||||||
{
|
|
||||||
if (len == lenLimit)
|
|
||||||
{
|
|
||||||
*ptr1 = pair[0];
|
|
||||||
*ptr0 = pair[1];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pb[len] < cur[len])
|
|
||||||
{
|
|
||||||
*ptr1 = curMatch;
|
|
||||||
ptr1 = pair + 1;
|
|
||||||
curMatch = *ptr1;
|
|
||||||
len1 = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*ptr0 = curMatch;
|
|
||||||
ptr0 = pair;
|
|
||||||
curMatch = *ptr0;
|
|
||||||
len0 = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MOVE_POS \
|
|
||||||
++p->cyclicBufferPos; \
|
|
||||||
p->buffer++; \
|
|
||||||
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
|
|
||||||
|
|
||||||
#define MOVE_POS_RET MOVE_POS return offset;
|
|
||||||
|
|
||||||
void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
|
|
||||||
|
|
||||||
#define GET_MATCHES_HEADER2(minLen, ret_op) \
|
|
||||||
UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
|
|
||||||
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
|
|
||||||
cur = p->buffer;
|
|
||||||
|
|
||||||
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
|
|
||||||
#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
|
|
||||||
|
|
||||||
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
|
|
||||||
|
|
||||||
#define GET_MATCHES_FOOTER(offset, maxLen) \
|
|
||||||
offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
|
|
||||||
distances + offset, maxLen) - distances); MOVE_POS_RET;
|
|
||||||
|
|
||||||
#define SKIP_FOOTER \
|
|
||||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
|
|
||||||
|
|
||||||
UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 offset;
|
|
||||||
GET_MATCHES_HEADER(2)
|
|
||||||
HASH2_CALC;
|
|
||||||
curMatch = p->hash[hashValue];
|
|
||||||
p->hash[hashValue] = p->pos;
|
|
||||||
offset = 0;
|
|
||||||
GET_MATCHES_FOOTER(offset, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 offset;
|
|
||||||
GET_MATCHES_HEADER(3)
|
|
||||||
HASH_ZIP_CALC;
|
|
||||||
curMatch = p->hash[hashValue];
|
|
||||||
p->hash[hashValue] = p->pos;
|
|
||||||
offset = 0;
|
|
||||||
GET_MATCHES_FOOTER(offset, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 hash2Value, delta2, maxLen, offset;
|
|
||||||
GET_MATCHES_HEADER(3)
|
|
||||||
|
|
||||||
HASH3_CALC;
|
|
||||||
|
|
||||||
delta2 = p->pos - p->hash[hash2Value];
|
|
||||||
curMatch = p->hash[kFix3HashSize + hashValue];
|
|
||||||
|
|
||||||
p->hash[hash2Value] =
|
|
||||||
p->hash[kFix3HashSize + hashValue] = p->pos;
|
|
||||||
|
|
||||||
|
|
||||||
maxLen = 2;
|
|
||||||
offset = 0;
|
|
||||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
|
||||||
{
|
|
||||||
for (; maxLen != lenLimit; maxLen++)
|
|
||||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
|
||||||
break;
|
|
||||||
distances[0] = maxLen;
|
|
||||||
distances[1] = delta2 - 1;
|
|
||||||
offset = 2;
|
|
||||||
if (maxLen == lenLimit)
|
|
||||||
{
|
|
||||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
|
||||||
MOVE_POS_RET;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GET_MATCHES_FOOTER(offset, maxLen)
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
|
||||||
GET_MATCHES_HEADER(4)
|
|
||||||
|
|
||||||
HASH4_CALC;
|
|
||||||
|
|
||||||
delta2 = p->pos - p->hash[ hash2Value];
|
|
||||||
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
|
||||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
|
||||||
|
|
||||||
p->hash[ hash2Value] =
|
|
||||||
p->hash[kFix3HashSize + hash3Value] =
|
|
||||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
|
||||||
|
|
||||||
maxLen = 1;
|
|
||||||
offset = 0;
|
|
||||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
|
||||||
{
|
|
||||||
distances[0] = maxLen = 2;
|
|
||||||
distances[1] = delta2 - 1;
|
|
||||||
offset = 2;
|
|
||||||
}
|
|
||||||
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
|
||||||
{
|
|
||||||
maxLen = 3;
|
|
||||||
distances[offset + 1] = delta3 - 1;
|
|
||||||
offset += 2;
|
|
||||||
delta2 = delta3;
|
|
||||||
}
|
|
||||||
if (offset != 0)
|
|
||||||
{
|
|
||||||
for (; maxLen != lenLimit; maxLen++)
|
|
||||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
|
||||||
break;
|
|
||||||
distances[offset - 2] = maxLen;
|
|
||||||
if (maxLen == lenLimit)
|
|
||||||
{
|
|
||||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
|
||||||
MOVE_POS_RET;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (maxLen < 3)
|
|
||||||
maxLen = 3;
|
|
||||||
GET_MATCHES_FOOTER(offset, maxLen)
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
|
||||||
GET_MATCHES_HEADER(4)
|
|
||||||
|
|
||||||
HASH4_CALC;
|
|
||||||
|
|
||||||
delta2 = p->pos - p->hash[ hash2Value];
|
|
||||||
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
|
||||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
|
||||||
|
|
||||||
p->hash[ hash2Value] =
|
|
||||||
p->hash[kFix3HashSize + hash3Value] =
|
|
||||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
|
||||||
|
|
||||||
maxLen = 1;
|
|
||||||
offset = 0;
|
|
||||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
|
||||||
{
|
|
||||||
distances[0] = maxLen = 2;
|
|
||||||
distances[1] = delta2 - 1;
|
|
||||||
offset = 2;
|
|
||||||
}
|
|
||||||
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
|
||||||
{
|
|
||||||
maxLen = 3;
|
|
||||||
distances[offset + 1] = delta3 - 1;
|
|
||||||
offset += 2;
|
|
||||||
delta2 = delta3;
|
|
||||||
}
|
|
||||||
if (offset != 0)
|
|
||||||
{
|
|
||||||
for (; maxLen != lenLimit; maxLen++)
|
|
||||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
|
||||||
break;
|
|
||||||
distances[offset - 2] = maxLen;
|
|
||||||
if (maxLen == lenLimit)
|
|
||||||
{
|
|
||||||
p->son[p->cyclicBufferPos] = curMatch;
|
|
||||||
MOVE_POS_RET;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (maxLen < 3)
|
|
||||||
maxLen = 3;
|
|
||||||
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
|
||||||
distances + offset, maxLen) - (distances));
|
|
||||||
MOVE_POS_RET
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 offset;
|
|
||||||
GET_MATCHES_HEADER(3)
|
|
||||||
HASH_ZIP_CALC;
|
|
||||||
curMatch = p->hash[hashValue];
|
|
||||||
p->hash[hashValue] = p->pos;
|
|
||||||
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
|
||||||
distances, 2) - (distances));
|
|
||||||
MOVE_POS_RET
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
SKIP_HEADER(2)
|
|
||||||
HASH2_CALC;
|
|
||||||
curMatch = p->hash[hashValue];
|
|
||||||
p->hash[hashValue] = p->pos;
|
|
||||||
SKIP_FOOTER
|
|
||||||
}
|
|
||||||
while (--num != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
SKIP_HEADER(3)
|
|
||||||
HASH_ZIP_CALC;
|
|
||||||
curMatch = p->hash[hashValue];
|
|
||||||
p->hash[hashValue] = p->pos;
|
|
||||||
SKIP_FOOTER
|
|
||||||
}
|
|
||||||
while (--num != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UInt32 hash2Value;
|
|
||||||
SKIP_HEADER(3)
|
|
||||||
HASH3_CALC;
|
|
||||||
curMatch = p->hash[kFix3HashSize + hashValue];
|
|
||||||
p->hash[hash2Value] =
|
|
||||||
p->hash[kFix3HashSize + hashValue] = p->pos;
|
|
||||||
SKIP_FOOTER
|
|
||||||
}
|
|
||||||
while (--num != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UInt32 hash2Value, hash3Value;
|
|
||||||
SKIP_HEADER(4)
|
|
||||||
HASH4_CALC;
|
|
||||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
|
||||||
p->hash[ hash2Value] =
|
|
||||||
p->hash[kFix3HashSize + hash3Value] = p->pos;
|
|
||||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
|
||||||
SKIP_FOOTER
|
|
||||||
}
|
|
||||||
while (--num != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UInt32 hash2Value, hash3Value;
|
|
||||||
SKIP_HEADER(4)
|
|
||||||
HASH4_CALC;
|
|
||||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
|
||||||
p->hash[ hash2Value] =
|
|
||||||
p->hash[kFix3HashSize + hash3Value] =
|
|
||||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
|
||||||
p->son[p->cyclicBufferPos] = curMatch;
|
|
||||||
MOVE_POS
|
|
||||||
}
|
|
||||||
while (--num != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
SKIP_HEADER(3)
|
|
||||||
HASH_ZIP_CALC;
|
|
||||||
curMatch = p->hash[hashValue];
|
|
||||||
p->hash[hashValue] = p->pos;
|
|
||||||
p->son[p->cyclicBufferPos] = curMatch;
|
|
||||||
MOVE_POS
|
|
||||||
}
|
|
||||||
while (--num != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
|
|
||||||
{
|
|
||||||
vTable->Init = (Mf_Init_Func)MatchFinder_Init;
|
|
||||||
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
|
|
||||||
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
|
|
||||||
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
|
|
||||||
if (!p->btMode)
|
|
||||||
{
|
|
||||||
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
|
|
||||||
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
|
|
||||||
}
|
|
||||||
else if (p->numHashBytes == 2)
|
|
||||||
{
|
|
||||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
|
|
||||||
vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
|
|
||||||
}
|
|
||||||
else if (p->numHashBytes == 3)
|
|
||||||
{
|
|
||||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
|
|
||||||
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
|
|
||||||
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
/* MatchFinder.h */
|
|
||||||
|
|
||||||
#ifndef __MATCHFINDER_H
|
|
||||||
#define __MATCHFINDER_H
|
|
||||||
|
|
||||||
#include "../../IStream.h"
|
|
||||||
|
|
||||||
typedef UInt32 CLzRef;
|
|
||||||
|
|
||||||
typedef struct _CMatchFinder
|
|
||||||
{
|
|
||||||
Byte *buffer;
|
|
||||||
UInt32 pos;
|
|
||||||
UInt32 posLimit;
|
|
||||||
UInt32 streamPos;
|
|
||||||
UInt32 lenLimit;
|
|
||||||
|
|
||||||
UInt32 cyclicBufferPos;
|
|
||||||
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
|
|
||||||
|
|
||||||
UInt32 matchMaxLen;
|
|
||||||
CLzRef *hash;
|
|
||||||
CLzRef *son;
|
|
||||||
UInt32 hashMask;
|
|
||||||
UInt32 cutValue;
|
|
||||||
|
|
||||||
Byte *bufferBase;
|
|
||||||
ISeqInStream *stream;
|
|
||||||
int streamEndWasReached;
|
|
||||||
|
|
||||||
UInt32 blockSize;
|
|
||||||
UInt32 keepSizeBefore;
|
|
||||||
UInt32 keepSizeAfter;
|
|
||||||
|
|
||||||
UInt32 numHashBytes;
|
|
||||||
int directInput;
|
|
||||||
int btMode;
|
|
||||||
/* int skipModeBits; */
|
|
||||||
int bigHash;
|
|
||||||
UInt32 historySize;
|
|
||||||
UInt32 fixedHashSize;
|
|
||||||
UInt32 hashSizeSum;
|
|
||||||
UInt32 numSons;
|
|
||||||
|
|
||||||
HRes result;
|
|
||||||
} CMatchFinder;
|
|
||||||
|
|
||||||
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
|
||||||
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
|
|
||||||
|
|
||||||
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
|
|
||||||
|
|
||||||
int MatchFinder_NeedMove(CMatchFinder *p);
|
|
||||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
|
||||||
void MatchFinder_MoveBlock(CMatchFinder *p);
|
|
||||||
void MatchFinder_ReadIfRequired(CMatchFinder *p);
|
|
||||||
|
|
||||||
void MatchFinder_Construct(CMatchFinder *p);
|
|
||||||
|
|
||||||
/* Conditions:
|
|
||||||
historySize <= 3 GB
|
|
||||||
keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
|
|
||||||
*/
|
|
||||||
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
|
||||||
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
|
|
||||||
ISzAlloc *alloc);
|
|
||||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
|
|
||||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
|
|
||||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
|
|
||||||
|
|
||||||
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
|
||||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
|
||||||
UInt32 *distances, UInt32 maxLen);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Conditions:
|
|
||||||
Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
|
|
||||||
Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef void (*Mf_Init_Func)(void *object);
|
|
||||||
typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
|
|
||||||
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
|
|
||||||
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
|
|
||||||
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
|
|
||||||
typedef void (*Mf_Skip_Func)(void *object, UInt32);
|
|
||||||
|
|
||||||
typedef struct _IMatchFinder
|
|
||||||
{
|
|
||||||
Mf_Init_Func Init;
|
|
||||||
Mf_GetIndexByte_Func GetIndexByte;
|
|
||||||
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
|
|
||||||
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
|
|
||||||
Mf_GetMatches_Func GetMatches;
|
|
||||||
Mf_Skip_Func Skip;
|
|
||||||
} IMatchFinder;
|
|
||||||
|
|
||||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
|
||||||
|
|
||||||
void MatchFinder_Init(CMatchFinder *p);
|
|
||||||
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
|
||||||
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
|
||||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
|
||||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,806 +0,0 @@
|
|||||||
/* MatchFinderMt.c */
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define USE_ALLOCA
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_ALLOCA
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <malloc.h>
|
|
||||||
#else
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../../7zCrc.h"
|
|
||||||
#include "LzHash.h"
|
|
||||||
|
|
||||||
#include "MatchFinderMt.h"
|
|
||||||
|
|
||||||
void MtSync_Construct(CMtSync *p)
|
|
||||||
{
|
|
||||||
p->wasCreated = False;
|
|
||||||
p->csWasInitialized = False;
|
|
||||||
p->csWasEntered = False;
|
|
||||||
Thread_Construct(&p->thread);
|
|
||||||
Event_Construct(&p->canStart);
|
|
||||||
Event_Construct(&p->wasStarted);
|
|
||||||
Event_Construct(&p->wasStopped);
|
|
||||||
Semaphore_Construct(&p->freeSemaphore);
|
|
||||||
Semaphore_Construct(&p->filledSemaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MtSync_GetNextBlock(CMtSync *p)
|
|
||||||
{
|
|
||||||
if (p->needStart)
|
|
||||||
{
|
|
||||||
p->numProcessedBlocks = 1;
|
|
||||||
p->needStart = False;
|
|
||||||
p->stopWriting = False;
|
|
||||||
p->exit = False;
|
|
||||||
Event_Reset(&p->wasStarted);
|
|
||||||
Event_Reset(&p->wasStopped);
|
|
||||||
|
|
||||||
Event_Set(&p->canStart);
|
|
||||||
Event_Wait(&p->wasStarted);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CriticalSection_Leave(&p->cs);
|
|
||||||
p->csWasEntered = False;
|
|
||||||
p->numProcessedBlocks++;
|
|
||||||
Semaphore_Release1(&p->freeSemaphore);
|
|
||||||
}
|
|
||||||
Semaphore_Wait(&p->filledSemaphore);
|
|
||||||
CriticalSection_Enter(&p->cs);
|
|
||||||
p->csWasEntered = True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MtSync_StopWriting must be called if Writing was started */
|
|
||||||
|
|
||||||
void MtSync_StopWriting(CMtSync *p)
|
|
||||||
{
|
|
||||||
UInt32 myNumBlocks = p->numProcessedBlocks;
|
|
||||||
if (!Thread_WasCreated(&p->thread) || p->needStart)
|
|
||||||
return;
|
|
||||||
p->stopWriting = True;
|
|
||||||
if (p->csWasEntered)
|
|
||||||
{
|
|
||||||
CriticalSection_Leave(&p->cs);
|
|
||||||
p->csWasEntered = False;
|
|
||||||
}
|
|
||||||
Semaphore_Release1(&p->freeSemaphore);
|
|
||||||
|
|
||||||
Event_Wait(&p->wasStopped);
|
|
||||||
|
|
||||||
while (myNumBlocks++ != p->numProcessedBlocks)
|
|
||||||
{
|
|
||||||
Semaphore_Wait(&p->filledSemaphore);
|
|
||||||
Semaphore_Release1(&p->freeSemaphore);
|
|
||||||
}
|
|
||||||
p->needStart = True;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MtSync_Destruct(CMtSync *p)
|
|
||||||
{
|
|
||||||
if (Thread_WasCreated(&p->thread))
|
|
||||||
{
|
|
||||||
MtSync_StopWriting(p);
|
|
||||||
p->exit = True;
|
|
||||||
if (p->needStart)
|
|
||||||
Event_Set(&p->canStart);
|
|
||||||
Thread_Wait(&p->thread);
|
|
||||||
Thread_Close(&p->thread);
|
|
||||||
}
|
|
||||||
if (p->csWasInitialized)
|
|
||||||
{
|
|
||||||
CriticalSection_Delete(&p->cs);
|
|
||||||
p->csWasInitialized = False;
|
|
||||||
}
|
|
||||||
|
|
||||||
Event_Close(&p->canStart);
|
|
||||||
Event_Close(&p->wasStarted);
|
|
||||||
Event_Close(&p->wasStopped);
|
|
||||||
Semaphore_Close(&p->freeSemaphore);
|
|
||||||
Semaphore_Close(&p->filledSemaphore);
|
|
||||||
|
|
||||||
p->wasCreated = False;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRes MtSync_Create2(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
|
|
||||||
{
|
|
||||||
if (p->wasCreated)
|
|
||||||
return SZ_OK;
|
|
||||||
|
|
||||||
RINOK(CriticalSection_Init(&p->cs));
|
|
||||||
p->csWasInitialized = True;
|
|
||||||
|
|
||||||
RINOK(AutoResetEvent_CreateNotSignaled(&p->canStart));
|
|
||||||
RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStarted));
|
|
||||||
RINOK(AutoResetEvent_CreateNotSignaled(&p->wasStopped));
|
|
||||||
|
|
||||||
RINOK(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks));
|
|
||||||
RINOK(Semaphore_Create(&p->filledSemaphore, 0, numBlocks));
|
|
||||||
|
|
||||||
p->needStart = True;
|
|
||||||
|
|
||||||
RINOK(Thread_Create(&p->thread, startAddress, obj));
|
|
||||||
p->wasCreated = True;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRes MtSync_Create(CMtSync *p, unsigned (StdCall *startAddress)(void *), void *obj, UInt32 numBlocks)
|
|
||||||
{
|
|
||||||
HRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
|
|
||||||
if (res != SZ_OK)
|
|
||||||
MtSync_Destruct(p);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MtSync_Init(CMtSync *p) { p->needStart = True; }
|
|
||||||
|
|
||||||
#define kMtMaxValForNormalize 0xFFFFFFFF
|
|
||||||
|
|
||||||
#define DEF_GetHeads(name, v) \
|
|
||||||
static void GetHeads ## name(const Byte *p, UInt32 pos, \
|
|
||||||
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads) { \
|
|
||||||
for (; numHeads != 0; numHeads--) { \
|
|
||||||
const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } }
|
|
||||||
|
|
||||||
DEF_GetHeads(2, (p[0] | ((UInt32)p[1] << 8)) & hashMask)
|
|
||||||
DEF_GetHeads(3, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
|
|
||||||
DEF_GetHeads(4, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5)) & hashMask)
|
|
||||||
DEF_GetHeads(4b, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
|
|
||||||
DEF_GetHeads(5, (g_CrcTable[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (g_CrcTable[p[3]] << 5) ^ (g_CrcTable[p[4]] << 3)) & hashMask)
|
|
||||||
|
|
||||||
void HashThreadFunc(CMatchFinderMt *mt)
|
|
||||||
{
|
|
||||||
CMtSync *p = &mt->hashSync;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
UInt32 numProcessedBlocks = 0;
|
|
||||||
Event_Wait(&p->canStart);
|
|
||||||
Event_Set(&p->wasStarted);
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (p->exit)
|
|
||||||
return;
|
|
||||||
if (p->stopWriting)
|
|
||||||
{
|
|
||||||
p->numProcessedBlocks = numProcessedBlocks;
|
|
||||||
Event_Set(&p->wasStopped);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
CMatchFinder *mf = mt->MatchFinder;
|
|
||||||
if (MatchFinder_NeedMove(mf))
|
|
||||||
{
|
|
||||||
CriticalSection_Enter(&mt->btSync.cs);
|
|
||||||
CriticalSection_Enter(&mt->hashSync.cs);
|
|
||||||
{
|
|
||||||
const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf);
|
|
||||||
const Byte *afterPtr;
|
|
||||||
MatchFinder_MoveBlock(mf);
|
|
||||||
afterPtr = MatchFinder_GetPointerToCurrentPos(mf);
|
|
||||||
mt->pointerToCurPos -= beforePtr - afterPtr;
|
|
||||||
mt->buffer -= beforePtr - afterPtr;
|
|
||||||
}
|
|
||||||
CriticalSection_Leave(&mt->btSync.cs);
|
|
||||||
CriticalSection_Leave(&mt->hashSync.cs);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Semaphore_Wait(&p->freeSemaphore);
|
|
||||||
|
|
||||||
MatchFinder_ReadIfRequired(mf);
|
|
||||||
if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize))
|
|
||||||
{
|
|
||||||
UInt32 subValue = (mf->pos - mf->historySize - 1);
|
|
||||||
MatchFinder_ReduceOffsets(mf, subValue);
|
|
||||||
MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize;
|
|
||||||
UInt32 num = mf->streamPos - mf->pos;
|
|
||||||
heads[0] = 2;
|
|
||||||
heads[1] = num;
|
|
||||||
if (num >= mf->numHashBytes)
|
|
||||||
{
|
|
||||||
num = num - mf->numHashBytes + 1;
|
|
||||||
if (num > kMtHashBlockSize - 2)
|
|
||||||
num = kMtHashBlockSize - 2;
|
|
||||||
mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num);
|
|
||||||
heads[0] += num;
|
|
||||||
}
|
|
||||||
mf->pos += num;
|
|
||||||
mf->buffer += num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Semaphore_Release1(&p->filledSemaphore);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
|
|
||||||
{
|
|
||||||
MtSync_GetNextBlock(&p->hashSync);
|
|
||||||
p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize;
|
|
||||||
p->hashBufPosLimit += p->hashBuf[p->hashBufPos++];
|
|
||||||
p->hashNumAvail = p->hashBuf[p->hashBufPos++];
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kEmptyHashValue 0
|
|
||||||
|
|
||||||
/* #define MFMT_GM_INLINE */
|
|
||||||
|
|
||||||
#ifdef MFMT_GM_INLINE
|
|
||||||
|
|
||||||
#if _MSC_VER >= 1300
|
|
||||||
#define NO_INLINE __declspec(noinline) __fastcall
|
|
||||||
#else
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define NO_INLINE __fastcall
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
|
|
||||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
|
||||||
UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UInt32 *distances = _distances + 1;
|
|
||||||
UInt32 curMatch = pos - *hash++;
|
|
||||||
|
|
||||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
|
||||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
|
||||||
UInt32 len0 = 0, len1 = 0;
|
|
||||||
UInt32 cutValue = _cutValue;
|
|
||||||
UInt32 maxLen = _maxLen;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
UInt32 delta = pos - curMatch;
|
|
||||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
|
||||||
{
|
|
||||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
|
||||||
const Byte *pb = cur - delta;
|
|
||||||
UInt32 len = (len0 < len1 ? len0 : len1);
|
|
||||||
if (pb[len] == cur[len])
|
|
||||||
{
|
|
||||||
if (++len != lenLimit && pb[len] == cur[len])
|
|
||||||
while(++len != lenLimit)
|
|
||||||
if (pb[len] != cur[len])
|
|
||||||
break;
|
|
||||||
if (maxLen < len)
|
|
||||||
{
|
|
||||||
*distances++ = maxLen = len;
|
|
||||||
*distances++ = delta - 1;
|
|
||||||
if (len == lenLimit)
|
|
||||||
{
|
|
||||||
*ptr1 = pair[0];
|
|
||||||
*ptr0 = pair[1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pb[len] < cur[len])
|
|
||||||
{
|
|
||||||
*ptr1 = curMatch;
|
|
||||||
ptr1 = pair + 1;
|
|
||||||
curMatch = *ptr1;
|
|
||||||
len1 = len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*ptr0 = curMatch;
|
|
||||||
ptr0 = pair;
|
|
||||||
curMatch = *ptr0;
|
|
||||||
len0 = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
_cyclicBufferPos++;
|
|
||||||
cur++;
|
|
||||||
{
|
|
||||||
UInt32 num = (UInt32)(distances - _distances);
|
|
||||||
*_distances = num - 1;
|
|
||||||
_distances += num;
|
|
||||||
limit -= num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (limit > 0 && --size != 0);
|
|
||||||
*posRes = pos;
|
|
||||||
return limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 numProcessed = 0;
|
|
||||||
UInt32 curPos = 2;
|
|
||||||
UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
|
|
||||||
distances[1] = p->hashNumAvail;
|
|
||||||
while (curPos < limit)
|
|
||||||
{
|
|
||||||
if (p->hashBufPos == p->hashBufPosLimit)
|
|
||||||
{
|
|
||||||
MatchFinderMt_GetNextBlock_Hash(p);
|
|
||||||
distances[1] = numProcessed + p->hashNumAvail;
|
|
||||||
if (p->hashNumAvail >= p->numHashBytes)
|
|
||||||
continue;
|
|
||||||
for (; p->hashNumAvail != 0; p->hashNumAvail--)
|
|
||||||
distances[curPos++] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
UInt32 size = p->hashBufPosLimit - p->hashBufPos;
|
|
||||||
UInt32 lenLimit = p->matchMaxLen;
|
|
||||||
UInt32 pos = p->pos;
|
|
||||||
UInt32 cyclicBufferPos = p->cyclicBufferPos;
|
|
||||||
if (lenLimit >= p->hashNumAvail)
|
|
||||||
lenLimit = p->hashNumAvail;
|
|
||||||
{
|
|
||||||
UInt32 size2 = p->hashNumAvail - lenLimit + 1;
|
|
||||||
if (size2 < size)
|
|
||||||
size = size2;
|
|
||||||
size2 = p->cyclicBufferSize - cyclicBufferPos;
|
|
||||||
if (size2 < size)
|
|
||||||
size = size2;
|
|
||||||
}
|
|
||||||
#ifndef MFMT_GM_INLINE
|
|
||||||
while (curPos < limit && size-- != 0)
|
|
||||||
{
|
|
||||||
UInt32 *startDistances = distances + curPos;
|
|
||||||
UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],
|
|
||||||
pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
|
||||||
startDistances + 1, p->numHashBytes - 1) - startDistances);
|
|
||||||
*startDistances = num - 1;
|
|
||||||
curPos += num;
|
|
||||||
cyclicBufferPos++;
|
|
||||||
pos++;
|
|
||||||
p->buffer++;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
UInt32 posRes;
|
|
||||||
curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
|
|
||||||
distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes);
|
|
||||||
p->hashBufPos += posRes - pos;
|
|
||||||
cyclicBufferPos += posRes - pos;
|
|
||||||
p->buffer += posRes - pos;
|
|
||||||
pos = posRes;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
numProcessed += pos - p->pos;
|
|
||||||
p->hashNumAvail -= pos - p->pos;
|
|
||||||
p->pos = pos;
|
|
||||||
if (cyclicBufferPos == p->cyclicBufferSize)
|
|
||||||
cyclicBufferPos = 0;
|
|
||||||
p->cyclicBufferPos = cyclicBufferPos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
distances[0] = curPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)
|
|
||||||
{
|
|
||||||
CMtSync *sync = &p->hashSync;
|
|
||||||
if (!sync->needStart)
|
|
||||||
{
|
|
||||||
CriticalSection_Enter(&sync->cs);
|
|
||||||
sync->csWasEntered = True;
|
|
||||||
}
|
|
||||||
|
|
||||||
BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize);
|
|
||||||
|
|
||||||
if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize)
|
|
||||||
{
|
|
||||||
UInt32 subValue = p->pos - p->cyclicBufferSize;
|
|
||||||
MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2);
|
|
||||||
p->pos -= subValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sync->needStart)
|
|
||||||
{
|
|
||||||
CriticalSection_Leave(&sync->cs);
|
|
||||||
sync->csWasEntered = False;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BtThreadFunc(CMatchFinderMt *mt)
|
|
||||||
{
|
|
||||||
CMtSync *p = &mt->btSync;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
UInt32 blockIndex = 0;
|
|
||||||
Event_Wait(&p->canStart);
|
|
||||||
Event_Set(&p->wasStarted);
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (p->exit)
|
|
||||||
return;
|
|
||||||
if (p->stopWriting)
|
|
||||||
{
|
|
||||||
p->numProcessedBlocks = blockIndex;
|
|
||||||
MtSync_StopWriting(&mt->hashSync);
|
|
||||||
Event_Set(&p->wasStopped);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Semaphore_Wait(&p->freeSemaphore);
|
|
||||||
BtFillBlock(mt, blockIndex++);
|
|
||||||
Semaphore_Release1(&p->filledSemaphore);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinderMt_Construct(CMatchFinderMt *p)
|
|
||||||
{
|
|
||||||
p->hashBuf = 0;
|
|
||||||
MtSync_Construct(&p->hashSync);
|
|
||||||
MtSync_Construct(&p->btSync);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
alloc->Free(p->hashBuf);
|
|
||||||
p->hashBuf = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
MtSync_Destruct(&p->hashSync);
|
|
||||||
MtSync_Destruct(&p->btSync);
|
|
||||||
MatchFinderMt_FreeMem(p, alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
|
|
||||||
#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
|
|
||||||
|
|
||||||
static unsigned StdCall HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
|
|
||||||
static unsigned StdCall BtThreadFunc2(void *p)
|
|
||||||
{
|
|
||||||
#ifdef USE_ALLOCA
|
|
||||||
alloca(0x180);
|
|
||||||
#endif
|
|
||||||
BtThreadFunc((CMatchFinderMt *)p);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
|
|
||||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc)
|
|
||||||
{
|
|
||||||
CMatchFinder *mf = p->MatchFinder;
|
|
||||||
p->historySize = historySize;
|
|
||||||
if (kMtBtBlockSize <= matchMaxLen * 4)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
if (p->hashBuf == 0)
|
|
||||||
{
|
|
||||||
p->hashBuf = (UInt32 *)alloc->Alloc((kHashBufferSize + kBtBufferSize) * sizeof(UInt32));
|
|
||||||
if (p->hashBuf == 0)
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
p->btBuf = p->hashBuf + kHashBufferSize;
|
|
||||||
}
|
|
||||||
keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);
|
|
||||||
keepAddBufferAfter += kMtHashBlockSize;
|
|
||||||
if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))
|
|
||||||
return SZE_OUTOFMEMORY;
|
|
||||||
|
|
||||||
RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks));
|
|
||||||
RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks));
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call it after ReleaseStream / SetStream */
|
|
||||||
void MatchFinderMt_Init(CMatchFinderMt *p)
|
|
||||||
{
|
|
||||||
CMatchFinder *mf = p->MatchFinder;
|
|
||||||
p->btBufPos = p->btBufPosLimit = 0;
|
|
||||||
p->hashBufPos = p->hashBufPosLimit = 0;
|
|
||||||
MatchFinder_Init(mf);
|
|
||||||
p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf);
|
|
||||||
p->btNumAvailBytes = 0;
|
|
||||||
p->lzPos = p->historySize + 1;
|
|
||||||
|
|
||||||
p->hash = mf->hash;
|
|
||||||
p->fixedHashSize = mf->fixedHashSize;
|
|
||||||
|
|
||||||
p->son = mf->son;
|
|
||||||
p->matchMaxLen = mf->matchMaxLen;
|
|
||||||
p->numHashBytes = mf->numHashBytes;
|
|
||||||
p->pos = mf->pos;
|
|
||||||
p->buffer = mf->buffer;
|
|
||||||
p->cyclicBufferPos = mf->cyclicBufferPos;
|
|
||||||
p->cyclicBufferSize = mf->cyclicBufferSize;
|
|
||||||
p->cutValue = mf->cutValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ReleaseStream is required to finish multithreading */
|
|
||||||
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p)
|
|
||||||
{
|
|
||||||
MtSync_StopWriting(&p->btSync);
|
|
||||||
/* p->MatchFinder->ReleaseStream(); */
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinderMt_Normalize(CMatchFinderMt *p)
|
|
||||||
{
|
|
||||||
MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize);
|
|
||||||
p->lzPos = p->historySize + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
|
|
||||||
{
|
|
||||||
UInt32 blockIndex;
|
|
||||||
MtSync_GetNextBlock(&p->btSync);
|
|
||||||
blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask);
|
|
||||||
p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize;
|
|
||||||
p->btBufPosLimit += p->btBuf[p->btBufPos++];
|
|
||||||
p->btNumAvailBytes = p->btBuf[p->btBufPos++];
|
|
||||||
if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize)
|
|
||||||
MatchFinderMt_Normalize(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
|
|
||||||
{
|
|
||||||
return p->pointerToCurPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
|
|
||||||
|
|
||||||
UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p)
|
|
||||||
{
|
|
||||||
GET_NEXT_BLOCK_IF_REQUIRED;
|
|
||||||
return p->btNumAvailBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index)
|
|
||||||
{
|
|
||||||
return p->pointerToCurPos[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 hash2Value, curMatch2;
|
|
||||||
UInt32 *hash = p->hash;
|
|
||||||
const Byte *cur = p->pointerToCurPos;
|
|
||||||
UInt32 lzPos = p->lzPos;
|
|
||||||
MT_HASH2_CALC
|
|
||||||
|
|
||||||
curMatch2 = hash[hash2Value];
|
|
||||||
hash[hash2Value] = lzPos;
|
|
||||||
|
|
||||||
if (curMatch2 >= matchMinPos)
|
|
||||||
if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
|
||||||
{
|
|
||||||
*distances++ = 2;
|
|
||||||
*distances++ = lzPos - curMatch2 - 1;
|
|
||||||
}
|
|
||||||
return distances;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 hash2Value, hash3Value, curMatch2, curMatch3;
|
|
||||||
UInt32 *hash = p->hash;
|
|
||||||
const Byte *cur = p->pointerToCurPos;
|
|
||||||
UInt32 lzPos = p->lzPos;
|
|
||||||
MT_HASH3_CALC
|
|
||||||
|
|
||||||
curMatch2 = hash[ hash2Value];
|
|
||||||
curMatch3 = hash[kFix3HashSize + hash3Value];
|
|
||||||
|
|
||||||
hash[ hash2Value] =
|
|
||||||
hash[kFix3HashSize + hash3Value] =
|
|
||||||
lzPos;
|
|
||||||
|
|
||||||
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
|
||||||
{
|
|
||||||
distances[1] = lzPos - curMatch2 - 1;
|
|
||||||
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
|
|
||||||
{
|
|
||||||
distances[0] = 3;
|
|
||||||
return distances + 2;
|
|
||||||
}
|
|
||||||
distances[0] = 2;
|
|
||||||
distances += 2;
|
|
||||||
}
|
|
||||||
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
|
||||||
{
|
|
||||||
*distances++ = 3;
|
|
||||||
*distances++ = lzPos - curMatch3 - 1;
|
|
||||||
}
|
|
||||||
return distances;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances)
|
|
||||||
{
|
|
||||||
UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4;
|
|
||||||
UInt32 *hash = p->hash;
|
|
||||||
const Byte *cur = p->pointerToCurPos;
|
|
||||||
UInt32 lzPos = p->lzPos;
|
|
||||||
MT_HASH4_CALC
|
|
||||||
|
|
||||||
curMatch2 = hash[ hash2Value];
|
|
||||||
curMatch3 = hash[kFix3HashSize + hash3Value];
|
|
||||||
curMatch4 = hash[kFix4HashSize + hash4Value];
|
|
||||||
|
|
||||||
hash[ hash2Value] =
|
|
||||||
hash[kFix3HashSize + hash3Value] =
|
|
||||||
hash[kFix4HashSize + hash4Value] =
|
|
||||||
lzPos;
|
|
||||||
|
|
||||||
if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0])
|
|
||||||
{
|
|
||||||
distances[1] = lzPos - curMatch2 - 1;
|
|
||||||
if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2])
|
|
||||||
{
|
|
||||||
distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3;
|
|
||||||
return distances + 2;
|
|
||||||
}
|
|
||||||
distances[0] = 2;
|
|
||||||
distances += 2;
|
|
||||||
}
|
|
||||||
if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0])
|
|
||||||
{
|
|
||||||
distances[1] = lzPos - curMatch3 - 1;
|
|
||||||
if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3])
|
|
||||||
{
|
|
||||||
distances[0] = 4;
|
|
||||||
return distances + 2;
|
|
||||||
}
|
|
||||||
distances[0] = 3;
|
|
||||||
distances += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curMatch4 >= matchMinPos)
|
|
||||||
if (
|
|
||||||
cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] &&
|
|
||||||
cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3]
|
|
||||||
)
|
|
||||||
{
|
|
||||||
*distances++ = 4;
|
|
||||||
*distances++ = lzPos - curMatch4 - 1;
|
|
||||||
}
|
|
||||||
return distances;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;
|
|
||||||
|
|
||||||
UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|
||||||
{
|
|
||||||
const UInt32 *btBuf = p->btBuf + p->btBufPos;
|
|
||||||
UInt32 len = *btBuf++;
|
|
||||||
p->btBufPos += 1 + len;
|
|
||||||
p->btNumAvailBytes--;
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < len; i += 2)
|
|
||||||
{
|
|
||||||
*distances++ = *btBuf++;
|
|
||||||
*distances++ = *btBuf++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
INCREASE_LZ_POS
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances)
|
|
||||||
{
|
|
||||||
const UInt32 *btBuf = p->btBuf + p->btBufPos;
|
|
||||||
UInt32 len = *btBuf++;
|
|
||||||
p->btBufPos += 1 + len;
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
{
|
|
||||||
if (p->btNumAvailBytes-- >= 4)
|
|
||||||
len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Condition: there are matches in btBuf with length < p->numHashBytes */
|
|
||||||
UInt32 *distances2;
|
|
||||||
p->btNumAvailBytes--;
|
|
||||||
distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
*distances2++ = *btBuf++;
|
|
||||||
*distances2++ = *btBuf++;
|
|
||||||
}
|
|
||||||
while ((len -= 2) != 0);
|
|
||||||
len = (UInt32)(distances2 - (distances));
|
|
||||||
}
|
|
||||||
INCREASE_LZ_POS
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SKIP_HEADER2 do { GET_NEXT_BLOCK_IF_REQUIRED
|
|
||||||
#define SKIP_HEADER(n) SKIP_HEADER2 if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
|
|
||||||
#define SKIP_FOOTER } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while(--num != 0);
|
|
||||||
|
|
||||||
void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num)
|
|
||||||
{
|
|
||||||
SKIP_HEADER2 { p->btNumAvailBytes--;
|
|
||||||
SKIP_FOOTER
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
|
|
||||||
{
|
|
||||||
SKIP_HEADER(2)
|
|
||||||
UInt32 hash2Value;
|
|
||||||
MT_HASH2_CALC
|
|
||||||
hash[hash2Value] = p->lzPos;
|
|
||||||
SKIP_FOOTER
|
|
||||||
}
|
|
||||||
|
|
||||||
void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num)
|
|
||||||
{
|
|
||||||
SKIP_HEADER(3)
|
|
||||||
UInt32 hash2Value, hash3Value;
|
|
||||||
MT_HASH3_CALC
|
|
||||||
hash[kFix3HashSize + hash3Value] =
|
|
||||||
hash[ hash2Value] =
|
|
||||||
p->lzPos;
|
|
||||||
SKIP_FOOTER
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
|
|
||||||
{
|
|
||||||
SKIP_HEADER(4)
|
|
||||||
UInt32 hash2Value, hash3Value, hash4Value;
|
|
||||||
MT_HASH4_CALC
|
|
||||||
hash[kFix4HashSize + hash4Value] =
|
|
||||||
hash[kFix3HashSize + hash3Value] =
|
|
||||||
hash[ hash2Value] =
|
|
||||||
p->lzPos;
|
|
||||||
SKIP_FOOTER
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable)
|
|
||||||
{
|
|
||||||
vTable->Init = (Mf_Init_Func)MatchFinderMt_Init;
|
|
||||||
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte;
|
|
||||||
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes;
|
|
||||||
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos;
|
|
||||||
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches;
|
|
||||||
switch(p->MatchFinder->numHashBytes)
|
|
||||||
{
|
|
||||||
case 2:
|
|
||||||
p->GetHeadsFunc = GetHeads2;
|
|
||||||
p->MixMatchesFunc = (Mf_Mix_Matches)0;
|
|
||||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip;
|
|
||||||
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
p->GetHeadsFunc = GetHeads3;
|
|
||||||
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2;
|
|
||||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* case 4: */
|
|
||||||
p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4;
|
|
||||||
/* p->GetHeadsFunc = GetHeads4; */
|
|
||||||
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3;
|
|
||||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip;
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
default:
|
|
||||||
p->GetHeadsFunc = GetHeads5;
|
|
||||||
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4;
|
|
||||||
vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip;
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/* MatchFinderMt.h */
|
|
||||||
|
|
||||||
#ifndef __MATCHFINDERMT_H
|
|
||||||
#define __MATCHFINDERMT_H
|
|
||||||
|
|
||||||
#include "../../Threads.h"
|
|
||||||
#include "MatchFinder.h"
|
|
||||||
|
|
||||||
#define kMtHashBlockSize (1 << 13)
|
|
||||||
#define kMtHashNumBlocks (1 << 3)
|
|
||||||
#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1)
|
|
||||||
|
|
||||||
#define kMtBtBlockSize (1 << 14)
|
|
||||||
#define kMtBtNumBlocks (1 << 6)
|
|
||||||
#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1)
|
|
||||||
|
|
||||||
typedef struct _CMtSync
|
|
||||||
{
|
|
||||||
Bool wasCreated;
|
|
||||||
Bool needStart;
|
|
||||||
Bool exit;
|
|
||||||
Bool stopWriting;
|
|
||||||
|
|
||||||
CThread thread;
|
|
||||||
CAutoResetEvent canStart;
|
|
||||||
CAutoResetEvent wasStarted;
|
|
||||||
CAutoResetEvent wasStopped;
|
|
||||||
CSemaphore freeSemaphore;
|
|
||||||
CSemaphore filledSemaphore;
|
|
||||||
Bool csWasInitialized;
|
|
||||||
Bool csWasEntered;
|
|
||||||
CCriticalSection cs;
|
|
||||||
UInt32 numProcessedBlocks;
|
|
||||||
} CMtSync;
|
|
||||||
|
|
||||||
typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);
|
|
||||||
|
|
||||||
/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
|
|
||||||
#define kMtCacheLineDummy 128
|
|
||||||
|
|
||||||
typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
|
|
||||||
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads);
|
|
||||||
|
|
||||||
typedef struct _CMatchFinderMt
|
|
||||||
{
|
|
||||||
/* LZ */
|
|
||||||
const Byte *pointerToCurPos;
|
|
||||||
UInt32 *btBuf;
|
|
||||||
UInt32 btBufPos;
|
|
||||||
UInt32 btBufPosLimit;
|
|
||||||
UInt32 lzPos;
|
|
||||||
UInt32 btNumAvailBytes;
|
|
||||||
|
|
||||||
UInt32 *hash;
|
|
||||||
UInt32 fixedHashSize;
|
|
||||||
UInt32 historySize;
|
|
||||||
|
|
||||||
Mf_Mix_Matches MixMatchesFunc;
|
|
||||||
|
|
||||||
/* LZ + BT */
|
|
||||||
CMtSync btSync;
|
|
||||||
Byte btDummy[kMtCacheLineDummy];
|
|
||||||
|
|
||||||
/* BT */
|
|
||||||
UInt32 *hashBuf;
|
|
||||||
UInt32 hashBufPos;
|
|
||||||
UInt32 hashBufPosLimit;
|
|
||||||
UInt32 hashNumAvail;
|
|
||||||
|
|
||||||
CLzRef *son;
|
|
||||||
UInt32 matchMaxLen;
|
|
||||||
UInt32 numHashBytes;
|
|
||||||
UInt32 pos;
|
|
||||||
Byte *buffer;
|
|
||||||
UInt32 cyclicBufferPos;
|
|
||||||
UInt32 cyclicBufferSize; /* it must be historySize + 1 */
|
|
||||||
UInt32 cutValue;
|
|
||||||
|
|
||||||
/* BT + Hash */
|
|
||||||
CMtSync hashSync;
|
|
||||||
/* Byte hashDummy[kMtCacheLineDummy]; */
|
|
||||||
|
|
||||||
/* Hash */
|
|
||||||
Mf_GetHeads GetHeadsFunc;
|
|
||||||
CMatchFinder *MatchFinder;
|
|
||||||
} CMatchFinderMt;
|
|
||||||
|
|
||||||
void MatchFinderMt_Construct(CMatchFinderMt *p);
|
|
||||||
void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc);
|
|
||||||
HRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,
|
|
||||||
UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc);
|
|
||||||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
|
|
||||||
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,584 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaDecode.c
|
|
||||||
LZMA Decoder (optimized for Speed version)
|
|
||||||
|
|
||||||
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
|
|
||||||
http://www.7-zip.org/
|
|
||||||
|
|
||||||
LZMA SDK is licensed under two licenses:
|
|
||||||
1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
2) Common Public License (CPL)
|
|
||||||
It means that you can select one of these two licenses and
|
|
||||||
follow rules of that license.
|
|
||||||
|
|
||||||
SPECIAL EXCEPTION:
|
|
||||||
Igor Pavlov, as the author of this Code, expressly permits you to
|
|
||||||
statically or dynamically link your Code (or bind by name) to the
|
|
||||||
interfaces of this file without subjecting your linked Code to the
|
|
||||||
terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LzmaDecode.h"
|
|
||||||
|
|
||||||
#define kNumTopBits 24
|
|
||||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
|
||||||
|
|
||||||
#define kNumBitModelTotalBits 11
|
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
|
||||||
#define kNumMoveBits 5
|
|
||||||
|
|
||||||
#define RC_READ_BYTE (*Buffer++)
|
|
||||||
|
|
||||||
#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
|
|
||||||
{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
|
|
||||||
#define RC_TEST { if (Buffer == BufferLim) \
|
|
||||||
{ SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
|
|
||||||
BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
|
|
||||||
|
|
||||||
#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
|
|
||||||
|
|
||||||
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
|
|
||||||
|
|
||||||
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
|
|
||||||
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
|
|
||||||
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
|
|
||||||
|
|
||||||
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
|
|
||||||
{ UpdateBit0(p); mi <<= 1; A0; } else \
|
|
||||||
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; }
|
|
||||||
|
|
||||||
#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
|
|
||||||
|
|
||||||
#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
|
|
||||||
{ int i = numLevels; res = 1; \
|
|
||||||
do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
|
|
||||||
res -= (1 << numLevels); }
|
|
||||||
|
|
||||||
|
|
||||||
#define kNumPosBitsMax 4
|
|
||||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
|
||||||
|
|
||||||
#define kLenNumLowBits 3
|
|
||||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
|
||||||
#define kLenNumMidBits 3
|
|
||||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
|
||||||
#define kLenNumHighBits 8
|
|
||||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
|
||||||
|
|
||||||
#define LenChoice 0
|
|
||||||
#define LenChoice2 (LenChoice + 1)
|
|
||||||
#define LenLow (LenChoice2 + 1)
|
|
||||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
|
||||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
|
||||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
|
||||||
|
|
||||||
|
|
||||||
#define kNumStates 12
|
|
||||||
#define kNumLitStates 7
|
|
||||||
|
|
||||||
#define kStartPosModelIndex 4
|
|
||||||
#define kEndPosModelIndex 14
|
|
||||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
|
||||||
|
|
||||||
#define kNumPosSlotBits 6
|
|
||||||
#define kNumLenToPosStates 4
|
|
||||||
|
|
||||||
#define kNumAlignBits 4
|
|
||||||
#define kAlignTableSize (1 << kNumAlignBits)
|
|
||||||
|
|
||||||
#define kMatchMinLen 2
|
|
||||||
|
|
||||||
#define IsMatch 0
|
|
||||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define IsRepG0 (IsRep + kNumStates)
|
|
||||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
|
||||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
|
||||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
|
||||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
|
||||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
|
||||||
#define LenCoder (Align + kAlignTableSize)
|
|
||||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
|
||||||
#define Literal (RepLenCoder + kNumLenProbs)
|
|
||||||
|
|
||||||
#if Literal != LZMA_BASE_SIZE
|
|
||||||
StopCompilingDueBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
|
|
||||||
{
|
|
||||||
unsigned char prop0;
|
|
||||||
if (size < LZMA_PROPERTIES_SIZE)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
prop0 = propsData[0];
|
|
||||||
if (prop0 >= (9 * 5 * 5))
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
{
|
|
||||||
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
|
|
||||||
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
|
|
||||||
propsRes->lc = prop0;
|
|
||||||
/*
|
|
||||||
unsigned char remainder = (unsigned char)(prop0 / 9);
|
|
||||||
propsRes->lc = prop0 % 9;
|
|
||||||
propsRes->pb = remainder / 5;
|
|
||||||
propsRes->lp = remainder % 5;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
propsRes->DictionarySize = 0;
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
|
|
||||||
if (propsRes->DictionarySize == 0)
|
|
||||||
propsRes->DictionarySize = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kLzmaStreamWasFinishedId (-1)
|
|
||||||
|
|
||||||
int LzmaDecode(CLzmaDecoderState *vs,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ILzmaInCallback *InCallback,
|
|
||||||
#else
|
|
||||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
|
|
||||||
#endif
|
|
||||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
|
|
||||||
{
|
|
||||||
CProb *p = vs->Probs;
|
|
||||||
SizeT nowPos = 0;
|
|
||||||
Byte previousByte = 0;
|
|
||||||
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
|
|
||||||
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
|
|
||||||
int lc = vs->Properties.lc;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
|
|
||||||
UInt32 Range = vs->Range;
|
|
||||||
UInt32 Code = vs->Code;
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
const Byte *Buffer = vs->Buffer;
|
|
||||||
const Byte *BufferLim = vs->BufferLim;
|
|
||||||
#else
|
|
||||||
const Byte *Buffer = inStream;
|
|
||||||
const Byte *BufferLim = inStream + inSize;
|
|
||||||
#endif
|
|
||||||
int state = vs->State;
|
|
||||||
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
|
|
||||||
int len = vs->RemainLen;
|
|
||||||
UInt32 globalPos = vs->GlobalPos;
|
|
||||||
UInt32 distanceLimit = vs->DistanceLimit;
|
|
||||||
|
|
||||||
Byte *dictionary = vs->Dictionary;
|
|
||||||
UInt32 dictionarySize = vs->Properties.DictionarySize;
|
|
||||||
UInt32 dictionaryPos = vs->DictionaryPos;
|
|
||||||
|
|
||||||
Byte tempDictionary[4];
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
*inSizeProcessed = 0;
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = 0;
|
|
||||||
if (len == kLzmaStreamWasFinishedId)
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
|
|
||||||
if (dictionarySize == 0)
|
|
||||||
{
|
|
||||||
dictionary = tempDictionary;
|
|
||||||
dictionarySize = 1;
|
|
||||||
tempDictionary[0] = vs->TempDictionary[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == kLzmaNeedInitId)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
rep0 = rep1 = rep2 = rep3 = 1;
|
|
||||||
state = 0;
|
|
||||||
globalPos = 0;
|
|
||||||
distanceLimit = 0;
|
|
||||||
dictionaryPos = 0;
|
|
||||||
dictionary[dictionarySize - 1] = 0;
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
RC_INIT;
|
|
||||||
#else
|
|
||||||
RC_INIT(inStream, inSize);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize)
|
|
||||||
{
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
if (dictionaryPos == 0)
|
|
||||||
previousByte = dictionary[dictionarySize - 1];
|
|
||||||
else
|
|
||||||
previousByte = dictionary[dictionaryPos - 1];
|
|
||||||
|
|
||||||
#else /* if !_LZMA_OUT_READ */
|
|
||||||
|
|
||||||
int state = 0;
|
|
||||||
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
|
|
||||||
int len = 0;
|
|
||||||
const Byte *Buffer;
|
|
||||||
const Byte *BufferLim;
|
|
||||||
UInt32 Range;
|
|
||||||
UInt32 Code;
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
*inSizeProcessed = 0;
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = 0;
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
RC_INIT;
|
|
||||||
#else
|
|
||||||
RC_INIT(inStream, inSize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _LZMA_OUT_READ */
|
|
||||||
|
|
||||||
while(nowPos < outSize)
|
|
||||||
{
|
|
||||||
CProb *prob;
|
|
||||||
UInt32 bound;
|
|
||||||
int posState = (int)(
|
|
||||||
(nowPos
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
+ globalPos
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
& posStateMask);
|
|
||||||
|
|
||||||
prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
int symbol = 1;
|
|
||||||
UpdateBit0(prob)
|
|
||||||
prob = p + Literal + (LZMA_LIT_SIZE *
|
|
||||||
(((
|
|
||||||
(nowPos
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
+ globalPos
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
& literalPosMask) << lc) + (previousByte >> (8 - lc))));
|
|
||||||
|
|
||||||
if (state >= kNumLitStates)
|
|
||||||
{
|
|
||||||
int matchByte;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
matchByte = dictionary[pos];
|
|
||||||
#else
|
|
||||||
matchByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int bit;
|
|
||||||
CProb *probLit;
|
|
||||||
matchByte <<= 1;
|
|
||||||
bit = (matchByte & 0x100);
|
|
||||||
probLit = prob + 0x100 + bit + symbol;
|
|
||||||
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
}
|
|
||||||
while (symbol < 0x100)
|
|
||||||
{
|
|
||||||
CProb *probLit = prob + symbol;
|
|
||||||
RC_GET_BIT(probLit, symbol)
|
|
||||||
}
|
|
||||||
previousByte = (Byte)symbol;
|
|
||||||
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#endif
|
|
||||||
if (state < 4) state = 0;
|
|
||||||
else if (state < 10) state -= 3;
|
|
||||||
else state -= 6;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRep + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
rep3 = rep2;
|
|
||||||
rep2 = rep1;
|
|
||||||
rep1 = rep0;
|
|
||||||
state = state < kNumLitStates ? 0 : 3;
|
|
||||||
prob = p + LenCoder;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG0 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos;
|
|
||||||
#endif
|
|
||||||
UpdateBit0(prob);
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit == 0)
|
|
||||||
#else
|
|
||||||
if (nowPos == 0)
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
|
|
||||||
state = state < kNumLitStates ? 9 : 11;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#else
|
|
||||||
previousByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 distance;
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG1 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
distance = rep1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG2 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
distance = rep2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
distance = rep3;
|
|
||||||
rep3 = rep2;
|
|
||||||
}
|
|
||||||
rep2 = rep1;
|
|
||||||
}
|
|
||||||
rep1 = rep0;
|
|
||||||
rep0 = distance;
|
|
||||||
}
|
|
||||||
state = state < kNumLitStates ? 8 : 11;
|
|
||||||
prob = p + RepLenCoder;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
int numBits, offset;
|
|
||||||
CProb *probLen = prob + LenChoice;
|
|
||||||
IfBit0(probLen)
|
|
||||||
{
|
|
||||||
UpdateBit0(probLen);
|
|
||||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
|
||||||
offset = 0;
|
|
||||||
numBits = kLenNumLowBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(probLen);
|
|
||||||
probLen = prob + LenChoice2;
|
|
||||||
IfBit0(probLen)
|
|
||||||
{
|
|
||||||
UpdateBit0(probLen);
|
|
||||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
|
||||||
offset = kLenNumLowSymbols;
|
|
||||||
numBits = kLenNumMidBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(probLen);
|
|
||||||
probLen = prob + LenHigh;
|
|
||||||
offset = kLenNumLowSymbols + kLenNumMidSymbols;
|
|
||||||
numBits = kLenNumHighBits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RangeDecoderBitTreeDecode(probLen, numBits, len);
|
|
||||||
len += offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state < 4)
|
|
||||||
{
|
|
||||||
int posSlot;
|
|
||||||
state += kNumLitStates;
|
|
||||||
prob = p + PosSlot +
|
|
||||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
|
||||||
kNumPosSlotBits);
|
|
||||||
RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
|
|
||||||
if (posSlot >= kStartPosModelIndex)
|
|
||||||
{
|
|
||||||
int numDirectBits = ((posSlot >> 1) - 1);
|
|
||||||
rep0 = (2 | ((UInt32)posSlot & 1));
|
|
||||||
if (posSlot < kEndPosModelIndex)
|
|
||||||
{
|
|
||||||
rep0 <<= numDirectBits;
|
|
||||||
prob = p + SpecPos + rep0 - posSlot - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numDirectBits -= kNumAlignBits;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
RC_NORMALIZE
|
|
||||||
Range >>= 1;
|
|
||||||
rep0 <<= 1;
|
|
||||||
if (Code >= Range)
|
|
||||||
{
|
|
||||||
Code -= Range;
|
|
||||||
rep0 |= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (--numDirectBits != 0);
|
|
||||||
prob = p + Align;
|
|
||||||
rep0 <<= kNumAlignBits;
|
|
||||||
numDirectBits = kNumAlignBits;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
int i = 1;
|
|
||||||
int mi = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
CProb *prob3 = prob + mi;
|
|
||||||
RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
|
|
||||||
i <<= 1;
|
|
||||||
}
|
|
||||||
while(--numDirectBits != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rep0 = posSlot;
|
|
||||||
if (++rep0 == (UInt32)(0))
|
|
||||||
{
|
|
||||||
/* it's for stream version */
|
|
||||||
len = kLzmaStreamWasFinishedId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len += kMatchMinLen;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (rep0 > distanceLimit)
|
|
||||||
#else
|
|
||||||
if (rep0 > nowPos)
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (dictionarySize - distanceLimit > (UInt32)len)
|
|
||||||
distanceLimit += len;
|
|
||||||
else
|
|
||||||
distanceLimit = dictionarySize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#else
|
|
||||||
previousByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
len--;
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RC_NORMALIZE;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
vs->Range = Range;
|
|
||||||
vs->Code = Code;
|
|
||||||
vs->DictionaryPos = dictionaryPos;
|
|
||||||
vs->GlobalPos = globalPos + (UInt32)nowPos;
|
|
||||||
vs->DistanceLimit = distanceLimit;
|
|
||||||
vs->Reps[0] = rep0;
|
|
||||||
vs->Reps[1] = rep1;
|
|
||||||
vs->Reps[2] = rep2;
|
|
||||||
vs->Reps[3] = rep3;
|
|
||||||
vs->State = state;
|
|
||||||
vs->RemainLen = len;
|
|
||||||
vs->TempDictionary[0] = tempDictionary[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
vs->Buffer = Buffer;
|
|
||||||
vs->BufferLim = BufferLim;
|
|
||||||
#else
|
|
||||||
*inSizeProcessed = (SizeT)(Buffer - inStream);
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = nowPos;
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaDecode.h
|
|
||||||
LZMA Decoder interface
|
|
||||||
|
|
||||||
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
|
|
||||||
http://www.7-zip.org/
|
|
||||||
|
|
||||||
LZMA SDK is licensed under two licenses:
|
|
||||||
1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
2) Common Public License (CPL)
|
|
||||||
It means that you can select one of these two licenses and
|
|
||||||
follow rules of that license.
|
|
||||||
|
|
||||||
SPECIAL EXCEPTION:
|
|
||||||
Igor Pavlov, as the author of this code, expressly permits you to
|
|
||||||
statically or dynamically link your code (or bind by name) to the
|
|
||||||
interfaces of this file without subjecting your linked code to the
|
|
||||||
terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LZMADECODE_H
|
|
||||||
#define __LZMADECODE_H
|
|
||||||
|
|
||||||
#include "LzmaTypes.h"
|
|
||||||
|
|
||||||
/* #define _LZMA_IN_CB */
|
|
||||||
/* Use callback for input data */
|
|
||||||
|
|
||||||
/* #define _LZMA_OUT_READ */
|
|
||||||
/* Use read function for output data */
|
|
||||||
|
|
||||||
/* #define _LZMA_PROB32 */
|
|
||||||
/* It can increase speed on some 32-bit CPUs,
|
|
||||||
but memory usage will be doubled in that case */
|
|
||||||
|
|
||||||
/* #define _LZMA_LOC_OPT */
|
|
||||||
/* Enable local speed optimizations inside code */
|
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
|
||||||
#define CProb UInt32
|
|
||||||
#else
|
|
||||||
#define CProb UInt16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LZMA_RESULT_OK 0
|
|
||||||
#define LZMA_RESULT_DATA_ERROR 1
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
typedef struct _ILzmaInCallback
|
|
||||||
{
|
|
||||||
int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
|
|
||||||
} ILzmaInCallback;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LZMA_BASE_SIZE 1846
|
|
||||||
#define LZMA_LIT_SIZE 768
|
|
||||||
|
|
||||||
#define LZMA_PROPERTIES_SIZE 5
|
|
||||||
|
|
||||||
typedef struct _CLzmaProperties
|
|
||||||
{
|
|
||||||
int lc;
|
|
||||||
int lp;
|
|
||||||
int pb;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 DictionarySize;
|
|
||||||
#endif
|
|
||||||
}CLzmaProperties;
|
|
||||||
|
|
||||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
|
|
||||||
|
|
||||||
#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
|
|
||||||
|
|
||||||
#define kLzmaNeedInitId (-2)
|
|
||||||
|
|
||||||
typedef struct _CLzmaDecoderState
|
|
||||||
{
|
|
||||||
CLzmaProperties Properties;
|
|
||||||
CProb *Probs;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
const unsigned char *Buffer;
|
|
||||||
const unsigned char *BufferLim;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
unsigned char *Dictionary;
|
|
||||||
UInt32 Range;
|
|
||||||
UInt32 Code;
|
|
||||||
UInt32 DictionaryPos;
|
|
||||||
UInt32 GlobalPos;
|
|
||||||
UInt32 DistanceLimit;
|
|
||||||
UInt32 Reps[4];
|
|
||||||
int State;
|
|
||||||
int RemainLen;
|
|
||||||
unsigned char TempDictionary[4];
|
|
||||||
#endif
|
|
||||||
} CLzmaDecoderState;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int LzmaDecode(CLzmaDecoderState *vs,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ILzmaInCallback *inCallback,
|
|
||||||
#else
|
|
||||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
|
|
||||||
#endif
|
|
||||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,712 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaDecodeSize.c
|
|
||||||
LZMA Decoder (optimized for Size version)
|
|
||||||
|
|
||||||
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
|
|
||||||
http://www.7-zip.org/
|
|
||||||
|
|
||||||
LZMA SDK is licensed under two licenses:
|
|
||||||
1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
2) Common Public License (CPL)
|
|
||||||
It means that you can select one of these two licenses and
|
|
||||||
follow rules of that license.
|
|
||||||
|
|
||||||
SPECIAL EXCEPTION:
|
|
||||||
Igor Pavlov, as the author of this code, expressly permits you to
|
|
||||||
statically or dynamically link your code (or bind by name) to the
|
|
||||||
interfaces of this file without subjecting your linked code to the
|
|
||||||
terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LzmaDecode.h"
|
|
||||||
|
|
||||||
#define kNumTopBits 24
|
|
||||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
|
||||||
|
|
||||||
#define kNumBitModelTotalBits 11
|
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
|
||||||
#define kNumMoveBits 5
|
|
||||||
|
|
||||||
typedef struct _CRangeDecoder
|
|
||||||
{
|
|
||||||
const Byte *Buffer;
|
|
||||||
const Byte *BufferLim;
|
|
||||||
UInt32 Range;
|
|
||||||
UInt32 Code;
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ILzmaInCallback *InCallback;
|
|
||||||
int Result;
|
|
||||||
#endif
|
|
||||||
int ExtraBytes;
|
|
||||||
} CRangeDecoder;
|
|
||||||
|
|
||||||
Byte RangeDecoderReadByte(CRangeDecoder *rd)
|
|
||||||
{
|
|
||||||
if (rd->Buffer == rd->BufferLim)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
SizeT size;
|
|
||||||
rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
|
|
||||||
rd->BufferLim = rd->Buffer + size;
|
|
||||||
if (size == 0)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
rd->ExtraBytes = 1;
|
|
||||||
return 0xFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (*rd->Buffer++);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #define ReadByte (*rd->Buffer++) */
|
|
||||||
#define ReadByte (RangeDecoderReadByte(rd))
|
|
||||||
|
|
||||||
void RangeDecoderInit(CRangeDecoder *rd
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
, const Byte *stream, SizeT bufferSize
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
rd->Buffer = rd->BufferLim = 0;
|
|
||||||
#else
|
|
||||||
rd->Buffer = stream;
|
|
||||||
rd->BufferLim = stream + bufferSize;
|
|
||||||
#endif
|
|
||||||
rd->ExtraBytes = 0;
|
|
||||||
rd->Code = 0;
|
|
||||||
rd->Range = (0xFFFFFFFF);
|
|
||||||
for(i = 0; i < 5; i++)
|
|
||||||
rd->Code = (rd->Code << 8) | ReadByte;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
|
|
||||||
#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
|
|
||||||
#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
|
|
||||||
|
|
||||||
UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
|
|
||||||
{
|
|
||||||
RC_INIT_VAR
|
|
||||||
UInt32 result = 0;
|
|
||||||
int i;
|
|
||||||
for (i = numTotalBits; i != 0; i--)
|
|
||||||
{
|
|
||||||
/* UInt32 t; */
|
|
||||||
range >>= 1;
|
|
||||||
|
|
||||||
result <<= 1;
|
|
||||||
if (code >= range)
|
|
||||||
{
|
|
||||||
code -= range;
|
|
||||||
result |= 1;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
t = (code - range) >> 31;
|
|
||||||
t &= 1;
|
|
||||||
code -= range & (t - 1);
|
|
||||||
result = (result + result) | (1 - t);
|
|
||||||
*/
|
|
||||||
RC_NORMALIZE
|
|
||||||
}
|
|
||||||
RC_FLUSH_VAR
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
|
|
||||||
{
|
|
||||||
UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
|
|
||||||
if (rd->Code < bound)
|
|
||||||
{
|
|
||||||
rd->Range = bound;
|
|
||||||
*prob += (kBitModelTotal - *prob) >> kNumMoveBits;
|
|
||||||
if (rd->Range < kTopValue)
|
|
||||||
{
|
|
||||||
rd->Code = (rd->Code << 8) | ReadByte;
|
|
||||||
rd->Range <<= 8;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rd->Range -= bound;
|
|
||||||
rd->Code -= bound;
|
|
||||||
*prob -= (*prob) >> kNumMoveBits;
|
|
||||||
if (rd->Range < kTopValue)
|
|
||||||
{
|
|
||||||
rd->Code = (rd->Code << 8) | ReadByte;
|
|
||||||
rd->Range <<= 8;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RC_GET_BIT2(prob, mi, A0, A1) \
|
|
||||||
UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
|
|
||||||
if (code < bound) \
|
|
||||||
{ A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
|
|
||||||
else \
|
|
||||||
{ A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
|
|
||||||
RC_NORMALIZE
|
|
||||||
|
|
||||||
#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
|
|
||||||
|
|
||||||
int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
|
|
||||||
{
|
|
||||||
int mi = 1;
|
|
||||||
int i;
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_INIT_VAR
|
|
||||||
#endif
|
|
||||||
for(i = numLevels; i != 0; i--)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
CProb *prob = probs + mi;
|
|
||||||
RC_GET_BIT(prob, mi)
|
|
||||||
#else
|
|
||||||
mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_FLUSH_VAR
|
|
||||||
#endif
|
|
||||||
return mi - (1 << numLevels);
|
|
||||||
}
|
|
||||||
|
|
||||||
int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
|
|
||||||
{
|
|
||||||
int mi = 1;
|
|
||||||
int i;
|
|
||||||
int symbol = 0;
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_INIT_VAR
|
|
||||||
#endif
|
|
||||||
for(i = 0; i < numLevels; i++)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
CProb *prob = probs + mi;
|
|
||||||
RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
|
|
||||||
#else
|
|
||||||
int bit = RangeDecoderBitDecode(probs + mi, rd);
|
|
||||||
mi = mi + mi + bit;
|
|
||||||
symbol |= (bit << i);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_FLUSH_VAR
|
|
||||||
#endif
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
|
|
||||||
{
|
|
||||||
int symbol = 1;
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_INIT_VAR
|
|
||||||
#endif
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
CProb *prob = probs + symbol;
|
|
||||||
RC_GET_BIT(prob, symbol)
|
|
||||||
#else
|
|
||||||
symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_FLUSH_VAR
|
|
||||||
#endif
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
|
|
||||||
{
|
|
||||||
int symbol = 1;
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_INIT_VAR
|
|
||||||
#endif
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int bit;
|
|
||||||
int matchBit = (matchByte >> 7) & 1;
|
|
||||||
matchByte <<= 1;
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
{
|
|
||||||
CProb *prob = probs + 0x100 + (matchBit << 8) + symbol;
|
|
||||||
RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd);
|
|
||||||
symbol = (symbol << 1) | bit;
|
|
||||||
#endif
|
|
||||||
if (matchBit != bit)
|
|
||||||
{
|
|
||||||
while (symbol < 0x100)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
CProb *prob = probs + symbol;
|
|
||||||
RC_GET_BIT(prob, symbol)
|
|
||||||
#else
|
|
||||||
symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
#ifdef _LZMA_LOC_OPT
|
|
||||||
RC_FLUSH_VAR
|
|
||||||
#endif
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kNumPosBitsMax 4
|
|
||||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
|
||||||
|
|
||||||
#define kLenNumLowBits 3
|
|
||||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
|
||||||
#define kLenNumMidBits 3
|
|
||||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
|
||||||
#define kLenNumHighBits 8
|
|
||||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
|
||||||
|
|
||||||
#define LenChoice 0
|
|
||||||
#define LenChoice2 (LenChoice + 1)
|
|
||||||
#define LenLow (LenChoice2 + 1)
|
|
||||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
|
||||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
|
||||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
|
||||||
|
|
||||||
int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
|
|
||||||
{
|
|
||||||
if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
|
|
||||||
return RangeDecoderBitTreeDecode(p + LenLow +
|
|
||||||
(posState << kLenNumLowBits), kLenNumLowBits, rd);
|
|
||||||
if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
|
|
||||||
return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
|
|
||||||
(posState << kLenNumMidBits), kLenNumMidBits, rd);
|
|
||||||
return kLenNumLowSymbols + kLenNumMidSymbols +
|
|
||||||
RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kNumStates 12
|
|
||||||
#define kNumLitStates 7
|
|
||||||
|
|
||||||
#define kStartPosModelIndex 4
|
|
||||||
#define kEndPosModelIndex 14
|
|
||||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
|
||||||
|
|
||||||
#define kNumPosSlotBits 6
|
|
||||||
#define kNumLenToPosStates 4
|
|
||||||
|
|
||||||
#define kNumAlignBits 4
|
|
||||||
#define kAlignTableSize (1 << kNumAlignBits)
|
|
||||||
|
|
||||||
#define kMatchMinLen 2
|
|
||||||
|
|
||||||
#define IsMatch 0
|
|
||||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define IsRepG0 (IsRep + kNumStates)
|
|
||||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
|
||||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
|
||||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
|
||||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
|
||||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
|
||||||
#define LenCoder (Align + kAlignTableSize)
|
|
||||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
|
||||||
#define Literal (RepLenCoder + kNumLenProbs)
|
|
||||||
|
|
||||||
#if Literal != LZMA_BASE_SIZE
|
|
||||||
StopCompilingDueBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
|
|
||||||
{
|
|
||||||
unsigned char prop0;
|
|
||||||
if (size < LZMA_PROPERTIES_SIZE)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
prop0 = propsData[0];
|
|
||||||
if (prop0 >= (9 * 5 * 5))
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
{
|
|
||||||
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
|
|
||||||
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
|
|
||||||
propsRes->lc = prop0;
|
|
||||||
/*
|
|
||||||
unsigned char remainder = (unsigned char)(prop0 / 9);
|
|
||||||
propsRes->lc = prop0 % 9;
|
|
||||||
propsRes->pb = remainder / 5;
|
|
||||||
propsRes->lp = remainder % 5;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
propsRes->DictionarySize = 0;
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
|
|
||||||
if (propsRes->DictionarySize == 0)
|
|
||||||
propsRes->DictionarySize = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kLzmaStreamWasFinishedId (-1)
|
|
||||||
|
|
||||||
int LzmaDecode(CLzmaDecoderState *vs,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
ILzmaInCallback *InCallback,
|
|
||||||
#else
|
|
||||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
|
|
||||||
#endif
|
|
||||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
|
|
||||||
{
|
|
||||||
CProb *p = vs->Probs;
|
|
||||||
SizeT nowPos = 0;
|
|
||||||
Byte previousByte = 0;
|
|
||||||
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
|
|
||||||
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
|
|
||||||
int lc = vs->Properties.lc;
|
|
||||||
CRangeDecoder rd;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
|
|
||||||
int state = vs->State;
|
|
||||||
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
|
|
||||||
int len = vs->RemainLen;
|
|
||||||
UInt32 globalPos = vs->GlobalPos;
|
|
||||||
UInt32 distanceLimit = vs->DistanceLimit;
|
|
||||||
|
|
||||||
Byte *dictionary = vs->Dictionary;
|
|
||||||
UInt32 dictionarySize = vs->Properties.DictionarySize;
|
|
||||||
UInt32 dictionaryPos = vs->DictionaryPos;
|
|
||||||
|
|
||||||
Byte tempDictionary[4];
|
|
||||||
|
|
||||||
rd.Range = vs->Range;
|
|
||||||
rd.Code = vs->Code;
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
rd.InCallback = InCallback;
|
|
||||||
rd.Buffer = vs->Buffer;
|
|
||||||
rd.BufferLim = vs->BufferLim;
|
|
||||||
#else
|
|
||||||
rd.Buffer = inStream;
|
|
||||||
rd.BufferLim = inStream + inSize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
*inSizeProcessed = 0;
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = 0;
|
|
||||||
if (len == kLzmaStreamWasFinishedId)
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
|
|
||||||
if (dictionarySize == 0)
|
|
||||||
{
|
|
||||||
dictionary = tempDictionary;
|
|
||||||
dictionarySize = 1;
|
|
||||||
tempDictionary[0] = vs->TempDictionary[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == kLzmaNeedInitId)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
rep0 = rep1 = rep2 = rep3 = 1;
|
|
||||||
state = 0;
|
|
||||||
globalPos = 0;
|
|
||||||
distanceLimit = 0;
|
|
||||||
dictionaryPos = 0;
|
|
||||||
dictionary[dictionarySize - 1] = 0;
|
|
||||||
RangeDecoderInit(&rd
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
, inStream, inSize
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
if (rd.Result != LZMA_RESULT_OK)
|
|
||||||
return rd.Result;
|
|
||||||
#endif
|
|
||||||
if (rd.ExtraBytes != 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
}
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize)
|
|
||||||
{
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
if (dictionaryPos == 0)
|
|
||||||
previousByte = dictionary[dictionarySize - 1];
|
|
||||||
else
|
|
||||||
previousByte = dictionary[dictionaryPos - 1];
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
rd.Result = LZMA_RESULT_OK;
|
|
||||||
#endif
|
|
||||||
rd.ExtraBytes = 0;
|
|
||||||
|
|
||||||
#else /* if !_LZMA_OUT_READ */
|
|
||||||
|
|
||||||
int state = 0;
|
|
||||||
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
|
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
*inSizeProcessed = 0;
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = 0;
|
|
||||||
|
|
||||||
{
|
|
||||||
UInt32 i;
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
rd.InCallback = InCallback;
|
|
||||||
#endif
|
|
||||||
RangeDecoderInit(&rd
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
, inStream, inSize
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
if (rd.Result != LZMA_RESULT_OK)
|
|
||||||
return rd.Result;
|
|
||||||
#endif
|
|
||||||
if (rd.ExtraBytes != 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
|
|
||||||
#endif /* _LZMA_OUT_READ */
|
|
||||||
|
|
||||||
|
|
||||||
while(nowPos < outSize)
|
|
||||||
{
|
|
||||||
int posState = (int)(
|
|
||||||
(nowPos
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
+ globalPos
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
& posStateMask);
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
if (rd.Result != LZMA_RESULT_OK)
|
|
||||||
return rd.Result;
|
|
||||||
#endif
|
|
||||||
if (rd.ExtraBytes != 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
|
|
||||||
{
|
|
||||||
CProb *probs = p + Literal + (LZMA_LIT_SIZE *
|
|
||||||
(((
|
|
||||||
(nowPos
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
+ globalPos
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
& literalPosMask) << lc) + (previousByte >> (8 - lc))));
|
|
||||||
|
|
||||||
if (state >= kNumLitStates)
|
|
||||||
{
|
|
||||||
Byte matchByte;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
matchByte = dictionary[pos];
|
|
||||||
#else
|
|
||||||
matchByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
previousByte = LzmaLiteralDecode(probs, &rd);
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#endif
|
|
||||||
if (state < 4) state = 0;
|
|
||||||
else if (state < 10) state -= 3;
|
|
||||||
else state -= 6;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
|
|
||||||
{
|
|
||||||
if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
|
|
||||||
{
|
|
||||||
if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit == 0)
|
|
||||||
#else
|
|
||||||
if (nowPos == 0)
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
|
|
||||||
state = state < 7 ? 9 : 11;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#else
|
|
||||||
previousByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
#endif
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 distance;
|
|
||||||
if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
|
|
||||||
distance = rep1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
|
|
||||||
distance = rep2;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
distance = rep3;
|
|
||||||
rep3 = rep2;
|
|
||||||
}
|
|
||||||
rep2 = rep1;
|
|
||||||
}
|
|
||||||
rep1 = rep0;
|
|
||||||
rep0 = distance;
|
|
||||||
}
|
|
||||||
len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
|
|
||||||
state = state < 7 ? 8 : 11;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int posSlot;
|
|
||||||
rep3 = rep2;
|
|
||||||
rep2 = rep1;
|
|
||||||
rep1 = rep0;
|
|
||||||
state = state < 7 ? 7 : 10;
|
|
||||||
len = LzmaLenDecode(p + LenCoder, &rd, posState);
|
|
||||||
posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
|
|
||||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
|
||||||
kNumPosSlotBits), kNumPosSlotBits, &rd);
|
|
||||||
if (posSlot >= kStartPosModelIndex)
|
|
||||||
{
|
|
||||||
int numDirectBits = ((posSlot >> 1) - 1);
|
|
||||||
rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
|
|
||||||
if (posSlot < kEndPosModelIndex)
|
|
||||||
{
|
|
||||||
rep0 += RangeDecoderReverseBitTreeDecode(
|
|
||||||
p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rep0 += RangeDecoderDecodeDirectBits(&rd,
|
|
||||||
numDirectBits - kNumAlignBits) << kNumAlignBits;
|
|
||||||
rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rep0 = posSlot;
|
|
||||||
if (++rep0 == (UInt32)(0))
|
|
||||||
{
|
|
||||||
/* it's for stream version */
|
|
||||||
len = kLzmaStreamWasFinishedId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len += kMatchMinLen;
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (rep0 > distanceLimit)
|
|
||||||
#else
|
|
||||||
if (rep0 > nowPos)
|
|
||||||
#endif
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (dictionarySize - distanceLimit > (UInt32)len)
|
|
||||||
distanceLimit += len;
|
|
||||||
else
|
|
||||||
distanceLimit = dictionarySize;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
#else
|
|
||||||
previousByte = outStream[nowPos - rep0];
|
|
||||||
#endif
|
|
||||||
len--;
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
vs->Range = rd.Range;
|
|
||||||
vs->Code = rd.Code;
|
|
||||||
vs->DictionaryPos = dictionaryPos;
|
|
||||||
vs->GlobalPos = globalPos + (UInt32)nowPos;
|
|
||||||
vs->DistanceLimit = distanceLimit;
|
|
||||||
vs->Reps[0] = rep0;
|
|
||||||
vs->Reps[1] = rep1;
|
|
||||||
vs->Reps[2] = rep2;
|
|
||||||
vs->Reps[3] = rep3;
|
|
||||||
vs->State = state;
|
|
||||||
vs->RemainLen = len;
|
|
||||||
vs->TempDictionary[0] = tempDictionary[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
vs->Buffer = rd.Buffer;
|
|
||||||
vs->BufferLim = rd.BufferLim;
|
|
||||||
#else
|
|
||||||
*inSizeProcessed = (SizeT)(rd.Buffer - inStream);
|
|
||||||
#endif
|
|
||||||
*outSizeProcessed = nowPos;
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
@@ -1,521 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaStateDecode.c
|
|
||||||
LZMA Decoder (State version)
|
|
||||||
|
|
||||||
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
|
|
||||||
http://www.7-zip.org/
|
|
||||||
|
|
||||||
LZMA SDK is licensed under two licenses:
|
|
||||||
1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
2) Common Public License (CPL)
|
|
||||||
It means that you can select one of these two licenses and
|
|
||||||
follow rules of that license.
|
|
||||||
|
|
||||||
SPECIAL EXCEPTION:
|
|
||||||
Igor Pavlov, as the author of this Code, expressly permits you to
|
|
||||||
statically or dynamically link your Code (or bind by name) to the
|
|
||||||
interfaces of this file without subjecting your linked Code to the
|
|
||||||
terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "LzmaStateDecode.h"
|
|
||||||
|
|
||||||
#define kNumTopBits 24
|
|
||||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
|
||||||
|
|
||||||
#define kNumBitModelTotalBits 11
|
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
|
||||||
#define kNumMoveBits 5
|
|
||||||
|
|
||||||
#define RC_READ_BYTE (*Buffer++)
|
|
||||||
|
|
||||||
#define RC_INIT Code = 0; Range = 0xFFFFFFFF; \
|
|
||||||
{ int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }}
|
|
||||||
|
|
||||||
#define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
|
|
||||||
|
|
||||||
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
|
|
||||||
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
|
|
||||||
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
|
|
||||||
|
|
||||||
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
|
|
||||||
{ UpdateBit0(p); mi <<= 1; A0; } else \
|
|
||||||
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; }
|
|
||||||
|
|
||||||
#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
|
|
||||||
|
|
||||||
#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
|
|
||||||
{ int i = numLevels; res = 1; \
|
|
||||||
do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
|
|
||||||
res -= (1 << numLevels); }
|
|
||||||
|
|
||||||
|
|
||||||
#define kNumPosBitsMax 4
|
|
||||||
#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
|
||||||
|
|
||||||
#define kLenNumLowBits 3
|
|
||||||
#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
|
||||||
#define kLenNumMidBits 3
|
|
||||||
#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
|
||||||
#define kLenNumHighBits 8
|
|
||||||
#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
|
||||||
|
|
||||||
#define LenChoice 0
|
|
||||||
#define LenChoice2 (LenChoice + 1)
|
|
||||||
#define LenLow (LenChoice2 + 1)
|
|
||||||
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
|
||||||
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
|
||||||
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
|
||||||
|
|
||||||
|
|
||||||
#define kNumStates 12
|
|
||||||
#define kNumLitStates 7
|
|
||||||
|
|
||||||
#define kStartPosModelIndex 4
|
|
||||||
#define kEndPosModelIndex 14
|
|
||||||
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
|
||||||
|
|
||||||
#define kNumPosSlotBits 6
|
|
||||||
#define kNumLenToPosStates 4
|
|
||||||
|
|
||||||
#define kNumAlignBits 4
|
|
||||||
#define kAlignTableSize (1 << kNumAlignBits)
|
|
||||||
|
|
||||||
#define kMatchMinLen 2
|
|
||||||
|
|
||||||
#define IsMatch 0
|
|
||||||
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define IsRepG0 (IsRep + kNumStates)
|
|
||||||
#define IsRepG1 (IsRepG0 + kNumStates)
|
|
||||||
#define IsRepG2 (IsRepG1 + kNumStates)
|
|
||||||
#define IsRep0Long (IsRepG2 + kNumStates)
|
|
||||||
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
|
||||||
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
|
||||||
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
|
||||||
#define LenCoder (Align + kAlignTableSize)
|
|
||||||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
|
||||||
#define Literal (RepLenCoder + kNumLenProbs)
|
|
||||||
|
|
||||||
#if Literal != LZMA_BASE_SIZE
|
|
||||||
StopCompilingDueBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* kRequiredInBufferSize = number of required input bytes for worst case:
|
|
||||||
longest match with longest distance.
|
|
||||||
kLzmaInBufferSize must be larger than kRequiredInBufferSize
|
|
||||||
23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8)
|
|
||||||
|
|
||||||
#define kLzmaStreamWasFinishedId (-1)
|
|
||||||
|
|
||||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
|
|
||||||
{
|
|
||||||
unsigned char prop0;
|
|
||||||
if (size < LZMA_PROPERTIES_SIZE)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
prop0 = propsData[0];
|
|
||||||
if (prop0 >= (9 * 5 * 5))
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
{
|
|
||||||
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
|
|
||||||
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
|
|
||||||
propsRes->lc = prop0;
|
|
||||||
/*
|
|
||||||
unsigned char remainder = (unsigned char)(prop0 / 9);
|
|
||||||
propsRes->lc = prop0 % 9;
|
|
||||||
propsRes->pb = remainder / 5;
|
|
||||||
propsRes->lp = remainder % 5;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
propsRes->DictionarySize = 0;
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
|
|
||||||
if (propsRes->DictionarySize == 0)
|
|
||||||
propsRes->DictionarySize = 1;
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int LzmaDecode(
|
|
||||||
CLzmaDecoderState *vs,
|
|
||||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
|
|
||||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
|
|
||||||
int finishDecoding)
|
|
||||||
{
|
|
||||||
UInt32 Range = vs->Range;
|
|
||||||
UInt32 Code = vs->Code;
|
|
||||||
|
|
||||||
unsigned char *Buffer = vs->Buffer;
|
|
||||||
int BufferSize = vs->BufferSize; /* don't change it to unsigned int */
|
|
||||||
CProb *p = vs->Probs;
|
|
||||||
|
|
||||||
int state = vs->State;
|
|
||||||
unsigned char previousByte;
|
|
||||||
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
|
|
||||||
SizeT nowPos = 0;
|
|
||||||
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
|
|
||||||
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
|
|
||||||
int lc = vs->Properties.lc;
|
|
||||||
int len = vs->RemainLen;
|
|
||||||
UInt32 globalPos = vs->GlobalPos;
|
|
||||||
UInt32 distanceLimit = vs->DistanceLimit;
|
|
||||||
|
|
||||||
unsigned char *dictionary = vs->Dictionary;
|
|
||||||
UInt32 dictionarySize = vs->Properties.DictionarySize;
|
|
||||||
UInt32 dictionaryPos = vs->DictionaryPos;
|
|
||||||
|
|
||||||
unsigned char tempDictionary[4];
|
|
||||||
|
|
||||||
(*inSizeProcessed) = 0;
|
|
||||||
(*outSizeProcessed) = 0;
|
|
||||||
if (len == kLzmaStreamWasFinishedId)
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
|
|
||||||
if (dictionarySize == 0)
|
|
||||||
{
|
|
||||||
dictionary = tempDictionary;
|
|
||||||
dictionarySize = 1;
|
|
||||||
tempDictionary[0] = vs->TempDictionary[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == kLzmaNeedInitId)
|
|
||||||
{
|
|
||||||
while (inSize > 0 && BufferSize < kLzmaInBufferSize)
|
|
||||||
{
|
|
||||||
Buffer[BufferSize++] = *inStream++;
|
|
||||||
(*inSizeProcessed)++;
|
|
||||||
inSize--;
|
|
||||||
}
|
|
||||||
if (BufferSize < 5)
|
|
||||||
{
|
|
||||||
vs->BufferSize = BufferSize;
|
|
||||||
return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < numProbs; i++)
|
|
||||||
p[i] = kBitModelTotal >> 1;
|
|
||||||
rep0 = rep1 = rep2 = rep3 = 1;
|
|
||||||
state = 0;
|
|
||||||
globalPos = 0;
|
|
||||||
distanceLimit = 0;
|
|
||||||
dictionaryPos = 0;
|
|
||||||
dictionary[dictionarySize - 1] = 0;
|
|
||||||
RC_INIT;
|
|
||||||
}
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize)
|
|
||||||
{
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
if (dictionaryPos == 0)
|
|
||||||
previousByte = dictionary[dictionarySize - 1];
|
|
||||||
else
|
|
||||||
previousByte = dictionary[dictionaryPos - 1];
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int bufferPos = (int)(Buffer - vs->Buffer);
|
|
||||||
if (BufferSize - bufferPos < kRequiredInBufferSize)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
BufferSize -= bufferPos;
|
|
||||||
if (BufferSize < 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
for (i = 0; i < BufferSize; i++)
|
|
||||||
vs->Buffer[i] = Buffer[i];
|
|
||||||
Buffer = vs->Buffer;
|
|
||||||
while (inSize > 0 && BufferSize < kLzmaInBufferSize)
|
|
||||||
{
|
|
||||||
Buffer[BufferSize++] = *inStream++;
|
|
||||||
(*inSizeProcessed)++;
|
|
||||||
inSize--;
|
|
||||||
}
|
|
||||||
if (BufferSize < kRequiredInBufferSize && !finishDecoding)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (nowPos >= outSize)
|
|
||||||
break;
|
|
||||||
{
|
|
||||||
CProb *prob;
|
|
||||||
UInt32 bound;
|
|
||||||
int posState = (int)((nowPos + globalPos) & posStateMask);
|
|
||||||
|
|
||||||
prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
int symbol = 1;
|
|
||||||
UpdateBit0(prob)
|
|
||||||
prob = p + Literal + (LZMA_LIT_SIZE *
|
|
||||||
((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc))));
|
|
||||||
|
|
||||||
if (state >= kNumLitStates)
|
|
||||||
{
|
|
||||||
int matchByte;
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
matchByte = dictionary[pos];
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int bit;
|
|
||||||
CProb *probLit;
|
|
||||||
matchByte <<= 1;
|
|
||||||
bit = (matchByte & 0x100);
|
|
||||||
probLit = prob + 0x100 + bit + symbol;
|
|
||||||
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
|
|
||||||
}
|
|
||||||
while (symbol < 0x100);
|
|
||||||
}
|
|
||||||
while (symbol < 0x100)
|
|
||||||
{
|
|
||||||
CProb *probLit = prob + symbol;
|
|
||||||
RC_GET_BIT(probLit, symbol)
|
|
||||||
}
|
|
||||||
previousByte = (unsigned char)symbol;
|
|
||||||
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
if (state < 4) state = 0;
|
|
||||||
else if (state < 10) state -= 3;
|
|
||||||
else state -= 6;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRep + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
rep3 = rep2;
|
|
||||||
rep2 = rep1;
|
|
||||||
rep1 = rep0;
|
|
||||||
state = state < kNumLitStates ? 0 : 3;
|
|
||||||
prob = p + LenCoder;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG0 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UInt32 pos;
|
|
||||||
UpdateBit0(prob);
|
|
||||||
if (distanceLimit == 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
if (distanceLimit < dictionarySize)
|
|
||||||
distanceLimit++;
|
|
||||||
state = state < kNumLitStates ? 9 : 11;
|
|
||||||
pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UInt32 distance;
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG1 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
distance = rep1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
prob = p + IsRepG2 + state;
|
|
||||||
IfBit0(prob)
|
|
||||||
{
|
|
||||||
UpdateBit0(prob);
|
|
||||||
distance = rep2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(prob);
|
|
||||||
distance = rep3;
|
|
||||||
rep3 = rep2;
|
|
||||||
}
|
|
||||||
rep2 = rep1;
|
|
||||||
}
|
|
||||||
rep1 = rep0;
|
|
||||||
rep0 = distance;
|
|
||||||
}
|
|
||||||
state = state < kNumLitStates ? 8 : 11;
|
|
||||||
prob = p + RepLenCoder;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
int numBits, offset;
|
|
||||||
CProb *probLen = prob + LenChoice;
|
|
||||||
IfBit0(probLen)
|
|
||||||
{
|
|
||||||
UpdateBit0(probLen);
|
|
||||||
probLen = prob + LenLow + (posState << kLenNumLowBits);
|
|
||||||
offset = 0;
|
|
||||||
numBits = kLenNumLowBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(probLen);
|
|
||||||
probLen = prob + LenChoice2;
|
|
||||||
IfBit0(probLen)
|
|
||||||
{
|
|
||||||
UpdateBit0(probLen);
|
|
||||||
probLen = prob + LenMid + (posState << kLenNumMidBits);
|
|
||||||
offset = kLenNumLowSymbols;
|
|
||||||
numBits = kLenNumMidBits;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateBit1(probLen);
|
|
||||||
probLen = prob + LenHigh;
|
|
||||||
offset = kLenNumLowSymbols + kLenNumMidSymbols;
|
|
||||||
numBits = kLenNumHighBits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RangeDecoderBitTreeDecode(probLen, numBits, len);
|
|
||||||
len += offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state < 4)
|
|
||||||
{
|
|
||||||
int posSlot;
|
|
||||||
state += kNumLitStates;
|
|
||||||
prob = p + PosSlot +
|
|
||||||
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
|
||||||
kNumPosSlotBits);
|
|
||||||
RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
|
|
||||||
if (posSlot >= kStartPosModelIndex)
|
|
||||||
{
|
|
||||||
int numDirectBits = ((posSlot >> 1) - 1);
|
|
||||||
rep0 = (2 | ((UInt32)posSlot & 1));
|
|
||||||
if (posSlot < kEndPosModelIndex)
|
|
||||||
{
|
|
||||||
rep0 <<= numDirectBits;
|
|
||||||
prob = p + SpecPos + rep0 - posSlot - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
numDirectBits -= kNumAlignBits;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
RC_NORMALIZE
|
|
||||||
Range >>= 1;
|
|
||||||
rep0 <<= 1;
|
|
||||||
if (Code >= Range)
|
|
||||||
{
|
|
||||||
Code -= Range;
|
|
||||||
rep0 |= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (--numDirectBits != 0);
|
|
||||||
prob = p + Align;
|
|
||||||
rep0 <<= kNumAlignBits;
|
|
||||||
numDirectBits = kNumAlignBits;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
int i = 1;
|
|
||||||
int mi = 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
CProb *prob3 = prob + mi;
|
|
||||||
RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
|
|
||||||
i <<= 1;
|
|
||||||
}
|
|
||||||
while(--numDirectBits != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rep0 = posSlot;
|
|
||||||
if (++rep0 == (UInt32)(0))
|
|
||||||
{
|
|
||||||
/* it's for stream version */
|
|
||||||
len = kLzmaStreamWasFinishedId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len += kMatchMinLen;
|
|
||||||
if (rep0 > distanceLimit)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
if (dictionarySize - distanceLimit > (UInt32)len)
|
|
||||||
distanceLimit += len;
|
|
||||||
else
|
|
||||||
distanceLimit = dictionarySize;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
UInt32 pos = dictionaryPos - rep0;
|
|
||||||
if (pos >= dictionarySize)
|
|
||||||
pos += dictionarySize;
|
|
||||||
previousByte = dictionary[pos];
|
|
||||||
dictionary[dictionaryPos] = previousByte;
|
|
||||||
if (++dictionaryPos == dictionarySize)
|
|
||||||
dictionaryPos = 0;
|
|
||||||
len--;
|
|
||||||
outStream[nowPos++] = previousByte;
|
|
||||||
}
|
|
||||||
while(len != 0 && nowPos < outSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RC_NORMALIZE;
|
|
||||||
|
|
||||||
BufferSize -= (int)(Buffer - vs->Buffer);
|
|
||||||
if (BufferSize < 0)
|
|
||||||
return LZMA_RESULT_DATA_ERROR;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < BufferSize; i++)
|
|
||||||
vs->Buffer[i] = Buffer[i];
|
|
||||||
}
|
|
||||||
vs->BufferSize = BufferSize;
|
|
||||||
vs->Range = Range;
|
|
||||||
vs->Code = Code;
|
|
||||||
vs->DictionaryPos = dictionaryPos;
|
|
||||||
vs->GlobalPos = (UInt32)(globalPos + nowPos);
|
|
||||||
vs->DistanceLimit = distanceLimit;
|
|
||||||
vs->Reps[0] = rep0;
|
|
||||||
vs->Reps[1] = rep1;
|
|
||||||
vs->Reps[2] = rep2;
|
|
||||||
vs->Reps[3] = rep3;
|
|
||||||
vs->State = state;
|
|
||||||
vs->RemainLen = len;
|
|
||||||
vs->TempDictionary[0] = tempDictionary[0];
|
|
||||||
|
|
||||||
(*outSizeProcessed) = nowPos;
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaStateDecode.h
|
|
||||||
LZMA Decoder interface (State version)
|
|
||||||
|
|
||||||
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
|
|
||||||
http://www.7-zip.org/
|
|
||||||
|
|
||||||
LZMA SDK is licensed under two licenses:
|
|
||||||
1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
2) Common Public License (CPL)
|
|
||||||
It means that you can select one of these two licenses and
|
|
||||||
follow rules of that license.
|
|
||||||
|
|
||||||
SPECIAL EXCEPTION:
|
|
||||||
Igor Pavlov, as the author of this code, expressly permits you to
|
|
||||||
statically or dynamically link your code (or bind by name) to the
|
|
||||||
interfaces of this file without subjecting your linked code to the
|
|
||||||
terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LZMASTATEDECODE_H
|
|
||||||
#define __LZMASTATEDECODE_H
|
|
||||||
|
|
||||||
#include "LzmaTypes.h"
|
|
||||||
|
|
||||||
/* #define _LZMA_PROB32 */
|
|
||||||
/* It can increase speed on some 32-bit CPUs,
|
|
||||||
but memory usage will be doubled in that case */
|
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
|
||||||
#define CProb UInt32
|
|
||||||
#else
|
|
||||||
#define CProb UInt16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LZMA_RESULT_OK 0
|
|
||||||
#define LZMA_RESULT_DATA_ERROR 1
|
|
||||||
|
|
||||||
#define LZMA_BASE_SIZE 1846
|
|
||||||
#define LZMA_LIT_SIZE 768
|
|
||||||
|
|
||||||
#define LZMA_PROPERTIES_SIZE 5
|
|
||||||
|
|
||||||
typedef struct _CLzmaProperties
|
|
||||||
{
|
|
||||||
int lc;
|
|
||||||
int lp;
|
|
||||||
int pb;
|
|
||||||
UInt32 DictionarySize;
|
|
||||||
}CLzmaProperties;
|
|
||||||
|
|
||||||
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
|
|
||||||
|
|
||||||
#define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp)))
|
|
||||||
|
|
||||||
#define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */
|
|
||||||
|
|
||||||
#define kLzmaNeedInitId (-2)
|
|
||||||
|
|
||||||
typedef struct _CLzmaDecoderState
|
|
||||||
{
|
|
||||||
CLzmaProperties Properties;
|
|
||||||
CProb *Probs;
|
|
||||||
unsigned char *Dictionary;
|
|
||||||
|
|
||||||
unsigned char Buffer[kLzmaInBufferSize];
|
|
||||||
int BufferSize;
|
|
||||||
|
|
||||||
UInt32 Range;
|
|
||||||
UInt32 Code;
|
|
||||||
UInt32 DictionaryPos;
|
|
||||||
UInt32 GlobalPos;
|
|
||||||
UInt32 DistanceLimit;
|
|
||||||
UInt32 Reps[4];
|
|
||||||
int State;
|
|
||||||
int RemainLen; /* -2: decoder needs internal initialization
|
|
||||||
-1: stream was finished,
|
|
||||||
0: ok
|
|
||||||
> 0: need to write RemainLen bytes as match Reps[0],
|
|
||||||
*/
|
|
||||||
unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */
|
|
||||||
} CLzmaDecoderState;
|
|
||||||
|
|
||||||
#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; }
|
|
||||||
|
|
||||||
/* LzmaDecode: decoding from input stream to output stream.
|
|
||||||
If finishDecoding != 0, then there are no more bytes in input stream
|
|
||||||
after inStream[inSize - 1]. */
|
|
||||||
|
|
||||||
int LzmaDecode(CLzmaDecoderState *vs,
|
|
||||||
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
|
|
||||||
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed,
|
|
||||||
int finishDecoding);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaStateTest.c
|
|
||||||
Test application for LZMA Decoder (State version)
|
|
||||||
|
|
||||||
This file written and distributed to public domain by Igor Pavlov.
|
|
||||||
This file is part of LZMA SDK 4.26 (2005-08-02)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "LzmaStateDecode.h"
|
|
||||||
|
|
||||||
const char *kCantReadMessage = "Can not read input file";
|
|
||||||
const char *kCantWriteMessage = "Can not write output file";
|
|
||||||
const char *kCantAllocateMessage = "Can not allocate memory";
|
|
||||||
|
|
||||||
#define kInBufferSize (1 << 15)
|
|
||||||
#define kOutBufferSize (1 << 15)
|
|
||||||
|
|
||||||
unsigned char g_InBuffer[kInBufferSize];
|
|
||||||
unsigned char g_OutBuffer[kOutBufferSize];
|
|
||||||
|
|
||||||
size_t MyReadFile(FILE *file, void *data, size_t size)
|
|
||||||
{ return fread(data, 1, size, file); }
|
|
||||||
|
|
||||||
int MyReadFileAndCheck(FILE *file, void *data, size_t size)
|
|
||||||
{ return (MyReadFile(file, data, size) == size); }
|
|
||||||
|
|
||||||
int PrintError(char *buffer, const char *message)
|
|
||||||
{
|
|
||||||
sprintf(buffer + strlen(buffer), "\nError: ");
|
|
||||||
sprintf(buffer + strlen(buffer), message);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main3(FILE *inFile, FILE *outFile, char *rs)
|
|
||||||
{
|
|
||||||
/* We use two 32-bit integers to construct 64-bit integer for file size.
|
|
||||||
You can remove outSizeHigh, if you don't need >= 4GB supporting,
|
|
||||||
or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
|
|
||||||
UInt32 outSize = 0;
|
|
||||||
UInt32 outSizeHigh = 0;
|
|
||||||
|
|
||||||
int waitEOS = 1;
|
|
||||||
/* waitEOS = 1, if there is no uncompressed size in headers,
|
|
||||||
so decoder will wait EOS (End of Stream Marker) in compressed stream */
|
|
||||||
|
|
||||||
int i;
|
|
||||||
int res = 0;
|
|
||||||
CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */
|
|
||||||
unsigned char properties[LZMA_PROPERTIES_SIZE];
|
|
||||||
SizeT inAvail = 0;
|
|
||||||
unsigned char *inBuffer = 0;
|
|
||||||
|
|
||||||
if (sizeof(UInt32) < 4)
|
|
||||||
return PrintError(rs, "LZMA decoder needs correct UInt32");
|
|
||||||
|
|
||||||
/* Read LZMA properties for compressed stream */
|
|
||||||
|
|
||||||
if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
|
|
||||||
return PrintError(rs, kCantReadMessage);
|
|
||||||
|
|
||||||
/* Read uncompressed size */
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
unsigned char b;
|
|
||||||
if (!MyReadFileAndCheck(inFile, &b, 1))
|
|
||||||
return PrintError(rs, kCantReadMessage);
|
|
||||||
if (b != 0xFF)
|
|
||||||
waitEOS = 0;
|
|
||||||
if (i < 4)
|
|
||||||
outSize += (UInt32)(b) << (i * 8);
|
|
||||||
else
|
|
||||||
outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode LZMA properties and allocate memory */
|
|
||||||
|
|
||||||
if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
|
|
||||||
return PrintError(rs, "Incorrect stream properties");
|
|
||||||
state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
|
|
||||||
if (state.Probs == 0)
|
|
||||||
return PrintError(rs, kCantAllocateMessage);
|
|
||||||
|
|
||||||
if (state.Properties.DictionarySize == 0)
|
|
||||||
state.Dictionary = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
|
|
||||||
if (state.Dictionary == 0)
|
|
||||||
{
|
|
||||||
free(state.Probs);
|
|
||||||
return PrintError(rs, kCantAllocateMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decompress */
|
|
||||||
|
|
||||||
LzmaDecoderInit(&state);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
SizeT inProcessed, outProcessed;
|
|
||||||
int finishDecoding;
|
|
||||||
UInt32 outAvail = kOutBufferSize;
|
|
||||||
if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
|
|
||||||
outAvail = outSize;
|
|
||||||
if (inAvail == 0)
|
|
||||||
{
|
|
||||||
inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize);
|
|
||||||
inBuffer = g_InBuffer;
|
|
||||||
}
|
|
||||||
finishDecoding = (inAvail == 0);
|
|
||||||
res = LzmaDecode(&state,
|
|
||||||
inBuffer, inAvail, &inProcessed,
|
|
||||||
g_OutBuffer, outAvail, &outProcessed,
|
|
||||||
finishDecoding);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
inAvail -= inProcessed;
|
|
||||||
inBuffer += inProcessed;
|
|
||||||
|
|
||||||
if (outFile != 0)
|
|
||||||
if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed)
|
|
||||||
{
|
|
||||||
PrintError(rs, kCantWriteMessage);
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outSize < outProcessed)
|
|
||||||
outSizeHigh--;
|
|
||||||
outSize -= (UInt32)outProcessed;
|
|
||||||
outSize &= 0xFFFFFFFF;
|
|
||||||
|
|
||||||
if (outProcessed == 0 && finishDecoding)
|
|
||||||
{
|
|
||||||
if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
|
|
||||||
|
|
||||||
free(state.Dictionary);
|
|
||||||
free(state.Probs);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main2(int numArgs, const char *args[], char *rs)
|
|
||||||
{
|
|
||||||
FILE *inFile = 0;
|
|
||||||
FILE *outFile = 0;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n");
|
|
||||||
if (numArgs < 2 || numArgs > 3)
|
|
||||||
{
|
|
||||||
sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inFile = fopen(args[1], "rb");
|
|
||||||
if (inFile == 0)
|
|
||||||
return PrintError(rs, "Can not open input file");
|
|
||||||
|
|
||||||
if (numArgs > 2)
|
|
||||||
{
|
|
||||||
outFile = fopen(args[2], "wb+");
|
|
||||||
if (outFile == 0)
|
|
||||||
return PrintError(rs, "Can not open output file");
|
|
||||||
}
|
|
||||||
|
|
||||||
res = main3(inFile, outFile, rs);
|
|
||||||
|
|
||||||
if (outFile != 0)
|
|
||||||
fclose(outFile);
|
|
||||||
fclose(inFile);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int numArgs, const char *args[])
|
|
||||||
{
|
|
||||||
char rs[800] = { 0 };
|
|
||||||
int res = main2(numArgs, args, rs);
|
|
||||||
printf(rs);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
@@ -1,342 +0,0 @@
|
|||||||
/*
|
|
||||||
LzmaTest.c
|
|
||||||
Test application for LZMA Decoder
|
|
||||||
|
|
||||||
This file written and distributed to public domain by Igor Pavlov.
|
|
||||||
This file is part of LZMA SDK 4.26 (2005-08-05)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "LzmaDecode.h"
|
|
||||||
|
|
||||||
const char *kCantReadMessage = "Can not read input file";
|
|
||||||
const char *kCantWriteMessage = "Can not write output file";
|
|
||||||
const char *kCantAllocateMessage = "Can not allocate memory";
|
|
||||||
|
|
||||||
size_t MyReadFile(FILE *file, void *data, size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
return fread(data, 1, size, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
int MyReadFileAndCheck(FILE *file, void *data, size_t size)
|
|
||||||
{ return (MyReadFile(file, data, size) == size);}
|
|
||||||
|
|
||||||
size_t MyWriteFile(FILE *file, const void *data, size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 0;
|
|
||||||
return fwrite(data, 1, size, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
int MyWriteFileAndCheck(FILE *file, const void *data, size_t size)
|
|
||||||
{ return (MyWriteFile(file, data, size) == size); }
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
#define kInBufferSize (1 << 15)
|
|
||||||
typedef struct _CBuffer
|
|
||||||
{
|
|
||||||
ILzmaInCallback InCallback;
|
|
||||||
FILE *File;
|
|
||||||
unsigned char Buffer[kInBufferSize];
|
|
||||||
} CBuffer;
|
|
||||||
|
|
||||||
int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size)
|
|
||||||
{
|
|
||||||
CBuffer *b = (CBuffer *)object;
|
|
||||||
*buffer = b->Buffer;
|
|
||||||
*size = (SizeT)MyReadFile(b->File, b->Buffer, kInBufferSize);
|
|
||||||
return LZMA_RESULT_OK;
|
|
||||||
}
|
|
||||||
CBuffer g_InBuffer;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
#define kOutBufferSize (1 << 15)
|
|
||||||
unsigned char g_OutBuffer[kOutBufferSize];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int PrintError(char *buffer, const char *message)
|
|
||||||
{
|
|
||||||
sprintf(buffer + strlen(buffer), "\nError: ");
|
|
||||||
sprintf(buffer + strlen(buffer), message);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main3(FILE *inFile, FILE *outFile, char *rs)
|
|
||||||
{
|
|
||||||
/* We use two 32-bit integers to construct 64-bit integer for file size.
|
|
||||||
You can remove outSizeHigh, if you don't need >= 4GB supporting,
|
|
||||||
or you can use UInt64 outSize, if your compiler supports 64-bit integers*/
|
|
||||||
UInt32 outSize = 0;
|
|
||||||
UInt32 outSizeHigh = 0;
|
|
||||||
#ifndef _LZMA_OUT_READ
|
|
||||||
SizeT outSizeFull;
|
|
||||||
unsigned char *outStream;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int waitEOS = 1;
|
|
||||||
/* waitEOS = 1, if there is no uncompressed size in headers,
|
|
||||||
so decoder will wait EOS (End of Stream Marker) in compressed stream */
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
SizeT compressedSize;
|
|
||||||
unsigned char *inStream;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
|
|
||||||
unsigned char properties[LZMA_PROPERTIES_SIZE];
|
|
||||||
|
|
||||||
int res;
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
g_InBuffer.File = inFile;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (sizeof(UInt32) < 4)
|
|
||||||
return PrintError(rs, "LZMA decoder needs correct UInt32");
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
{
|
|
||||||
long length;
|
|
||||||
fseek(inFile, 0, SEEK_END);
|
|
||||||
length = ftell(inFile);
|
|
||||||
fseek(inFile, 0, SEEK_SET);
|
|
||||||
if ((long)(SizeT)length != length)
|
|
||||||
return PrintError(rs, "Too big compressed stream");
|
|
||||||
compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read LZMA properties for compressed stream */
|
|
||||||
|
|
||||||
if (!MyReadFileAndCheck(inFile, properties, sizeof(properties)))
|
|
||||||
return PrintError(rs, kCantReadMessage);
|
|
||||||
|
|
||||||
/* Read uncompressed size */
|
|
||||||
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
unsigned char b;
|
|
||||||
if (!MyReadFileAndCheck(inFile, &b, 1))
|
|
||||||
return PrintError(rs, kCantReadMessage);
|
|
||||||
if (b != 0xFF)
|
|
||||||
waitEOS = 0;
|
|
||||||
if (i < 4)
|
|
||||||
outSize += (UInt32)(b) << (i * 8);
|
|
||||||
else
|
|
||||||
outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef _LZMA_OUT_READ
|
|
||||||
if (waitEOS)
|
|
||||||
return PrintError(rs, "Stream with EOS marker is not supported");
|
|
||||||
outSizeFull = (SizeT)outSize;
|
|
||||||
if (sizeof(SizeT) >= 8)
|
|
||||||
outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
|
|
||||||
else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize)
|
|
||||||
return PrintError(rs, "Too big uncompressed stream");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode LZMA properties and allocate memory */
|
|
||||||
|
|
||||||
if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK)
|
|
||||||
return PrintError(rs, "Incorrect stream properties");
|
|
||||||
state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
if (state.Properties.DictionarySize == 0)
|
|
||||||
state.Dictionary = 0;
|
|
||||||
else
|
|
||||||
state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize);
|
|
||||||
#else
|
|
||||||
if (outSizeFull == 0)
|
|
||||||
outStream = 0;
|
|
||||||
else
|
|
||||||
outStream = (unsigned char *)malloc(outSizeFull);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
if (compressedSize == 0)
|
|
||||||
inStream = 0;
|
|
||||||
else
|
|
||||||
inStream = (unsigned char *)malloc(compressedSize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (state.Probs == 0
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
|| (state.Dictionary == 0 && state.Properties.DictionarySize != 0)
|
|
||||||
#else
|
|
||||||
|| (outStream == 0 && outSizeFull != 0)
|
|
||||||
#endif
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
|| (inStream == 0 && compressedSize != 0)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
free(state.Probs);
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
free(state.Dictionary);
|
|
||||||
#else
|
|
||||||
free(outStream);
|
|
||||||
#endif
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
free(inStream);
|
|
||||||
#endif
|
|
||||||
return PrintError(rs, kCantAllocateMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decompress */
|
|
||||||
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
g_InBuffer.InCallback.Read = LzmaReadCompressed;
|
|
||||||
#else
|
|
||||||
if (!MyReadFileAndCheck(inFile, inStream, compressedSize))
|
|
||||||
return PrintError(rs, kCantReadMessage);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
{
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
SizeT inAvail = compressedSize;
|
|
||||||
const unsigned char *inBuffer = inStream;
|
|
||||||
#endif
|
|
||||||
LzmaDecoderInit(&state);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
SizeT inProcessed;
|
|
||||||
#endif
|
|
||||||
SizeT outProcessed;
|
|
||||||
SizeT outAvail = kOutBufferSize;
|
|
||||||
if (!waitEOS && outSizeHigh == 0 && outAvail > outSize)
|
|
||||||
outAvail = (SizeT)outSize;
|
|
||||||
res = LzmaDecode(&state,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
&g_InBuffer.InCallback,
|
|
||||||
#else
|
|
||||||
inBuffer, inAvail, &inProcessed,
|
|
||||||
#endif
|
|
||||||
g_OutBuffer, outAvail, &outProcessed);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
inAvail -= inProcessed;
|
|
||||||
inBuffer += inProcessed;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (outFile != 0)
|
|
||||||
if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed))
|
|
||||||
{
|
|
||||||
PrintError(rs, kCantWriteMessage);
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outSize < outProcessed)
|
|
||||||
outSizeHigh--;
|
|
||||||
outSize -= (UInt32)outProcessed;
|
|
||||||
outSize &= 0xFFFFFFFF;
|
|
||||||
|
|
||||||
if (outProcessed == 0)
|
|
||||||
{
|
|
||||||
if (!waitEOS && (outSize != 0 || outSizeHigh != 0))
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
SizeT inProcessed;
|
|
||||||
#endif
|
|
||||||
SizeT outProcessed;
|
|
||||||
res = LzmaDecode(&state,
|
|
||||||
#ifdef _LZMA_IN_CB
|
|
||||||
&g_InBuffer.InCallback,
|
|
||||||
#else
|
|
||||||
inStream, compressedSize, &inProcessed,
|
|
||||||
#endif
|
|
||||||
outStream, outSizeFull, &outProcessed);
|
|
||||||
if (res != 0)
|
|
||||||
{
|
|
||||||
sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res);
|
|
||||||
res = 1;
|
|
||||||
}
|
|
||||||
else if (outFile != 0)
|
|
||||||
{
|
|
||||||
if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed))
|
|
||||||
{
|
|
||||||
PrintError(rs, kCantWriteMessage);
|
|
||||||
res = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
free(state.Probs);
|
|
||||||
#ifdef _LZMA_OUT_READ
|
|
||||||
free(state.Dictionary);
|
|
||||||
#else
|
|
||||||
free(outStream);
|
|
||||||
#endif
|
|
||||||
#ifndef _LZMA_IN_CB
|
|
||||||
free(inStream);
|
|
||||||
#endif
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main2(int numArgs, const char *args[], char *rs)
|
|
||||||
{
|
|
||||||
FILE *inFile = 0;
|
|
||||||
FILE *outFile = 0;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n");
|
|
||||||
if (numArgs < 2 || numArgs > 3)
|
|
||||||
{
|
|
||||||
sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inFile = fopen(args[1], "rb");
|
|
||||||
if (inFile == 0)
|
|
||||||
return PrintError(rs, "Can not open input file");
|
|
||||||
|
|
||||||
if (numArgs > 2)
|
|
||||||
{
|
|
||||||
outFile = fopen(args[2], "wb+");
|
|
||||||
if (outFile == 0)
|
|
||||||
return PrintError(rs, "Can not open output file");
|
|
||||||
}
|
|
||||||
|
|
||||||
res = main3(inFile, outFile, rs);
|
|
||||||
|
|
||||||
if (outFile != 0)
|
|
||||||
fclose(outFile);
|
|
||||||
fclose(inFile);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int numArgs, const char *args[])
|
|
||||||
{
|
|
||||||
char rs[800] = { 0 };
|
|
||||||
int res = main2(numArgs, args, rs);
|
|
||||||
printf(rs);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user