Update PhysFS to 3.0.0.

This commit is contained in:
Alex Szpakowski
2017-10-09 16:08:39 -03:00
parent dae4a76a14
commit 63d7f9904d
568 changed files with 27483 additions and 93570 deletions
+1 -1
View File
@@ -139,7 +139,7 @@ endif()
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_LUAJIT_VER "2.0.5")
set(MEGA_LIBOGG_VER "1.3.2")
-5
View File
@@ -1,5 +0,0 @@
repo: 7672c9962ce627edaaa67ff54fe4ad8f9a46dc2b
node: f94eec5e90540889a42c34a27931b8266f4af52c
branch: stable-2.0
latesttag: release-2.0.3
latesttagdistance: 1
-411
View File
@@ -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 ...
-153
View File
@@ -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)
-45
View File
@@ -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 ...
-283
View File
@@ -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 ... */
-475
View File
@@ -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 ... */
-514
View File
@@ -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 ... */
-736
View File
@@ -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 ... */
-471
View File
@@ -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 ... */
-633
View File
@@ -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 ... */
-531
View File
@@ -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>
-159
View File
@@ -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 ... */
-89
View File
@@ -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
-237
View File
@@ -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
-471
View File
@@ -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
-32
View File
@@ -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;
}
-21
View File
@@ -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
-40
View File
@@ -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;
}
-119
View File
@@ -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
-29
View File
@@ -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