mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-22 17:49:43 +01:00
Migrate PhysFS to submodule
This means we are no longer copy-pasting PhysFS source files directly. Since the source files reside in a src/ subdirectory, the paths in the CMakeLists.txt have to be adjusted.
This commit is contained in:
parent
7a0d3046a5
commit
7a4dff2d75
23 changed files with 16 additions and 16739 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +1,6 @@
|
||||||
[submodule "third_party/lodepng"]
|
[submodule "third_party/lodepng"]
|
||||||
path = third_party/lodepng
|
path = third_party/lodepng
|
||||||
url = https://github.com/lvandeve/lodepng
|
url = https://github.com/lvandeve/lodepng
|
||||||
|
[submodule "third_party/physfs"]
|
||||||
|
path = third_party/physfs
|
||||||
|
url = https://github.com/icculus/physfs/
|
||||||
|
|
|
@ -141,7 +141,7 @@ if(BUNDLE_DEPENDENCIES)
|
||||||
VVVVVV PRIVATE
|
VVVVVV PRIVATE
|
||||||
src
|
src
|
||||||
../third_party/tinyxml2
|
../third_party/tinyxml2
|
||||||
../third_party/physfs
|
../third_party/physfs/src
|
||||||
../third_party/physfs/extras
|
../third_party/physfs/extras
|
||||||
../third_party/lodepng
|
../third_party/lodepng
|
||||||
../third_party/utfcpp/source
|
../third_party/utfcpp/source
|
||||||
|
@ -170,20 +170,20 @@ set(XML2_SRC
|
||||||
../third_party/tinyxml2/tinyxml2.cpp
|
../third_party/tinyxml2/tinyxml2.cpp
|
||||||
)
|
)
|
||||||
set(PFS_SRC
|
set(PFS_SRC
|
||||||
../third_party/physfs/physfs.c
|
../third_party/physfs/src/physfs.c
|
||||||
../third_party/physfs/physfs_archiver_dir.c
|
../third_party/physfs/src/physfs_archiver_dir.c
|
||||||
../third_party/physfs/physfs_archiver_unpacked.c
|
../third_party/physfs/src/physfs_archiver_unpacked.c
|
||||||
../third_party/physfs/physfs_archiver_zip.c
|
../third_party/physfs/src/physfs_archiver_zip.c
|
||||||
../third_party/physfs/physfs_byteorder.c
|
../third_party/physfs/src/physfs_byteorder.c
|
||||||
../third_party/physfs/physfs_unicode.c
|
../third_party/physfs/src/physfs_unicode.c
|
||||||
../third_party/physfs/physfs_platform_posix.c
|
../third_party/physfs/src/physfs_platform_posix.c
|
||||||
../third_party/physfs/physfs_platform_unix.c
|
../third_party/physfs/src/physfs_platform_unix.c
|
||||||
../third_party/physfs/physfs_platform_windows.c
|
../third_party/physfs/src/physfs_platform_windows.c
|
||||||
../third_party/physfs/physfs_platform_haiku.cpp
|
../third_party/physfs/src/physfs_platform_haiku.cpp
|
||||||
)
|
)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
# Are you noticing a pattern with this Apple crap yet?
|
# Are you noticing a pattern with this Apple crap yet?
|
||||||
set(PFS_SRC ${PFS_SRC} ../third_party/physfs/physfs_platform_apple.m)
|
set(PFS_SRC ${PFS_SRC} ../third_party/physfs/src/physfs_platform_apple.m)
|
||||||
endif()
|
endif()
|
||||||
set(PNG_SRC src/lodepng_wrapper.c)
|
set(PNG_SRC src/lodepng_wrapper.c)
|
||||||
|
|
||||||
|
|
1
third_party/physfs
vendored
Submodule
1
third_party/physfs
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit a0dfe220ffb97eef2c78fef2b8971995f221b18d
|
23
third_party/physfs/LICENSE.txt
vendored
23
third_party/physfs/LICENSE.txt
vendored
|
@ -1,23 +0,0 @@
|
||||||
|
|
||||||
Copyright (c) 2001-2019 Ryan C. Gordon and others.
|
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied warranty.
|
|
||||||
In no event will the authors be held liable for any damages arising from
|
|
||||||
the use of this software.
|
|
||||||
|
|
||||||
Permission is granted to anyone to use this software for any purpose,
|
|
||||||
including commercial applications, and to alter it and redistribute it
|
|
||||||
freely, subject to the following restrictions:
|
|
||||||
|
|
||||||
1. The origin of this software must not be misrepresented; you must not
|
|
||||||
claim that you wrote the original software. If you use this software in a
|
|
||||||
product, an acknowledgment in the product documentation would be
|
|
||||||
appreciated but is not required.
|
|
||||||
|
|
||||||
2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
misrepresented as being the original software.
|
|
||||||
|
|
||||||
3. This notice may not be removed or altered from any source distribution.
|
|
||||||
|
|
||||||
Ryan C. Gordon <icculus@icculus.org>
|
|
||||||
|
|
9
third_party/physfs/README.txt
vendored
9
third_party/physfs/README.txt
vendored
|
@ -1,9 +0,0 @@
|
||||||
|
|
||||||
PhysicsFS; a portable, flexible file i/o abstraction.
|
|
||||||
|
|
||||||
https://icculus.org/physfs/
|
|
||||||
|
|
||||||
Please see the docs directory for documentation.
|
|
||||||
|
|
||||||
Please see LICENSE.txt for licensing information.
|
|
||||||
|
|
251
third_party/physfs/extras/physfsrwops.c
vendored
251
third_party/physfs/extras/physfsrwops.c
vendored
|
@ -1,251 +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. 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.
|
|
||||||
*
|
|
||||||
* SDL 1.2 falls under the LGPL license. SDL 1.3+ is zlib, like PhysicsFS.
|
|
||||||
* You can get SDL at https://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"
|
|
||||||
|
|
||||||
/* SDL's RWOPS interface changed a little in SDL 2.0... */
|
|
||||||
#if defined(SDL_VERSION_ATLEAST)
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
#define TARGET_SDL2 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !TARGET_SDL2
|
|
||||||
#ifndef RW_SEEK_SET
|
|
||||||
#define RW_SEEK_SET SEEK_SET
|
|
||||||
#endif
|
|
||||||
#ifndef RW_SEEK_CUR
|
|
||||||
#define RW_SEEK_CUR SEEK_CUR
|
|
||||||
#endif
|
|
||||||
#ifndef RW_SEEK_END
|
|
||||||
#define RW_SEEK_END SEEK_END
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TARGET_SDL2
|
|
||||||
static Sint64 SDLCALL physfsrwops_size(struct SDL_RWops *rw)
|
|
||||||
{
|
|
||||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
|
||||||
return (Sint64) PHYSFS_fileLength(handle);
|
|
||||||
} /* physfsrwops_size */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if TARGET_SDL2
|
|
||||||
static Sint64 SDLCALL physfsrwops_seek(struct SDL_RWops *rw, Sint64 offset, int whence)
|
|
||||||
#else
|
|
||||||
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
|
||||||
PHYSFS_sint64 pos = 0;
|
|
||||||
|
|
||||||
if (whence == RW_SEEK_SET)
|
|
||||||
pos = (PHYSFS_sint64) offset;
|
|
||||||
|
|
||||||
else if (whence == RW_SEEK_CUR)
|
|
||||||
{
|
|
||||||
const PHYSFS_sint64 current = PHYSFS_tell(handle);
|
|
||||||
if (current == -1)
|
|
||||||
{
|
|
||||||
SDL_SetError("Can't find position in file: %s",
|
|
||||||
PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
|
||||||
return -1;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (offset == 0) /* this is a "tell" call. We're done. */
|
|
||||||
{
|
|
||||||
#if TARGET_SDL2
|
|
||||||
return (Sint64) current;
|
|
||||||
#else
|
|
||||||
return (int) current;
|
|
||||||
#endif
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
pos = current + ((PHYSFS_sint64) offset);
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else if (whence == RW_SEEK_END)
|
|
||||||
{
|
|
||||||
const PHYSFS_sint64 len = PHYSFS_fileLength(handle);
|
|
||||||
if (len == -1)
|
|
||||||
{
|
|
||||||
SDL_SetError("Can't find end of file: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
|
||||||
return -1;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
pos = len + ((PHYSFS_sint64) 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_getErrorByCode(PHYSFS_getLastErrorCode()));
|
|
||||||
return -1;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
#if TARGET_SDL2
|
|
||||||
return (Sint64) pos;
|
|
||||||
#else
|
|
||||||
return (int) pos;
|
|
||||||
#endif
|
|
||||||
} /* physfsrwops_seek */
|
|
||||||
|
|
||||||
|
|
||||||
#if TARGET_SDL2
|
|
||||||
static size_t SDLCALL physfsrwops_read(struct SDL_RWops *rw, void *ptr,
|
|
||||||
size_t size, size_t maxnum)
|
|
||||||
#else
|
|
||||||
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
|
||||||
const PHYSFS_uint64 readlen = (PHYSFS_uint64) (maxnum * size);
|
|
||||||
const PHYSFS_sint64 rc = PHYSFS_readBytes(handle, ptr, readlen);
|
|
||||||
if (rc != ((PHYSFS_sint64) readlen))
|
|
||||||
{
|
|
||||||
if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
|
|
||||||
{
|
|
||||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
|
||||||
|
|
||||||
#if TARGET_SDL2
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
#if TARGET_SDL2
|
|
||||||
return (size_t) rc / size;
|
|
||||||
#else
|
|
||||||
return (int) rc / size;
|
|
||||||
#endif
|
|
||||||
} /* physfsrwops_read */
|
|
||||||
|
|
||||||
|
|
||||||
#if TARGET_SDL2
|
|
||||||
static size_t SDLCALL physfsrwops_write(struct SDL_RWops *rw, const void *ptr,
|
|
||||||
size_t size, size_t num)
|
|
||||||
#else
|
|
||||||
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
|
||||||
const PHYSFS_uint64 writelen = (PHYSFS_uint64) (num * size);
|
|
||||||
const PHYSFS_sint64 rc = PHYSFS_writeBytes(handle, ptr, writelen);
|
|
||||||
if (rc != ((PHYSFS_sint64) writelen))
|
|
||||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
|
||||||
|
|
||||||
#if TARGET_SDL2
|
|
||||||
return (size_t) rc;
|
|
||||||
#else
|
|
||||||
return (int) rc;
|
|
||||||
#endif
|
|
||||||
} /* 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_getErrorByCode(PHYSFS_getLastErrorCode()));
|
|
||||||
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_getErrorByCode(PHYSFS_getLastErrorCode()));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retval = SDL_AllocRW();
|
|
||||||
if (retval != NULL)
|
|
||||||
{
|
|
||||||
#if TARGET_SDL2
|
|
||||||
retval->size = physfsrwops_size;
|
|
||||||
#endif
|
|
||||||
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 ... */
|
|
||||||
|
|
89
third_party/physfs/extras/physfsrwops.h
vendored
89
third_party/physfs/extras/physfsrwops.h
vendored
|
@ -1,89 +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. 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.
|
|
||||||
*
|
|
||||||
* SDL 1.2 falls under the LGPL license. SDL 1.3+ is zlib, like PhysicsFS.
|
|
||||||
* You can get SDL at https://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().
|
|
||||||
*/
|
|
||||||
PHYSFS_DECL 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().
|
|
||||||
*/
|
|
||||||
PHYSFS_DECL 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().
|
|
||||||
*/
|
|
||||||
PHYSFS_DECL 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().
|
|
||||||
*/
|
|
||||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* include-once blocker */
|
|
||||||
|
|
||||||
/* end of physfsrwops.h ... */
|
|
||||||
|
|
3318
third_party/physfs/physfs.c
vendored
3318
third_party/physfs/physfs.c
vendored
File diff suppressed because it is too large
Load diff
3854
third_party/physfs/physfs.h
vendored
3854
third_party/physfs/physfs.h
vendored
File diff suppressed because it is too large
Load diff
196
third_party/physfs/physfs_archiver_dir.c
vendored
196
third_party/physfs/physfs_archiver_dir.c
vendored
|
@ -1,196 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
/* There's no PHYSFS_Io interface here. Use __PHYSFS_createNativeIo(). */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static char *cvtToDependent(const char *prepend, const char *path,
|
|
||||||
char *buf, const size_t buflen)
|
|
||||||
{
|
|
||||||
BAIL_IF(buf == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
snprintf(buf, buflen, "%s%s", prepend ? prepend : "", path);
|
|
||||||
|
|
||||||
#if !__PHYSFS_STANDARD_DIRSEP
|
|
||||||
assert(__PHYSFS_platformDirSeparator != '/');
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
for (p = strchr(buf, '/'); p != NULL; p = strchr(p + 1, '/'))
|
|
||||||
*p = __PHYSFS_platformDirSeparator;
|
|
||||||
} /* if */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
} /* cvtToDependent */
|
|
||||||
|
|
||||||
|
|
||||||
#define CVT_TO_DEPENDENT(buf, pre, dir) { \
|
|
||||||
const size_t len = ((pre) ? strlen((char *) pre) : 0) + strlen(dir) + 1; \
|
|
||||||
buf = cvtToDependent((char*)pre,dir,(char*)__PHYSFS_smallAlloc(len),len); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void *DIR_openArchive(PHYSFS_Io *io, const char *name,
|
|
||||||
int forWriting, int *claimed)
|
|
||||||
{
|
|
||||||
PHYSFS_Stat st;
|
|
||||||
const char dirsep = __PHYSFS_platformDirSeparator;
|
|
||||||
char *retval = NULL;
|
|
||||||
const size_t namelen = strlen(name);
|
|
||||||
const size_t seplen = 1;
|
|
||||||
|
|
||||||
assert(io == NULL); /* shouldn't create an Io for these. */
|
|
||||||
BAIL_IF_ERRPASS(!__PHYSFS_platformStat(name, &st, 1), NULL);
|
|
||||||
|
|
||||||
if (st.filetype != PHYSFS_FILETYPE_DIRECTORY)
|
|
||||||
BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
|
|
||||||
|
|
||||||
*claimed = 1;
|
|
||||||
retval = allocator.Malloc(namelen + seplen + 1);
|
|
||||||
BAIL_IF(retval == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
|
|
||||||
strcpy(retval, name);
|
|
||||||
|
|
||||||
/* make sure there's a dir separator at the end of the string */
|
|
||||||
if (retval[namelen - 1] != dirsep)
|
|
||||||
{
|
|
||||||
retval[namelen] = dirsep;
|
|
||||||
retval[namelen + 1] = '\0';
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
} /* DIR_openArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_EnumerateCallbackResult DIR_enumerate(void *opaque,
|
|
||||||
const char *dname, PHYSFS_EnumerateCallback cb,
|
|
||||||
const char *origdir, void *callbackdata)
|
|
||||||
{
|
|
||||||
char *d;
|
|
||||||
PHYSFS_EnumerateCallbackResult retval;
|
|
||||||
CVT_TO_DEPENDENT(d, opaque, dname);
|
|
||||||
BAIL_IF_ERRPASS(!d, PHYSFS_ENUM_ERROR);
|
|
||||||
retval = __PHYSFS_platformEnumerate(d, cb, origdir, callbackdata);
|
|
||||||
__PHYSFS_smallFree(d);
|
|
||||||
return retval;
|
|
||||||
} /* DIR_enumerate */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_Io *doOpen(void *opaque, const char *name, const int mode)
|
|
||||||
{
|
|
||||||
PHYSFS_Io *io = NULL;
|
|
||||||
char *f = NULL;
|
|
||||||
|
|
||||||
CVT_TO_DEPENDENT(f, opaque, name);
|
|
||||||
BAIL_IF_ERRPASS(!f, NULL);
|
|
||||||
|
|
||||||
io = __PHYSFS_createNativeIo(f, mode);
|
|
||||||
if (io == NULL)
|
|
||||||
{
|
|
||||||
const PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode();
|
|
||||||
PHYSFS_Stat statbuf;
|
|
||||||
__PHYSFS_platformStat(f, &statbuf, 0); /* !!! FIXME: why are we stating here? */
|
|
||||||
PHYSFS_setErrorCode(err);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
__PHYSFS_smallFree(f);
|
|
||||||
|
|
||||||
return io;
|
|
||||||
} /* doOpen */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_Io *DIR_openRead(void *opaque, const char *filename)
|
|
||||||
{
|
|
||||||
return doOpen(opaque, filename, 'r');
|
|
||||||
} /* DIR_openRead */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_Io *DIR_openWrite(void *opaque, const char *filename)
|
|
||||||
{
|
|
||||||
return doOpen(opaque, filename, 'w');
|
|
||||||
} /* DIR_openWrite */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_Io *DIR_openAppend(void *opaque, const char *filename)
|
|
||||||
{
|
|
||||||
return doOpen(opaque, filename, 'a');
|
|
||||||
} /* DIR_openAppend */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_remove(void *opaque, const char *name)
|
|
||||||
{
|
|
||||||
int retval;
|
|
||||||
char *f;
|
|
||||||
|
|
||||||
CVT_TO_DEPENDENT(f, opaque, name);
|
|
||||||
BAIL_IF_ERRPASS(!f, 0);
|
|
||||||
retval = __PHYSFS_platformDelete(f);
|
|
||||||
__PHYSFS_smallFree(f);
|
|
||||||
return retval;
|
|
||||||
} /* DIR_remove */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_mkdir(void *opaque, const char *name)
|
|
||||||
{
|
|
||||||
int retval;
|
|
||||||
char *f;
|
|
||||||
|
|
||||||
CVT_TO_DEPENDENT(f, opaque, name);
|
|
||||||
BAIL_IF_ERRPASS(!f, 0);
|
|
||||||
retval = __PHYSFS_platformMkDir(f);
|
|
||||||
__PHYSFS_smallFree(f);
|
|
||||||
return retval;
|
|
||||||
} /* DIR_mkdir */
|
|
||||||
|
|
||||||
|
|
||||||
static void DIR_closeArchive(void *opaque)
|
|
||||||
{
|
|
||||||
allocator.Free(opaque);
|
|
||||||
} /* DIR_closeArchive */
|
|
||||||
|
|
||||||
|
|
||||||
static int DIR_stat(void *opaque, const char *name, PHYSFS_Stat *stat)
|
|
||||||
{
|
|
||||||
int retval = 0;
|
|
||||||
char *d;
|
|
||||||
|
|
||||||
CVT_TO_DEPENDENT(d, opaque, name);
|
|
||||||
BAIL_IF_ERRPASS(!d, 0);
|
|
||||||
retval = __PHYSFS_platformStat(d, stat, 0);
|
|
||||||
__PHYSFS_smallFree(d);
|
|
||||||
return retval;
|
|
||||||
} /* DIR_stat */
|
|
||||||
|
|
||||||
|
|
||||||
const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
|
|
||||||
{
|
|
||||||
CURRENT_PHYSFS_ARCHIVER_API_VERSION,
|
|
||||||
{
|
|
||||||
"",
|
|
||||||
"Non-archive, direct filesystem I/O",
|
|
||||||
"Ryan C. Gordon <icculus@icculus.org>",
|
|
||||||
"https://icculus.org/physfs/",
|
|
||||||
1, /* supportsSymlinks */
|
|
||||||
},
|
|
||||||
DIR_openArchive,
|
|
||||||
DIR_enumerate,
|
|
||||||
DIR_openRead,
|
|
||||||
DIR_openWrite,
|
|
||||||
DIR_openAppend,
|
|
||||||
DIR_remove,
|
|
||||||
DIR_mkdir,
|
|
||||||
DIR_stat,
|
|
||||||
DIR_closeArchive
|
|
||||||
};
|
|
||||||
|
|
||||||
/* end of physfs_archiver_dir.c ... */
|
|
||||||
|
|
305
third_party/physfs/physfs_archiver_unpacked.c
vendored
305
third_party/physfs/physfs_archiver_unpacked.c
vendored
|
@ -1,305 +0,0 @@
|
||||||
/*
|
|
||||||
* High-level PhysicsFS archiver for simple unpacked file formats.
|
|
||||||
*
|
|
||||||
* This is a framework that basic archivers build on top of. It's for simple
|
|
||||||
* formats that can just hand back a list of files and the offsets of their
|
|
||||||
* uncompressed data. There are an alarming number of formats like this.
|
|
||||||
*
|
|
||||||
* RULES: Archive entries must be uncompressed. Dirs and files allowed, but no
|
|
||||||
* symlinks, etc. We can relax some of these rules as necessary.
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
__PHYSFS_DirTree tree;
|
|
||||||
PHYSFS_Io *io;
|
|
||||||
} UNPKinfo;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
__PHYSFS_DirTreeEntry tree;
|
|
||||||
PHYSFS_uint64 startPos;
|
|
||||||
PHYSFS_uint64 size;
|
|
||||||
PHYSFS_sint64 ctime;
|
|
||||||
PHYSFS_sint64 mtime;
|
|
||||||
} UNPKentry;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
PHYSFS_Io *io;
|
|
||||||
UNPKentry *entry;
|
|
||||||
PHYSFS_uint32 curPos;
|
|
||||||
} UNPKfileinfo;
|
|
||||||
|
|
||||||
|
|
||||||
void UNPK_closeArchive(void *opaque)
|
|
||||||
{
|
|
||||||
UNPKinfo *info = ((UNPKinfo *) opaque);
|
|
||||||
if (info)
|
|
||||||
{
|
|
||||||
__PHYSFS_DirTreeDeinit(&info->tree);
|
|
||||||
|
|
||||||
if (info->io)
|
|
||||||
info->io->destroy(info->io);
|
|
||||||
|
|
||||||
allocator.Free(info);
|
|
||||||
} /* if */
|
|
||||||
} /* UNPK_closeArchive */
|
|
||||||
|
|
||||||
void UNPK_abandonArchive(void *opaque)
|
|
||||||
{
|
|
||||||
UNPKinfo *info = ((UNPKinfo *) opaque);
|
|
||||||
if (info)
|
|
||||||
{
|
|
||||||
info->io = NULL;
|
|
||||||
UNPK_closeArchive(info);
|
|
||||||
} /* if */
|
|
||||||
} /* UNPK_abandonArchive */
|
|
||||||
|
|
||||||
static PHYSFS_sint64 UNPK_read(PHYSFS_Io *io, void *buffer, PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
UNPKfileinfo *finfo = (UNPKfileinfo *) io->opaque;
|
|
||||||
const UNPKentry *entry = finfo->entry;
|
|
||||||
const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos);
|
|
||||||
PHYSFS_sint64 rc;
|
|
||||||
|
|
||||||
if (bytesLeft < len)
|
|
||||||
len = bytesLeft;
|
|
||||||
|
|
||||||
rc = finfo->io->read(finfo->io, buffer, len);
|
|
||||||
if (rc > 0)
|
|
||||||
finfo->curPos += (PHYSFS_uint32) rc;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
} /* UNPK_read */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 UNPK_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
BAIL(PHYSFS_ERR_READ_ONLY, -1);
|
|
||||||
} /* UNPK_write */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 UNPK_tell(PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
return ((UNPKfileinfo *) io->opaque)->curPos;
|
|
||||||
} /* UNPK_tell */
|
|
||||||
|
|
||||||
|
|
||||||
static int UNPK_seek(PHYSFS_Io *io, PHYSFS_uint64 offset)
|
|
||||||
{
|
|
||||||
UNPKfileinfo *finfo = (UNPKfileinfo *) io->opaque;
|
|
||||||
const UNPKentry *entry = finfo->entry;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
BAIL_IF(offset >= entry->size, PHYSFS_ERR_PAST_EOF, 0);
|
|
||||||
rc = finfo->io->seek(finfo->io, entry->startPos + offset);
|
|
||||||
if (rc)
|
|
||||||
finfo->curPos = (PHYSFS_uint32) offset;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
} /* UNPK_seek */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_sint64 UNPK_length(PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
const UNPKfileinfo *finfo = (UNPKfileinfo *) io->opaque;
|
|
||||||
return ((PHYSFS_sint64) finfo->entry->size);
|
|
||||||
} /* UNPK_length */
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_Io *UNPK_duplicate(PHYSFS_Io *_io)
|
|
||||||
{
|
|
||||||
UNPKfileinfo *origfinfo = (UNPKfileinfo *) _io->opaque;
|
|
||||||
PHYSFS_Io *io = NULL;
|
|
||||||
PHYSFS_Io *retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
|
|
||||||
UNPKfileinfo *finfo = (UNPKfileinfo *) allocator.Malloc(sizeof (UNPKfileinfo));
|
|
||||||
GOTO_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, UNPK_duplicate_failed);
|
|
||||||
GOTO_IF(!finfo, PHYSFS_ERR_OUT_OF_MEMORY, UNPK_duplicate_failed);
|
|
||||||
|
|
||||||
io = origfinfo->io->duplicate(origfinfo->io);
|
|
||||||
if (!io) goto UNPK_duplicate_failed;
|
|
||||||
finfo->io = io;
|
|
||||||
finfo->entry = origfinfo->entry;
|
|
||||||
finfo->curPos = 0;
|
|
||||||
memcpy(retval, _io, sizeof (PHYSFS_Io));
|
|
||||||
retval->opaque = finfo;
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
UNPK_duplicate_failed:
|
|
||||||
if (finfo != NULL) allocator.Free(finfo);
|
|
||||||
if (retval != NULL) allocator.Free(retval);
|
|
||||||
if (io != NULL) io->destroy(io);
|
|
||||||
return NULL;
|
|
||||||
} /* UNPK_duplicate */
|
|
||||||
|
|
||||||
static int UNPK_flush(PHYSFS_Io *io) { return 1; /* no write support. */ }
|
|
||||||
|
|
||||||
static void UNPK_destroy(PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
UNPKfileinfo *finfo = (UNPKfileinfo *) io->opaque;
|
|
||||||
finfo->io->destroy(finfo->io);
|
|
||||||
allocator.Free(finfo);
|
|
||||||
allocator.Free(io);
|
|
||||||
} /* UNPK_destroy */
|
|
||||||
|
|
||||||
|
|
||||||
static const PHYSFS_Io UNPK_Io =
|
|
||||||
{
|
|
||||||
CURRENT_PHYSFS_IO_API_VERSION, NULL,
|
|
||||||
UNPK_read,
|
|
||||||
UNPK_write,
|
|
||||||
UNPK_seek,
|
|
||||||
UNPK_tell,
|
|
||||||
UNPK_length,
|
|
||||||
UNPK_duplicate,
|
|
||||||
UNPK_flush,
|
|
||||||
UNPK_destroy
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static inline UNPKentry *findEntry(UNPKinfo *info, const char *path)
|
|
||||||
{
|
|
||||||
return (UNPKentry *) __PHYSFS_DirTreeFind(&info->tree, path);
|
|
||||||
} /* findEntry */
|
|
||||||
|
|
||||||
|
|
||||||
PHYSFS_Io *UNPK_openRead(void *opaque, const char *name)
|
|
||||||
{
|
|
||||||
PHYSFS_Io *retval = NULL;
|
|
||||||
UNPKinfo *info = (UNPKinfo *) opaque;
|
|
||||||
UNPKfileinfo *finfo = NULL;
|
|
||||||
UNPKentry *entry = findEntry(info, name);
|
|
||||||
|
|
||||||
BAIL_IF_ERRPASS(!entry, NULL);
|
|
||||||
BAIL_IF(entry->tree.isdir, PHYSFS_ERR_NOT_A_FILE, NULL);
|
|
||||||
|
|
||||||
retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
|
|
||||||
GOTO_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, UNPK_openRead_failed);
|
|
||||||
|
|
||||||
finfo = (UNPKfileinfo *) allocator.Malloc(sizeof (UNPKfileinfo));
|
|
||||||
GOTO_IF(!finfo, PHYSFS_ERR_OUT_OF_MEMORY, UNPK_openRead_failed);
|
|
||||||
|
|
||||||
finfo->io = info->io->duplicate(info->io);
|
|
||||||
GOTO_IF_ERRPASS(!finfo->io, UNPK_openRead_failed);
|
|
||||||
|
|
||||||
if (!finfo->io->seek(finfo->io, entry->startPos))
|
|
||||||
goto UNPK_openRead_failed;
|
|
||||||
|
|
||||||
finfo->curPos = 0;
|
|
||||||
finfo->entry = entry;
|
|
||||||
|
|
||||||
memcpy(retval, &UNPK_Io, sizeof (*retval));
|
|
||||||
retval->opaque = finfo;
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
UNPK_openRead_failed:
|
|
||||||
if (finfo != NULL)
|
|
||||||
{
|
|
||||||
if (finfo->io != NULL)
|
|
||||||
finfo->io->destroy(finfo->io);
|
|
||||||
allocator.Free(finfo);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (retval != NULL)
|
|
||||||
allocator.Free(retval);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
} /* UNPK_openRead */
|
|
||||||
|
|
||||||
|
|
||||||
PHYSFS_Io *UNPK_openWrite(void *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL(PHYSFS_ERR_READ_ONLY, NULL);
|
|
||||||
} /* UNPK_openWrite */
|
|
||||||
|
|
||||||
|
|
||||||
PHYSFS_Io *UNPK_openAppend(void *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL(PHYSFS_ERR_READ_ONLY, NULL);
|
|
||||||
} /* UNPK_openAppend */
|
|
||||||
|
|
||||||
|
|
||||||
int UNPK_remove(void *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL(PHYSFS_ERR_READ_ONLY, 0);
|
|
||||||
} /* UNPK_remove */
|
|
||||||
|
|
||||||
|
|
||||||
int UNPK_mkdir(void *opaque, const char *name)
|
|
||||||
{
|
|
||||||
BAIL(PHYSFS_ERR_READ_ONLY, 0);
|
|
||||||
} /* UNPK_mkdir */
|
|
||||||
|
|
||||||
|
|
||||||
int UNPK_stat(void *opaque, const char *path, PHYSFS_Stat *stat)
|
|
||||||
{
|
|
||||||
UNPKinfo *info = (UNPKinfo *) opaque;
|
|
||||||
const UNPKentry *entry = findEntry(info, path);
|
|
||||||
|
|
||||||
BAIL_IF_ERRPASS(!entry, 0);
|
|
||||||
|
|
||||||
if (entry->tree.isdir)
|
|
||||||
{
|
|
||||||
stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
|
|
||||||
stat->filesize = 0;
|
|
||||||
} /* if */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stat->filetype = PHYSFS_FILETYPE_REGULAR;
|
|
||||||
stat->filesize = entry->size;
|
|
||||||
} /* else */
|
|
||||||
|
|
||||||
stat->modtime = entry->mtime;
|
|
||||||
stat->createtime = entry->ctime;
|
|
||||||
stat->accesstime = -1;
|
|
||||||
stat->readonly = 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
} /* UNPK_stat */
|
|
||||||
|
|
||||||
|
|
||||||
void *UNPK_addEntry(void *opaque, char *name, const int isdir,
|
|
||||||
const PHYSFS_sint64 ctime, const PHYSFS_sint64 mtime,
|
|
||||||
const PHYSFS_uint64 pos, const PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
UNPKinfo *info = (UNPKinfo *) opaque;
|
|
||||||
UNPKentry *entry;
|
|
||||||
|
|
||||||
entry = (UNPKentry *) __PHYSFS_DirTreeAdd(&info->tree, name, isdir);
|
|
||||||
BAIL_IF_ERRPASS(!entry, NULL);
|
|
||||||
|
|
||||||
entry->startPos = isdir ? 0 : pos;
|
|
||||||
entry->size = isdir ? 0 : len;
|
|
||||||
entry->ctime = ctime;
|
|
||||||
entry->mtime = mtime;
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
} /* UNPK_addEntry */
|
|
||||||
|
|
||||||
|
|
||||||
void *UNPK_openArchive(PHYSFS_Io *io)
|
|
||||||
{
|
|
||||||
UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo));
|
|
||||||
BAIL_IF(!info, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
|
|
||||||
if (!__PHYSFS_DirTreeInit(&info->tree, sizeof (UNPKentry)))
|
|
||||||
{
|
|
||||||
allocator.Free(info);
|
|
||||||
return NULL;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
info->io = io;
|
|
||||||
|
|
||||||
return info;
|
|
||||||
} /* UNPK_openArchive */
|
|
||||||
|
|
||||||
/* end of physfs_archiver_unpacked.c ... */
|
|
||||||
|
|
1710
third_party/physfs/physfs_archiver_zip.c
vendored
1710
third_party/physfs/physfs_archiver_zip.c
vendored
File diff suppressed because it is too large
Load diff
137
third_party/physfs/physfs_byteorder.c
vendored
137
third_party/physfs/physfs_byteorder.c
vendored
|
@ -1,137 +0,0 @@
|
||||||
/**
|
|
||||||
* PhysicsFS; a portable, flexible file i/o abstraction.
|
|
||||||
*
|
|
||||||
* Documentation is in physfs.h. It's verbose, honest. :)
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
#ifndef PHYSFS_Swap16
|
|
||||||
static inline PHYSFS_uint16 PHYSFS_Swap16(PHYSFS_uint16 D)
|
|
||||||
{
|
|
||||||
return ((D<<8)|(D>>8));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_Swap32
|
|
||||||
static inline PHYSFS_uint32 PHYSFS_Swap32(PHYSFS_uint32 D)
|
|
||||||
{
|
|
||||||
return ((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_NO_64BIT_SUPPORT
|
|
||||||
#ifndef PHYSFS_Swap64
|
|
||||||
static inline PHYSFS_uint64 PHYSFS_Swap64(PHYSFS_uint64 val) {
|
|
||||||
PHYSFS_uint32 hi, lo;
|
|
||||||
|
|
||||||
/* Separate into high and low 32-bit values and swap them */
|
|
||||||
lo = (PHYSFS_uint32)(val&0xFFFFFFFF);
|
|
||||||
val >>= 32;
|
|
||||||
hi = (PHYSFS_uint32)(val&0xFFFFFFFF);
|
|
||||||
val = PHYSFS_Swap32(lo);
|
|
||||||
val <<= 32;
|
|
||||||
val |= PHYSFS_Swap32(hi);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifndef PHYSFS_Swap64
|
|
||||||
/* This is mainly to keep compilers from complaining in PHYSFS code.
|
|
||||||
If there is no real 64-bit datatype, then compilers will complain about
|
|
||||||
the fake 64-bit datatype that PHYSFS provides when it compiles user code.
|
|
||||||
*/
|
|
||||||
#define PHYSFS_Swap64(X) (X)
|
|
||||||
#endif
|
|
||||||
#endif /* PHYSFS_NO_64BIT_SUPPORT */
|
|
||||||
|
|
||||||
|
|
||||||
/* Byteswap item from the specified endianness to the native endianness */
|
|
||||||
#if PHYSFS_BYTEORDER == PHYSFS_LIL_ENDIAN
|
|
||||||
PHYSFS_uint16 PHYSFS_swapULE16(PHYSFS_uint16 x) { return x; }
|
|
||||||
PHYSFS_sint16 PHYSFS_swapSLE16(PHYSFS_sint16 x) { return x; }
|
|
||||||
PHYSFS_uint32 PHYSFS_swapULE32(PHYSFS_uint32 x) { return x; }
|
|
||||||
PHYSFS_sint32 PHYSFS_swapSLE32(PHYSFS_sint32 x) { return x; }
|
|
||||||
PHYSFS_uint64 PHYSFS_swapULE64(PHYSFS_uint64 x) { return x; }
|
|
||||||
PHYSFS_sint64 PHYSFS_swapSLE64(PHYSFS_sint64 x) { return x; }
|
|
||||||
|
|
||||||
PHYSFS_uint16 PHYSFS_swapUBE16(PHYSFS_uint16 x) { return PHYSFS_Swap16(x); }
|
|
||||||
PHYSFS_sint16 PHYSFS_swapSBE16(PHYSFS_sint16 x) { return PHYSFS_Swap16(x); }
|
|
||||||
PHYSFS_uint32 PHYSFS_swapUBE32(PHYSFS_uint32 x) { return PHYSFS_Swap32(x); }
|
|
||||||
PHYSFS_sint32 PHYSFS_swapSBE32(PHYSFS_sint32 x) { return PHYSFS_Swap32(x); }
|
|
||||||
PHYSFS_uint64 PHYSFS_swapUBE64(PHYSFS_uint64 x) { return PHYSFS_Swap64(x); }
|
|
||||||
PHYSFS_sint64 PHYSFS_swapSBE64(PHYSFS_sint64 x) { return PHYSFS_Swap64(x); }
|
|
||||||
#else
|
|
||||||
PHYSFS_uint16 PHYSFS_swapULE16(PHYSFS_uint16 x) { return PHYSFS_Swap16(x); }
|
|
||||||
PHYSFS_sint16 PHYSFS_swapSLE16(PHYSFS_sint16 x) { return PHYSFS_Swap16(x); }
|
|
||||||
PHYSFS_uint32 PHYSFS_swapULE32(PHYSFS_uint32 x) { return PHYSFS_Swap32(x); }
|
|
||||||
PHYSFS_sint32 PHYSFS_swapSLE32(PHYSFS_sint32 x) { return PHYSFS_Swap32(x); }
|
|
||||||
PHYSFS_uint64 PHYSFS_swapULE64(PHYSFS_uint64 x) { return PHYSFS_Swap64(x); }
|
|
||||||
PHYSFS_sint64 PHYSFS_swapSLE64(PHYSFS_sint64 x) { return PHYSFS_Swap64(x); }
|
|
||||||
|
|
||||||
PHYSFS_uint16 PHYSFS_swapUBE16(PHYSFS_uint16 x) { return x; }
|
|
||||||
PHYSFS_sint16 PHYSFS_swapSBE16(PHYSFS_sint16 x) { return x; }
|
|
||||||
PHYSFS_uint32 PHYSFS_swapUBE32(PHYSFS_uint32 x) { return x; }
|
|
||||||
PHYSFS_sint32 PHYSFS_swapSBE32(PHYSFS_sint32 x) { return x; }
|
|
||||||
PHYSFS_uint64 PHYSFS_swapUBE64(PHYSFS_uint64 x) { return x; }
|
|
||||||
PHYSFS_sint64 PHYSFS_swapSBE64(PHYSFS_sint64 x) { return x; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline int readAll(PHYSFS_File *file, void *val, const size_t len)
|
|
||||||
{
|
|
||||||
return (PHYSFS_readBytes(file, val, len) == len);
|
|
||||||
} /* readAll */
|
|
||||||
|
|
||||||
#define PHYSFS_BYTEORDER_READ(datatype, swaptype) \
|
|
||||||
int PHYSFS_read##swaptype(PHYSFS_File *file, PHYSFS_##datatype *val) { \
|
|
||||||
PHYSFS_##datatype in; \
|
|
||||||
BAIL_IF(val == NULL, PHYSFS_ERR_INVALID_ARGUMENT, 0); \
|
|
||||||
BAIL_IF_ERRPASS(!readAll(file, &in, sizeof (in)), 0); \
|
|
||||||
*val = PHYSFS_swap##swaptype(in); \
|
|
||||||
return 1; \
|
|
||||||
}
|
|
||||||
|
|
||||||
PHYSFS_BYTEORDER_READ(sint16, SLE16)
|
|
||||||
PHYSFS_BYTEORDER_READ(uint16, ULE16)
|
|
||||||
PHYSFS_BYTEORDER_READ(sint16, SBE16)
|
|
||||||
PHYSFS_BYTEORDER_READ(uint16, UBE16)
|
|
||||||
PHYSFS_BYTEORDER_READ(sint32, SLE32)
|
|
||||||
PHYSFS_BYTEORDER_READ(uint32, ULE32)
|
|
||||||
PHYSFS_BYTEORDER_READ(sint32, SBE32)
|
|
||||||
PHYSFS_BYTEORDER_READ(uint32, UBE32)
|
|
||||||
PHYSFS_BYTEORDER_READ(sint64, SLE64)
|
|
||||||
PHYSFS_BYTEORDER_READ(uint64, ULE64)
|
|
||||||
PHYSFS_BYTEORDER_READ(sint64, SBE64)
|
|
||||||
PHYSFS_BYTEORDER_READ(uint64, UBE64)
|
|
||||||
|
|
||||||
|
|
||||||
static inline int writeAll(PHYSFS_File *f, const void *val, const size_t len)
|
|
||||||
{
|
|
||||||
return (PHYSFS_writeBytes(f, val, len) == len);
|
|
||||||
} /* writeAll */
|
|
||||||
|
|
||||||
#define PHYSFS_BYTEORDER_WRITE(datatype, swaptype) \
|
|
||||||
int PHYSFS_write##swaptype(PHYSFS_File *file, PHYSFS_##datatype val) { \
|
|
||||||
const PHYSFS_##datatype out = PHYSFS_swap##swaptype(val); \
|
|
||||||
BAIL_IF_ERRPASS(!writeAll(file, &out, sizeof (out)), 0); \
|
|
||||||
return 1; \
|
|
||||||
}
|
|
||||||
|
|
||||||
PHYSFS_BYTEORDER_WRITE(sint16, SLE16)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(uint16, ULE16)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(sint16, SBE16)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(uint16, UBE16)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(sint32, SLE32)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(uint32, ULE32)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(sint32, SBE32)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(uint32, UBE32)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(sint64, SLE64)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(uint64, ULE64)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(sint64, SBE64)
|
|
||||||
PHYSFS_BYTEORDER_WRITE(uint64, UBE64)
|
|
||||||
|
|
||||||
/* end of physfs_byteorder.c ... */
|
|
||||||
|
|
2572
third_party/physfs/physfs_casefolding.h
vendored
2572
third_party/physfs/physfs_casefolding.h
vendored
File diff suppressed because it is too large
Load diff
729
third_party/physfs/physfs_internal.h
vendored
729
third_party/physfs/physfs_internal.h
vendored
|
@ -1,729 +0,0 @@
|
||||||
/*
|
|
||||||
* Internal function/structure declaration. Do NOT include in your
|
|
||||||
* application.
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INCLUDE_PHYSFS_INTERNAL_H_
|
|
||||||
#define _INCLUDE_PHYSFS_INTERNAL_H_
|
|
||||||
|
|
||||||
#ifndef __PHYSICSFS_INTERNAL__
|
|
||||||
#error Do not include this header from your applications.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Turn off MSVC warnings that are aggressively anti-portability. */
|
|
||||||
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "physfs.h"
|
|
||||||
|
|
||||||
/* The holy trinity. */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "physfs_platforms.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#define __PHYSFS_COMPILE_TIME_ASSERT(name, x) \
|
|
||||||
typedef int __PHYSFS_compile_time_assert_##name[(x) * 2 - 1]
|
|
||||||
|
|
||||||
/* !!! FIXME: remove this when revamping stack allocation code... */
|
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__)
|
|
||||||
#include <malloc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PHYSFS_PLATFORM_SOLARIS
|
|
||||||
#include <alloca.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define PHYSFS_MINIMUM_GCC_VERSION(major, minor) \
|
|
||||||
( ((__GNUC__ << 16) + __GNUC_MINOR__) >= (((major) << 16) + (minor)) )
|
|
||||||
#else
|
|
||||||
#define PHYSFS_MINIMUM_GCC_VERSION(major, minor) (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
/* C++ always has a real inline keyword. */
|
|
||||||
#elif (defined macintosh) && !(defined __MWERKS__)
|
|
||||||
# define inline
|
|
||||||
#elif (defined _MSC_VER)
|
|
||||||
# define inline __inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PHYSFS_PLATFORM_LINUX) && !defined(_FILE_OFFSET_BITS)
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* All public APIs need to be in physfs.h with a PHYSFS_DECL.
|
|
||||||
All file-private symbols need to be marked "static".
|
|
||||||
Everything shared between PhysicsFS sources needs to be in this
|
|
||||||
file between the visibility pragma blocks. */
|
|
||||||
#if PHYSFS_MINIMUM_GCC_VERSION(4,0) || defined(__clang__)
|
|
||||||
#define PHYSFS_HAVE_PRAGMA_VISIBILITY 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PHYSFS_HAVE_PRAGMA_VISIBILITY
|
|
||||||
#pragma GCC visibility push(hidden)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* These are the build-in archivers. We list them all as "extern" here without
|
|
||||||
#ifdefs to keep it tidy, but obviously you need to make sure these are
|
|
||||||
wrapped in PHYSFS_SUPPORTS_* checks before actually referencing them. */
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_DIR;
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_ZIP;
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_7Z;
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_GRP;
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_QPAK;
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_HOG;
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_MVL;
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_WAD;
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_SLB;
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660;
|
|
||||||
extern const PHYSFS_Archiver __PHYSFS_Archiver_VDF;
|
|
||||||
|
|
||||||
/* a real C99-compliant snprintf() is in Visual Studio 2015,
|
|
||||||
but just use this everywhere for binary compatibility. */
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
int __PHYSFS_msvc_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap);
|
|
||||||
int __PHYSFS_msvc_snprintf(char *outBuf, size_t size, const char *format, ...);
|
|
||||||
#define vsnprintf __PHYSFS_msvc_vsnprintf
|
|
||||||
#define snprintf __PHYSFS_msvc_snprintf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Some simple wrappers around WinRT C++ interfaces we can call from C. */
|
|
||||||
#ifdef PHYSFS_PLATFORM_WINRT
|
|
||||||
const void *__PHYSFS_winrtCalcBaseDir(void);
|
|
||||||
const void *__PHYSFS_winrtCalcPrefDir(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* atomic operations. */
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
|
||||||
#include <intrin.h>
|
|
||||||
__PHYSFS_COMPILE_TIME_ASSERT(LongEqualsInt, sizeof (int) == sizeof (long));
|
|
||||||
#define __PHYSFS_ATOMIC_INCR(ptrval) _InterlockedIncrement((long*)(ptrval))
|
|
||||||
#define __PHYSFS_ATOMIC_DECR(ptrval) _InterlockedDecrement((long*)(ptrval))
|
|
||||||
#elif defined(__clang__) || (defined(__GNUC__) && (((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100)) >= 40100))
|
|
||||||
#define __PHYSFS_ATOMIC_INCR(ptrval) __sync_fetch_and_add(ptrval, 1)
|
|
||||||
#define __PHYSFS_ATOMIC_DECR(ptrval) __sync_fetch_and_add(ptrval, -1)
|
|
||||||
#else
|
|
||||||
#define PHYSFS_NEED_ATOMIC_OP_FALLBACK 1
|
|
||||||
int __PHYSFS_ATOMIC_INCR(int *ptrval);
|
|
||||||
int __PHYSFS_ATOMIC_DECR(int *ptrval);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Interface for small allocations. If you need a little scratch space for
|
|
||||||
* a throwaway buffer or string, use this. It will make small allocations
|
|
||||||
* on the stack if possible, and use allocator.Malloc() if they are too
|
|
||||||
* large. This helps reduce malloc pressure.
|
|
||||||
* There are some rules, though:
|
|
||||||
* NEVER return a pointer from this, as stack-allocated buffers go away
|
|
||||||
* when your function returns.
|
|
||||||
* NEVER allocate in a loop, as stack-allocated pointers will pile up. Call
|
|
||||||
* a function that uses smallAlloc from your loop, so the allocation can
|
|
||||||
* free each time.
|
|
||||||
* NEVER call smallAlloc with any complex expression (it's a macro that WILL
|
|
||||||
* have side effects...it references the argument multiple times). Use a
|
|
||||||
* variable or a literal.
|
|
||||||
* NEVER free a pointer from this with anything but smallFree. It will not
|
|
||||||
* be a valid pointer to the allocator, regardless of where the memory came
|
|
||||||
* from.
|
|
||||||
* NEVER realloc a pointer from this.
|
|
||||||
* NEVER forget to use smallFree: it may not be a pointer from the stack.
|
|
||||||
* NEVER forget to check for NULL...allocation can fail here, of course!
|
|
||||||
*/
|
|
||||||
#define __PHYSFS_SMALLALLOCTHRESHOLD 256
|
|
||||||
void *__PHYSFS_initSmallAlloc(void *ptr, const size_t len);
|
|
||||||
|
|
||||||
#define __PHYSFS_smallAlloc(bytes) ( \
|
|
||||||
__PHYSFS_initSmallAlloc( \
|
|
||||||
(((bytes) < __PHYSFS_SMALLALLOCTHRESHOLD) ? \
|
|
||||||
alloca((size_t)((bytes)+sizeof(void*))) : NULL), (bytes)) \
|
|
||||||
)
|
|
||||||
|
|
||||||
void __PHYSFS_smallFree(void *ptr);
|
|
||||||
|
|
||||||
|
|
||||||
/* Use the allocation hooks. */
|
|
||||||
#define malloc(x) Do not use malloc() directly.
|
|
||||||
#define realloc(x, y) Do not use realloc() directly.
|
|
||||||
#define free(x) Do not use free() directly.
|
|
||||||
/* !!! FIXME: add alloca check here. */
|
|
||||||
|
|
||||||
|
|
||||||
/* by default, enable things, so builds can opt out of a few things they
|
|
||||||
want to avoid. But you can build with this #defined to 0 if you would
|
|
||||||
like to turn off everything except a handful of things you opt into. */
|
|
||||||
#ifndef PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#define PHYSFS_SUPPORTS_DEFAULT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef PHYSFS_SUPPORTS_ZIP
|
|
||||||
#define PHYSFS_SUPPORTS_ZIP PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_SUPPORTS_7Z
|
|
||||||
#define PHYSFS_SUPPORTS_7Z PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_SUPPORTS_GRP
|
|
||||||
#define PHYSFS_SUPPORTS_GRP PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_SUPPORTS_HOG
|
|
||||||
#define PHYSFS_SUPPORTS_HOG PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_SUPPORTS_MVL
|
|
||||||
#define PHYSFS_SUPPORTS_MVL PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_SUPPORTS_WAD
|
|
||||||
#define PHYSFS_SUPPORTS_WAD PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_SUPPORTS_QPAK
|
|
||||||
#define PHYSFS_SUPPORTS_QPAK PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_SUPPORTS_SLB
|
|
||||||
#define PHYSFS_SUPPORTS_SLB PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_SUPPORTS_ISO9660
|
|
||||||
#define PHYSFS_SUPPORTS_ISO9660 PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#endif
|
|
||||||
#ifndef PHYSFS_SUPPORTS_VDF
|
|
||||||
#define PHYSFS_SUPPORTS_VDF PHYSFS_SUPPORTS_DEFAULT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PHYSFS_SUPPORTS_7Z
|
|
||||||
/* 7zip support needs a global init function called at startup (no deinit). */
|
|
||||||
extern void SZIP_global_init(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The latest supported PHYSFS_Io::version value. */
|
|
||||||
#define CURRENT_PHYSFS_IO_API_VERSION 0
|
|
||||||
|
|
||||||
/* The latest supported PHYSFS_Archiver::version value. */
|
|
||||||
#define CURRENT_PHYSFS_ARCHIVER_API_VERSION 0
|
|
||||||
|
|
||||||
/* This byteorder stuff was lifted from SDL. https://www.libsdl.org/ */
|
|
||||||
#define PHYSFS_LIL_ENDIAN 1234
|
|
||||||
#define PHYSFS_BIG_ENDIAN 4321
|
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
#include <endian.h>
|
|
||||||
#define PHYSFS_BYTEORDER __BYTE_ORDER
|
|
||||||
#else /* __linux__ */
|
|
||||||
#if defined(__hppa__) || \
|
|
||||||
defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
|
|
||||||
(defined(__MIPS__) && defined(__MISPEB__)) || \
|
|
||||||
defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
|
|
||||||
defined(__sparc__)
|
|
||||||
#define PHYSFS_BYTEORDER PHYSFS_BIG_ENDIAN
|
|
||||||
#else
|
|
||||||
#define PHYSFS_BYTEORDER PHYSFS_LIL_ENDIAN
|
|
||||||
#endif
|
|
||||||
#endif /* __linux__ */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When sorting the entries in an archive, we use a modified QuickSort.
|
|
||||||
* When there are less then PHYSFS_QUICKSORT_THRESHOLD entries left to sort,
|
|
||||||
* we switch over to a BubbleSort for the remainder. Tweak to taste.
|
|
||||||
*
|
|
||||||
* You can override this setting by defining PHYSFS_QUICKSORT_THRESHOLD
|
|
||||||
* before #including "physfs_internal.h".
|
|
||||||
*/
|
|
||||||
#ifndef PHYSFS_QUICKSORT_THRESHOLD
|
|
||||||
#define PHYSFS_QUICKSORT_THRESHOLD 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sort an array (or whatever) of (max) elements. This uses a mixture of
|
|
||||||
* a QuickSort and BubbleSort internally.
|
|
||||||
* (cmpfn) is used to determine ordering, and (swapfn) does the actual
|
|
||||||
* swapping of elements in the list.
|
|
||||||
*/
|
|
||||||
void __PHYSFS_sort(void *entries, size_t max,
|
|
||||||
int (*cmpfn)(void *, size_t, size_t),
|
|
||||||
void (*swapfn)(void *, size_t, size_t));
|
|
||||||
|
|
||||||
/* These get used all over for lessening code clutter. */
|
|
||||||
/* "ERRPASS" means "something else just set the error state for us" and is
|
|
||||||
just to make it clear where the responsibility for the error state lays. */
|
|
||||||
#define BAIL(e, r) do { if (e) PHYSFS_setErrorCode(e); return r; } while (0)
|
|
||||||
#define BAIL_ERRPASS(r) do { return r; } while (0)
|
|
||||||
#define BAIL_IF(c, e, r) do { if (c) { if (e) PHYSFS_setErrorCode(e); return r; } } while (0)
|
|
||||||
#define BAIL_IF_ERRPASS(c, r) do { if (c) { return r; } } while (0)
|
|
||||||
#define BAIL_MUTEX(e, m, r) do { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); return r; } while (0)
|
|
||||||
#define BAIL_MUTEX_ERRPASS(m, r) do { __PHYSFS_platformReleaseMutex(m); return r; } while (0)
|
|
||||||
#define BAIL_IF_MUTEX(c, e, m, r) do { if (c) { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); return r; } } while (0)
|
|
||||||
#define BAIL_IF_MUTEX_ERRPASS(c, m, r) do { if (c) { __PHYSFS_platformReleaseMutex(m); return r; } } while (0)
|
|
||||||
#define GOTO(e, g) do { if (e) PHYSFS_setErrorCode(e); goto g; } while (0)
|
|
||||||
#define GOTO_ERRPASS(g) do { goto g; } while (0)
|
|
||||||
#define GOTO_IF(c, e, g) do { if (c) { if (e) PHYSFS_setErrorCode(e); goto g; } } while (0)
|
|
||||||
#define GOTO_IF_ERRPASS(c, g) do { if (c) { goto g; } } while (0)
|
|
||||||
#define GOTO_MUTEX(e, m, g) do { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); goto g; } while (0)
|
|
||||||
#define GOTO_MUTEX_ERRPASS(m, g) do { __PHYSFS_platformReleaseMutex(m); goto g; } while (0)
|
|
||||||
#define GOTO_IF_MUTEX(c, e, m, g) do { if (c) { if (e) PHYSFS_setErrorCode(e); __PHYSFS_platformReleaseMutex(m); goto g; } } while (0)
|
|
||||||
#define GOTO_IF_MUTEX_ERRPASS(c, m, g) do { if (c) { __PHYSFS_platformReleaseMutex(m); goto g; } } while (0)
|
|
||||||
|
|
||||||
#define __PHYSFS_ARRAYLEN(x) ( (sizeof (x)) / (sizeof (x[0])) )
|
|
||||||
|
|
||||||
#ifdef PHYSFS_NO_64BIT_SUPPORT
|
|
||||||
#define __PHYSFS_SI64(x) ((PHYSFS_sint64) (x))
|
|
||||||
#define __PHYSFS_UI64(x) ((PHYSFS_uint64) (x))
|
|
||||||
#elif (defined __GNUC__)
|
|
||||||
#define __PHYSFS_SI64(x) x##LL
|
|
||||||
#define __PHYSFS_UI64(x) x##ULL
|
|
||||||
#elif (defined _MSC_VER)
|
|
||||||
#define __PHYSFS_SI64(x) x##i64
|
|
||||||
#define __PHYSFS_UI64(x) x##ui64
|
|
||||||
#else
|
|
||||||
#define __PHYSFS_SI64(x) ((PHYSFS_sint64) (x))
|
|
||||||
#define __PHYSFS_UI64(x) ((PHYSFS_uint64) (x))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if a ui64 will fit in the platform's address space.
|
|
||||||
* The initial sizeof check will optimize this macro out entirely on
|
|
||||||
* 64-bit (and larger?!) platforms, and the other condition will
|
|
||||||
* return zero or non-zero if the variable will fit in the platform's
|
|
||||||
* size_t, suitable to pass to malloc. This is kinda messy, but effective.
|
|
||||||
*/
|
|
||||||
#define __PHYSFS_ui64FitsAddressSpace(s) ( \
|
|
||||||
(sizeof (PHYSFS_uint64) <= sizeof (size_t)) || \
|
|
||||||
((s) < (__PHYSFS_UI64(0xFFFFFFFFFFFFFFFF) >> (64-(sizeof(size_t)*8)))) \
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Like strdup(), but uses the current PhysicsFS allocator.
|
|
||||||
*/
|
|
||||||
char *__PHYSFS_strdup(const char *str);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Give a hash value for a C string (uses djb's xor hashing algorithm).
|
|
||||||
*/
|
|
||||||
PHYSFS_uint32 __PHYSFS_hashString(const char *str, size_t len);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The current allocator. Not valid before PHYSFS_init is called!
|
|
||||||
*/
|
|
||||||
extern PHYSFS_Allocator __PHYSFS_AllocatorHooks;
|
|
||||||
|
|
||||||
/* convenience macro to make this less cumbersome internally... */
|
|
||||||
#define allocator __PHYSFS_AllocatorHooks
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a PHYSFS_Io for a file in the physical filesystem.
|
|
||||||
* This path is in platform-dependent notation. (mode) must be 'r', 'w', or
|
|
||||||
* 'a' for Read, Write, or Append.
|
|
||||||
*/
|
|
||||||
PHYSFS_Io *__PHYSFS_createNativeIo(const char *path, const int mode);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a PHYSFS_Io for a buffer of memory (READ-ONLY). If you already
|
|
||||||
* have one of these, just use its duplicate() method, and it'll increment
|
|
||||||
* its refcount without allocating a copy of the buffer.
|
|
||||||
*/
|
|
||||||
PHYSFS_Io *__PHYSFS_createMemoryIo(const void *buf, PHYSFS_uint64 len,
|
|
||||||
void (*destruct)(void *));
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read (len) bytes from (io) into (buf). Returns non-zero on success,
|
|
||||||
* zero on i/o error. Literally: "return (io->read(io, buf, len) == len);"
|
|
||||||
*/
|
|
||||||
int __PHYSFS_readAll(PHYSFS_Io *io, void *buf, const size_t len);
|
|
||||||
|
|
||||||
|
|
||||||
/* These are shared between some archivers. */
|
|
||||||
|
|
||||||
void UNPK_abandonArchive(void *opaque);
|
|
||||||
void UNPK_closeArchive(void *opaque);
|
|
||||||
void *UNPK_openArchive(PHYSFS_Io *io);
|
|
||||||
void *UNPK_addEntry(void *opaque, char *name, const int isdir,
|
|
||||||
const PHYSFS_sint64 ctime, const PHYSFS_sint64 mtime,
|
|
||||||
const PHYSFS_uint64 pos, const PHYSFS_uint64 len);
|
|
||||||
PHYSFS_Io *UNPK_openRead(void *opaque, const char *name);
|
|
||||||
PHYSFS_Io *UNPK_openWrite(void *opaque, const char *name);
|
|
||||||
PHYSFS_Io *UNPK_openAppend(void *opaque, const char *name);
|
|
||||||
int UNPK_remove(void *opaque, const char *name);
|
|
||||||
int UNPK_mkdir(void *opaque, const char *name);
|
|
||||||
int UNPK_stat(void *opaque, const char *fn, PHYSFS_Stat *st);
|
|
||||||
#define UNPK_enumerate __PHYSFS_DirTreeEnumerate
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Optional API many archivers use this to manage their directory tree. */
|
|
||||||
/* !!! FIXME: document this better. */
|
|
||||||
|
|
||||||
typedef struct __PHYSFS_DirTreeEntry
|
|
||||||
{
|
|
||||||
char *name; /* Full path in archive. */
|
|
||||||
struct __PHYSFS_DirTreeEntry *hashnext; /* next item in hash bucket. */
|
|
||||||
struct __PHYSFS_DirTreeEntry *children; /* linked list of kids, if dir. */
|
|
||||||
struct __PHYSFS_DirTreeEntry *sibling; /* next item in same dir. */
|
|
||||||
int isdir;
|
|
||||||
} __PHYSFS_DirTreeEntry;
|
|
||||||
|
|
||||||
typedef struct __PHYSFS_DirTree
|
|
||||||
{
|
|
||||||
__PHYSFS_DirTreeEntry *root; /* root of directory tree. */
|
|
||||||
__PHYSFS_DirTreeEntry **hash; /* all entries hashed for fast lookup. */
|
|
||||||
size_t hashBuckets; /* number of buckets in hash. */
|
|
||||||
size_t entrylen; /* size in bytes of entries (including subclass). */
|
|
||||||
} __PHYSFS_DirTree;
|
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen);
|
|
||||||
void *__PHYSFS_DirTreeAdd(__PHYSFS_DirTree *dt, char *name, const int isdir);
|
|
||||||
void *__PHYSFS_DirTreeFind(__PHYSFS_DirTree *dt, const char *path);
|
|
||||||
PHYSFS_EnumerateCallbackResult __PHYSFS_DirTreeEnumerate(void *opaque,
|
|
||||||
const char *dname, PHYSFS_EnumerateCallback cb,
|
|
||||||
const char *origdir, void *callbackdata);
|
|
||||||
void __PHYSFS_DirTreeDeinit(__PHYSFS_DirTree *dt);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
/*------------ ----------------*/
|
|
||||||
/*------------ You MUST implement the following functions ----------------*/
|
|
||||||
/*------------ if porting to a new platform. ----------------*/
|
|
||||||
/*------------ (see platform/unix.c for an example) ----------------*/
|
|
||||||
/*------------ ----------------*/
|
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The dir separator; '/' on unix, '\\' on win32, ":" on MacOS, etc...
|
|
||||||
* Obviously, this isn't a function. If you need more than one char for this,
|
|
||||||
* you'll need to pull some old pieces of PhysicsFS out of revision control.
|
|
||||||
*/
|
|
||||||
#if defined(PHYSFS_PLATFORM_WINDOWS) || defined(PHYSFS_PLATFORM_OS2)
|
|
||||||
#define __PHYSFS_platformDirSeparator '\\'
|
|
||||||
#else
|
|
||||||
#define __PHYSFS_STANDARD_DIRSEP 1
|
|
||||||
#define __PHYSFS_platformDirSeparator '/'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize the platform. This is called when PHYSFS_init() is called from
|
|
||||||
* the application.
|
|
||||||
*
|
|
||||||
* Return zero if there was a catastrophic failure (which prevents you from
|
|
||||||
* functioning at all), and non-zero otherwise.
|
|
||||||
*/
|
|
||||||
int __PHYSFS_platformInit(void);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Deinitialize the platform. This is called when PHYSFS_deinit() is called
|
|
||||||
* from the application. You can use this to clean up anything you've
|
|
||||||
* allocated in your platform driver.
|
|
||||||
*/
|
|
||||||
void __PHYSFS_platformDeinit(void);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open a file for reading. (filename) is in platform-dependent notation. The
|
|
||||||
* file pointer should be positioned on the first byte of the file.
|
|
||||||
*
|
|
||||||
* The return value will be some platform-specific datatype that is opaque to
|
|
||||||
* the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32.
|
|
||||||
*
|
|
||||||
* The same file can be opened for read multiple times, and each should have
|
|
||||||
* a unique file handle; this is frequently employed to prevent race
|
|
||||||
* conditions in the archivers.
|
|
||||||
*
|
|
||||||
* Call PHYSFS_setErrorCode() and return (NULL) if the file can't be opened.
|
|
||||||
*/
|
|
||||||
void *__PHYSFS_platformOpenRead(const char *filename);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open a file for writing. (filename) is in platform-dependent notation. If
|
|
||||||
* the file exists, it should be truncated to zero bytes, and if it doesn't
|
|
||||||
* exist, it should be created as a zero-byte file. The file pointer should
|
|
||||||
* be positioned on the first byte of the file.
|
|
||||||
*
|
|
||||||
* The return value will be some platform-specific datatype that is opaque to
|
|
||||||
* the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32,
|
|
||||||
* etc.
|
|
||||||
*
|
|
||||||
* Opening a file for write multiple times has undefined results.
|
|
||||||
*
|
|
||||||
* Call PHYSFS_setErrorCode() and return (NULL) if the file can't be opened.
|
|
||||||
*/
|
|
||||||
void *__PHYSFS_platformOpenWrite(const char *filename);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open a file for appending. (filename) is in platform-dependent notation. If
|
|
||||||
* the file exists, the file pointer should be place just past the end of the
|
|
||||||
* file, so that the first write will be one byte after the current end of
|
|
||||||
* the file. If the file doesn't exist, it should be created as a zero-byte
|
|
||||||
* file. The file pointer should be positioned on the first byte of the file.
|
|
||||||
*
|
|
||||||
* The return value will be some platform-specific datatype that is opaque to
|
|
||||||
* the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32,
|
|
||||||
* etc.
|
|
||||||
*
|
|
||||||
* Opening a file for append multiple times has undefined results.
|
|
||||||
*
|
|
||||||
* Call PHYSFS_setErrorCode() and return (NULL) if the file can't be opened.
|
|
||||||
*/
|
|
||||||
void *__PHYSFS_platformOpenAppend(const char *filename);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read more data from a platform-specific file handle. (opaque) should be
|
|
||||||
* cast to whatever data type your platform uses. Read a maximum of (len)
|
|
||||||
* 8-bit bytes to the area pointed to by (buf). If there isn't enough data
|
|
||||||
* available, return the number of bytes read, and position the file pointer
|
|
||||||
* immediately after those bytes.
|
|
||||||
* On success, return (len) and position the file pointer immediately past
|
|
||||||
* the end of the last read byte. Return (-1) if there is a catastrophic
|
|
||||||
* error, and call PHYSFS_setErrorCode() to describe the problem; the file
|
|
||||||
* pointer should not move in such a case. A partial read is success; only
|
|
||||||
* return (-1) on total failure; presumably, the next read call after a
|
|
||||||
* partial read will fail as such.
|
|
||||||
*/
|
|
||||||
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write more data to a platform-specific file handle. (opaque) should be
|
|
||||||
* cast to whatever data type your platform uses. Write a maximum of (len)
|
|
||||||
* 8-bit bytes from the area pointed to by (buffer). If there is a problem,
|
|
||||||
* return the number of bytes written, and position the file pointer
|
|
||||||
* immediately after those bytes. Return (-1) if there is a catastrophic
|
|
||||||
* error, and call PHYSFS_setErrorCode() to describe the problem; the file
|
|
||||||
* pointer should not move in such a case. A partial write is success; only
|
|
||||||
* return (-1) on total failure; presumably, the next write call after a
|
|
||||||
* partial write will fail as such.
|
|
||||||
*/
|
|
||||||
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
|
|
||||||
PHYSFS_uint64 len);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the file pointer to a new position. (opaque) should be cast to
|
|
||||||
* whatever data type your platform uses. (pos) specifies the number
|
|
||||||
* of 8-bit bytes to seek to from the start of the file. Seeking past the
|
|
||||||
* end of the file is an error condition, and you should check for it.
|
|
||||||
*
|
|
||||||
* Not all file types can seek; this is to be expected by the caller.
|
|
||||||
*
|
|
||||||
* On error, call PHYSFS_setErrorCode() and return zero. On success, return
|
|
||||||
* a non-zero value.
|
|
||||||
*/
|
|
||||||
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the file pointer's position, in an 8-bit byte offset from the start of
|
|
||||||
* the file. (opaque) should be cast to whatever data type your platform
|
|
||||||
* uses.
|
|
||||||
*
|
|
||||||
* Not all file types can "tell"; this is to be expected by the caller.
|
|
||||||
*
|
|
||||||
* On error, call PHYSFS_setErrorCode() and return -1. On success, return >= 0.
|
|
||||||
*/
|
|
||||||
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Determine the current size of a file, in 8-bit bytes, from an open file.
|
|
||||||
*
|
|
||||||
* The caller expects that this information may not be available for all
|
|
||||||
* file types on all platforms.
|
|
||||||
*
|
|
||||||
* Return -1 if you can't do it, and call PHYSFS_setErrorCode(). Otherwise,
|
|
||||||
* return the file length in 8-bit bytes.
|
|
||||||
*/
|
|
||||||
PHYSFS_sint64 __PHYSFS_platformFileLength(void *handle);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read filesystem metadata for a specific path.
|
|
||||||
*
|
|
||||||
* This needs to fill in all the fields of (stat). For fields that might not
|
|
||||||
* mean anything on a platform (access time, perhaps), choose a reasonable
|
|
||||||
* default. if (follow), we want to follow symlinks and stat what they
|
|
||||||
* link to and not the link itself.
|
|
||||||
*
|
|
||||||
* Return zero on failure, non-zero on success.
|
|
||||||
*/
|
|
||||||
int __PHYSFS_platformStat(const char *fn, PHYSFS_Stat *stat, const int follow);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Flush any pending writes to disk. (opaque) should be cast to whatever data
|
|
||||||
* type your platform uses. Be sure to check for errors; the caller expects
|
|
||||||
* that this function can fail if there was a flushing error, etc.
|
|
||||||
*
|
|
||||||
* Return zero on failure, non-zero on success.
|
|
||||||
*/
|
|
||||||
int __PHYSFS_platformFlush(void *opaque);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close file and deallocate resources. (opaque) should be cast to whatever
|
|
||||||
* data type your platform uses. This should close the file in any scenario:
|
|
||||||
* flushing is a separate function call, and this function should never fail.
|
|
||||||
*
|
|
||||||
* You should clean up all resources associated with (opaque); the pointer
|
|
||||||
* will be considered invalid after this call.
|
|
||||||
*/
|
|
||||||
void __PHYSFS_platformClose(void *opaque);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Platform implementation of PHYSFS_getCdRomDirsCallback()...
|
|
||||||
* CD directories are discovered and reported to the callback one at a time.
|
|
||||||
* Pointers passed to the callback are assumed to be invalid to the
|
|
||||||
* application after the callback returns, so you can free them or whatever.
|
|
||||||
* Callback does not assume results will be sorted in any meaningful way.
|
|
||||||
*/
|
|
||||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate the base dir, if your platform needs special consideration.
|
|
||||||
* Just return NULL if the standard routines will suffice. (see
|
|
||||||
* calculateBaseDir() in physfs.c ...)
|
|
||||||
* Your string must end with a dir separator if you don't return NULL.
|
|
||||||
* Caller will allocator.Free() the retval if it's not NULL.
|
|
||||||
*/
|
|
||||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the platform-specific user dir.
|
|
||||||
* As of PhysicsFS 2.1, returning NULL means fatal error.
|
|
||||||
* Your string must end with a dir separator if you don't return NULL.
|
|
||||||
* Caller will allocator.Free() the retval if it's not NULL.
|
|
||||||
*/
|
|
||||||
char *__PHYSFS_platformCalcUserDir(void);
|
|
||||||
|
|
||||||
|
|
||||||
/* This is the cached version from PHYSFS_init(). This is a fast call. */
|
|
||||||
const char *__PHYSFS_getUserDir(void); /* not deprecated internal version. */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the platform-specific pref dir.
|
|
||||||
* Returning NULL means fatal error.
|
|
||||||
* Your string must end with a dir separator if you don't return NULL.
|
|
||||||
* Caller will allocator.Free() the retval if it's not NULL.
|
|
||||||
* Caller will make missing directories if necessary; this just reports
|
|
||||||
* the final path.
|
|
||||||
*/
|
|
||||||
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a pointer that uniquely identifies the current thread.
|
|
||||||
* On a platform without threading, (0x1) will suffice. These numbers are
|
|
||||||
* arbitrary; the only requirement is that no two threads have the same
|
|
||||||
* pointer.
|
|
||||||
*/
|
|
||||||
void *__PHYSFS_platformGetThreadID(void);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enumerate a directory of files. This follows the rules for the
|
|
||||||
* PHYSFS_Archiver::enumerate() method, except that the (dirName) that is
|
|
||||||
* passed to this function is converted to platform-DEPENDENT notation by
|
|
||||||
* the caller. The PHYSFS_Archiver version uses platform-independent
|
|
||||||
* notation. Note that ".", "..", and other meta-entries should always
|
|
||||||
* be ignored.
|
|
||||||
*/
|
|
||||||
PHYSFS_EnumerateCallbackResult __PHYSFS_platformEnumerate(const char *dirname,
|
|
||||||
PHYSFS_EnumerateCallback callback,
|
|
||||||
const char *origdir, void *callbackdata);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make a directory in the actual filesystem. (path) is specified in
|
|
||||||
* platform-dependent notation. On error, return zero and set the error
|
|
||||||
* message. Return non-zero on success.
|
|
||||||
*/
|
|
||||||
int __PHYSFS_platformMkDir(const char *path);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove a file or directory entry in the actual filesystem. (path) is
|
|
||||||
* specified in platform-dependent notation. Note that this deletes files
|
|
||||||
* _and_ directories, so you might need to do some determination.
|
|
||||||
* Non-empty directories should report an error and not delete themselves
|
|
||||||
* or their contents.
|
|
||||||
*
|
|
||||||
* Deleting a symlink should remove the link, not what it points to.
|
|
||||||
*
|
|
||||||
* On error, return zero and set the error message. Return non-zero on success.
|
|
||||||
*/
|
|
||||||
int __PHYSFS_platformDelete(const char *path);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a platform-specific mutex. This can be whatever datatype your
|
|
||||||
* platform uses for mutexes, but it is cast to a (void *) for abstractness.
|
|
||||||
*
|
|
||||||
* Return (NULL) if you couldn't create one. Systems without threads can
|
|
||||||
* return any arbitrary non-NULL value.
|
|
||||||
*/
|
|
||||||
void *__PHYSFS_platformCreateMutex(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Destroy a platform-specific mutex, and clean up any resources associated
|
|
||||||
* with it. (mutex) is a value previously returned by
|
|
||||||
* __PHYSFS_platformCreateMutex(). This can be a no-op on single-threaded
|
|
||||||
* platforms.
|
|
||||||
*/
|
|
||||||
void __PHYSFS_platformDestroyMutex(void *mutex);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Grab possession of a platform-specific mutex. Mutexes should be recursive;
|
|
||||||
* that is, the same thread should be able to call this function multiple
|
|
||||||
* times in a row without causing a deadlock. This function should block
|
|
||||||
* until a thread can gain possession of the mutex.
|
|
||||||
*
|
|
||||||
* Return non-zero if the mutex was grabbed, zero if there was an
|
|
||||||
* unrecoverable problem grabbing it (this should not be a matter of
|
|
||||||
* timing out! We're talking major system errors; block until the mutex
|
|
||||||
* is available otherwise.)
|
|
||||||
*
|
|
||||||
* _DO NOT_ call PHYSFS_setErrorCode() in here! Since setErrorCode calls this
|
|
||||||
* function, you'll cause an infinite recursion. This means you can't
|
|
||||||
* use the BAIL_*MACRO* macros, either.
|
|
||||||
*/
|
|
||||||
int __PHYSFS_platformGrabMutex(void *mutex);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Relinquish possession of the mutex when this method has been called
|
|
||||||
* once for each time that platformGrabMutex was called. Once possession has
|
|
||||||
* been released, the next thread in line to grab the mutex (if any) may
|
|
||||||
* proceed.
|
|
||||||
*
|
|
||||||
* _DO NOT_ call PHYSFS_setErrorCode() in here! Since setErrorCode calls this
|
|
||||||
* function, you'll cause an infinite recursion. This means you can't
|
|
||||||
* use the BAIL_*MACRO* macros, either.
|
|
||||||
*/
|
|
||||||
void __PHYSFS_platformReleaseMutex(void *mutex);
|
|
||||||
|
|
||||||
#if PHYSFS_HAVE_PRAGMA_VISIBILITY
|
|
||||||
#pragma GCC visibility pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* end of physfs_internal.h ... */
|
|
||||||
|
|
701
third_party/physfs/physfs_miniz.h
vendored
701
third_party/physfs/physfs_miniz.h
vendored
|
@ -1,701 +0,0 @@
|
||||||
/* tinfl.c v1.11 - public domain inflate with zlib header parsing/adler32 checking (inflate-only subset of miniz.c)
|
|
||||||
See "unlicense" statement at the end of this file.
|
|
||||||
Rich Geldreich <richgel99@gmail.com>, last updated May 20, 2011
|
|
||||||
Implements RFC 1950: https://www.ietf.org/rfc/rfc1950.txt and RFC 1951: https://www.ietf.org/rfc/rfc1951.txt
|
|
||||||
|
|
||||||
The entire decompressor coroutine is implemented in tinfl_decompress(). The other functions are optional high-level helpers.
|
|
||||||
*/
|
|
||||||
#ifndef TINFL_HEADER_INCLUDED
|
|
||||||
#define TINFL_HEADER_INCLUDED
|
|
||||||
|
|
||||||
typedef PHYSFS_uint8 mz_uint8;
|
|
||||||
typedef PHYSFS_sint16 mz_int16;
|
|
||||||
typedef PHYSFS_uint16 mz_uint16;
|
|
||||||
typedef PHYSFS_uint32 mz_uint32;
|
|
||||||
typedef unsigned int mz_uint;
|
|
||||||
typedef PHYSFS_uint64 mz_uint64;
|
|
||||||
|
|
||||||
/* For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. */
|
|
||||||
typedef unsigned long mz_ulong;
|
|
||||||
|
|
||||||
/* Heap allocation callbacks. */
|
|
||||||
typedef void *(*mz_alloc_func)(void *opaque, unsigned int items, unsigned int size);
|
|
||||||
typedef void (*mz_free_func)(void *opaque, void *address);
|
|
||||||
|
|
||||||
#if defined(_M_IX86) || defined(_M_X64)
|
|
||||||
/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 if integer loads and stores to unaligned addresses are acceptable on the target platform (slightly faster). */
|
|
||||||
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
|
|
||||||
/* Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. */
|
|
||||||
#define MINIZ_LITTLE_ENDIAN 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__)
|
|
||||||
/* Set MINIZ_HAS_64BIT_REGISTERS to 1 if the processor has 64-bit general purpose registers (enables 64-bit bitbuffer in inflator) */
|
|
||||||
#define MINIZ_HAS_64BIT_REGISTERS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Works around MSVC's spammy "warning C4127: conditional expression is constant" message. */
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define MZ_MACRO_END while (0, 0)
|
|
||||||
#else
|
|
||||||
#define MZ_MACRO_END while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Decompression flags. */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
|
|
||||||
TINFL_FLAG_HAS_MORE_INPUT = 2,
|
|
||||||
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
|
|
||||||
TINFL_FLAG_COMPUTE_ADLER32 = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
|
|
||||||
|
|
||||||
/* Max size of LZ dictionary. */
|
|
||||||
#define TINFL_LZ_DICT_SIZE 32768
|
|
||||||
|
|
||||||
/* Return status. */
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TINFL_STATUS_BAD_PARAM = -3,
|
|
||||||
TINFL_STATUS_ADLER32_MISMATCH = -2,
|
|
||||||
TINFL_STATUS_FAILED = -1,
|
|
||||||
TINFL_STATUS_DONE = 0,
|
|
||||||
TINFL_STATUS_NEEDS_MORE_INPUT = 1,
|
|
||||||
TINFL_STATUS_HAS_MORE_OUTPUT = 2
|
|
||||||
} tinfl_status;
|
|
||||||
|
|
||||||
/* Initializes the decompressor to its initial state. */
|
|
||||||
#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
|
|
||||||
#define tinfl_get_adler32(r) (r)->m_check_adler32
|
|
||||||
|
|
||||||
/* Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. */
|
|
||||||
/* This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. */
|
|
||||||
static tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
|
|
||||||
|
|
||||||
/* Internal/private bits follow. */
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
|
|
||||||
TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
|
|
||||||
mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
|
|
||||||
} tinfl_huff_table;
|
|
||||||
|
|
||||||
#if MINIZ_HAS_64BIT_REGISTERS
|
|
||||||
#define TINFL_USE_64BIT_BITBUF 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TINFL_USE_64BIT_BITBUF
|
|
||||||
typedef mz_uint64 tinfl_bit_buf_t;
|
|
||||||
#define TINFL_BITBUF_SIZE (64)
|
|
||||||
#else
|
|
||||||
typedef mz_uint32 tinfl_bit_buf_t;
|
|
||||||
#define TINFL_BITBUF_SIZE (32)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct tinfl_decompressor_tag
|
|
||||||
{
|
|
||||||
mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
|
|
||||||
tinfl_bit_buf_t m_bit_buf;
|
|
||||||
size_t m_dist_from_out_buf_start;
|
|
||||||
tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
|
|
||||||
mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* #ifdef TINFL_HEADER_INCLUDED */
|
|
||||||
|
|
||||||
/* ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.) */
|
|
||||||
|
|
||||||
#ifndef TINFL_HEADER_FILE_ONLY
|
|
||||||
|
|
||||||
#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
|
|
||||||
#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
|
|
||||||
#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
|
|
||||||
|
|
||||||
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
|
|
||||||
#define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
|
|
||||||
#define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
|
|
||||||
#else
|
|
||||||
#define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
|
|
||||||
#define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
|
|
||||||
#define TINFL_MEMSET(p, c, l) memset(p, c, l)
|
|
||||||
|
|
||||||
#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
|
|
||||||
#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
|
|
||||||
#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
|
|
||||||
#define TINFL_CR_FINISH }
|
|
||||||
|
|
||||||
/* TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never */
|
|
||||||
/* reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario. */
|
|
||||||
#define TINFL_GET_BYTE(state_index, c) do { \
|
|
||||||
if (pIn_buf_cur >= pIn_buf_end) { \
|
|
||||||
for ( ; ; ) { \
|
|
||||||
if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
|
|
||||||
TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
|
|
||||||
if (pIn_buf_cur < pIn_buf_end) { \
|
|
||||||
c = *pIn_buf_cur++; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
} else { \
|
|
||||||
c = 0; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} else c = *pIn_buf_cur++; } MZ_MACRO_END
|
|
||||||
|
|
||||||
#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
|
|
||||||
#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
|
|
||||||
#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
|
|
||||||
|
|
||||||
/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
|
|
||||||
/* It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a */
|
|
||||||
/* Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the */
|
|
||||||
/* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
|
|
||||||
#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
|
|
||||||
do { \
|
|
||||||
temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
|
|
||||||
if (temp >= 0) { \
|
|
||||||
code_len = temp >> 9; \
|
|
||||||
if ((code_len) && (num_bits >= code_len)) \
|
|
||||||
break; \
|
|
||||||
} else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
|
|
||||||
code_len = TINFL_FAST_LOOKUP_BITS; \
|
|
||||||
do { \
|
|
||||||
temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
|
|
||||||
} while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
|
|
||||||
} TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
|
|
||||||
} while (num_bits < 15);
|
|
||||||
|
|
||||||
/* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */
|
|
||||||
/* beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully */
|
|
||||||
/* decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. */
|
|
||||||
/* The slow path is only executed at the very end of the input buffer. */
|
|
||||||
#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
|
|
||||||
int temp; mz_uint code_len, c; \
|
|
||||||
if (num_bits < 15) { \
|
|
||||||
if ((pIn_buf_end - pIn_buf_cur) < 2) { \
|
|
||||||
TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
|
|
||||||
} else { \
|
|
||||||
bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
|
|
||||||
code_len = temp >> 9, temp &= 511; \
|
|
||||||
else { \
|
|
||||||
code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
|
|
||||||
} sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
|
|
||||||
|
|
||||||
static tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
|
|
||||||
{
|
|
||||||
static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 };
|
|
||||||
static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
|
|
||||||
static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
|
|
||||||
static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
|
|
||||||
static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
|
|
||||||
static const int s_min_table_sizes[3] = { 257, 1, 4 };
|
|
||||||
|
|
||||||
tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
|
|
||||||
const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
|
|
||||||
mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
|
|
||||||
size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
|
|
||||||
|
|
||||||
/* Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). */
|
|
||||||
if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }
|
|
||||||
|
|
||||||
num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
|
|
||||||
TINFL_CR_BEGIN
|
|
||||||
|
|
||||||
bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
|
|
||||||
if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
|
|
||||||
{
|
|
||||||
TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
|
|
||||||
counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
|
|
||||||
if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
|
|
||||||
if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
|
|
||||||
if (r->m_type == 0)
|
|
||||||
{
|
|
||||||
TINFL_SKIP_BITS(5, num_bits & 7);
|
|
||||||
for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
|
|
||||||
if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
|
|
||||||
while ((counter) && (num_bits))
|
|
||||||
{
|
|
||||||
TINFL_GET_BITS(51, dist, 8);
|
|
||||||
while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
|
|
||||||
*pOut_buf_cur++ = (mz_uint8)dist;
|
|
||||||
counter--;
|
|
||||||
}
|
|
||||||
while (counter)
|
|
||||||
{
|
|
||||||
size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
|
|
||||||
while (pIn_buf_cur >= pIn_buf_end)
|
|
||||||
{
|
|
||||||
if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
|
|
||||||
{
|
|
||||||
TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
|
|
||||||
TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (r->m_type == 3)
|
|
||||||
{
|
|
||||||
TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (r->m_type == 1)
|
|
||||||
{
|
|
||||||
mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
|
|
||||||
r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
|
|
||||||
for ( i = 0; i <= 143; ++i) *p++ = 8;
|
|
||||||
for ( ; i <= 255; ++i) *p++ = 9;
|
|
||||||
for ( ; i <= 279; ++i) *p++ = 7;
|
|
||||||
for ( ; i <= 287; ++i) *p++ = 8;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
|
|
||||||
MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
|
|
||||||
r->m_table_sizes[2] = 19;
|
|
||||||
}
|
|
||||||
for ( ; (int)r->m_type >= 0; r->m_type--)
|
|
||||||
{
|
|
||||||
int tree_next, tree_cur; tinfl_huff_table *pTable;
|
|
||||||
mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
|
|
||||||
for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
|
|
||||||
used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
|
|
||||||
for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
|
|
||||||
if ((65536 != total) && (used_syms > 1))
|
|
||||||
{
|
|
||||||
TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
|
|
||||||
}
|
|
||||||
for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
|
|
||||||
{
|
|
||||||
mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
|
|
||||||
cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
|
|
||||||
if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
|
|
||||||
if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
|
|
||||||
rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
|
|
||||||
for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
|
|
||||||
{
|
|
||||||
tree_cur -= ((rev_code >>= 1) & 1);
|
|
||||||
if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
|
|
||||||
}
|
|
||||||
tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
|
|
||||||
}
|
|
||||||
if (r->m_type == 2)
|
|
||||||
{
|
|
||||||
for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
|
|
||||||
{
|
|
||||||
mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
|
|
||||||
if ((dist == 16) && (!counter))
|
|
||||||
{
|
|
||||||
TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
|
|
||||||
}
|
|
||||||
num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
|
|
||||||
TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
|
|
||||||
}
|
|
||||||
if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
|
|
||||||
{
|
|
||||||
TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
|
|
||||||
}
|
|
||||||
TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for ( ; ; )
|
|
||||||
{
|
|
||||||
mz_uint8 *pSrc;
|
|
||||||
for ( ; ; )
|
|
||||||
{
|
|
||||||
if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
|
|
||||||
{
|
|
||||||
TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
|
|
||||||
if (counter >= 256)
|
|
||||||
break;
|
|
||||||
while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
|
|
||||||
*pOut_buf_cur++ = (mz_uint8)counter;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int sym2; mz_uint code_len;
|
|
||||||
#if TINFL_USE_64BIT_BITBUF
|
|
||||||
if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; }
|
|
||||||
#else
|
|
||||||
if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
|
|
||||||
#endif
|
|
||||||
if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
|
|
||||||
code_len = sym2 >> 9;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
|
|
||||||
}
|
|
||||||
counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
|
|
||||||
if (counter & 256)
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if !TINFL_USE_64BIT_BITBUF
|
|
||||||
if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
|
|
||||||
#endif
|
|
||||||
if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
|
|
||||||
code_len = sym2 >> 9;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
|
|
||||||
}
|
|
||||||
bit_buf >>= code_len; num_bits -= code_len;
|
|
||||||
|
|
||||||
pOut_buf_cur[0] = (mz_uint8)counter;
|
|
||||||
if (sym2 & 256)
|
|
||||||
{
|
|
||||||
pOut_buf_cur++;
|
|
||||||
counter = sym2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pOut_buf_cur[1] = (mz_uint8)sym2;
|
|
||||||
pOut_buf_cur += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((counter &= 511) == 256) break;
|
|
||||||
|
|
||||||
num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
|
|
||||||
if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
|
|
||||||
|
|
||||||
TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
|
|
||||||
num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
|
|
||||||
if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
|
|
||||||
|
|
||||||
dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
|
|
||||||
if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
|
|
||||||
{
|
|
||||||
TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
|
|
||||||
|
|
||||||
if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
|
|
||||||
{
|
|
||||||
while (counter--)
|
|
||||||
{
|
|
||||||
while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
|
|
||||||
*pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
|
|
||||||
else if ((counter >= 9) && (counter <= dist))
|
|
||||||
{
|
|
||||||
const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
|
|
||||||
((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
|
|
||||||
pOut_buf_cur += 8;
|
|
||||||
} while ((pSrc += 8) < pSrc_end);
|
|
||||||
if ((counter &= 7) < 3)
|
|
||||||
{
|
|
||||||
if (counter)
|
|
||||||
{
|
|
||||||
pOut_buf_cur[0] = pSrc[0];
|
|
||||||
if (counter > 1)
|
|
||||||
pOut_buf_cur[1] = pSrc[1];
|
|
||||||
pOut_buf_cur += counter;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
do
|
|
||||||
{
|
|
||||||
pOut_buf_cur[0] = pSrc[0];
|
|
||||||
pOut_buf_cur[1] = pSrc[1];
|
|
||||||
pOut_buf_cur[2] = pSrc[2];
|
|
||||||
pOut_buf_cur += 3; pSrc += 3;
|
|
||||||
} while ((int)(counter -= 3) > 2);
|
|
||||||
if ((int)counter > 0)
|
|
||||||
{
|
|
||||||
pOut_buf_cur[0] = pSrc[0];
|
|
||||||
if ((int)counter > 1)
|
|
||||||
pOut_buf_cur[1] = pSrc[1];
|
|
||||||
pOut_buf_cur += counter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!(r->m_final & 1));
|
|
||||||
if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
|
|
||||||
{
|
|
||||||
TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
|
|
||||||
}
|
|
||||||
TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
|
|
||||||
TINFL_CR_FINISH
|
|
||||||
|
|
||||||
common_exit:
|
|
||||||
r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
|
|
||||||
*pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
|
|
||||||
if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
|
|
||||||
{
|
|
||||||
const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
|
|
||||||
mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
|
|
||||||
while (buf_len)
|
|
||||||
{
|
|
||||||
for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
|
|
||||||
{
|
|
||||||
s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
|
|
||||||
s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
|
|
||||||
}
|
|
||||||
for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
|
|
||||||
s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
|
|
||||||
}
|
|
||||||
r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other stuff is for advanced use. */
|
|
||||||
enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 };
|
|
||||||
|
|
||||||
/* Return status codes. MZ_PARAM_ERROR is non-standard. */
|
|
||||||
enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 };
|
|
||||||
|
|
||||||
/* Compression levels. */
|
|
||||||
enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_DEFAULT_COMPRESSION = -1 };
|
|
||||||
|
|
||||||
/* Window bits */
|
|
||||||
#define MZ_DEFAULT_WINDOW_BITS 15
|
|
||||||
|
|
||||||
struct mz_internal_state;
|
|
||||||
|
|
||||||
/* Compression/decompression stream struct. */
|
|
||||||
typedef struct mz_stream_s
|
|
||||||
{
|
|
||||||
const unsigned char *next_in; /* pointer to next byte to read */
|
|
||||||
unsigned int avail_in; /* number of bytes available at next_in */
|
|
||||||
mz_ulong total_in; /* total number of bytes consumed so far */
|
|
||||||
|
|
||||||
unsigned char *next_out; /* pointer to next byte to write */
|
|
||||||
unsigned int avail_out; /* number of bytes that can be written to next_out */
|
|
||||||
mz_ulong total_out; /* total number of bytes produced so far */
|
|
||||||
|
|
||||||
char *msg; /* error msg (unused) */
|
|
||||||
struct mz_internal_state *state; /* internal state, allocated by zalloc/zfree */
|
|
||||||
|
|
||||||
mz_alloc_func zalloc; /* optional heap allocation function (defaults to malloc) */
|
|
||||||
mz_free_func zfree; /* optional heap free function (defaults to free) */
|
|
||||||
void *opaque; /* heap alloc function user pointer */
|
|
||||||
|
|
||||||
int data_type; /* data_type (unused) */
|
|
||||||
mz_ulong adler; /* adler32 of the source or uncompressed data */
|
|
||||||
mz_ulong reserved; /* not used */
|
|
||||||
} mz_stream;
|
|
||||||
|
|
||||||
typedef mz_stream *mz_streamp;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
tinfl_decompressor m_decomp;
|
|
||||||
mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits;
|
|
||||||
mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
|
|
||||||
tinfl_status m_last_status;
|
|
||||||
} inflate_state;
|
|
||||||
|
|
||||||
static int mz_inflateInit2(mz_streamp pStream, int window_bits)
|
|
||||||
{
|
|
||||||
inflate_state *pDecomp;
|
|
||||||
if (!pStream) return MZ_STREAM_ERROR;
|
|
||||||
if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR;
|
|
||||||
|
|
||||||
pStream->data_type = 0;
|
|
||||||
pStream->adler = 0;
|
|
||||||
pStream->msg = NULL;
|
|
||||||
pStream->total_in = 0;
|
|
||||||
pStream->total_out = 0;
|
|
||||||
pStream->reserved = 0;
|
|
||||||
/* if (!pStream->zalloc) pStream->zalloc = def_alloc_func; */
|
|
||||||
/* if (!pStream->zfree) pStream->zfree = def_free_func; */
|
|
||||||
|
|
||||||
pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
|
|
||||||
if (!pDecomp) return MZ_MEM_ERROR;
|
|
||||||
|
|
||||||
pStream->state = (struct mz_internal_state *)pDecomp;
|
|
||||||
|
|
||||||
tinfl_init(&pDecomp->m_decomp);
|
|
||||||
pDecomp->m_dict_ofs = 0;
|
|
||||||
pDecomp->m_dict_avail = 0;
|
|
||||||
pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
|
|
||||||
pDecomp->m_first_call = 1;
|
|
||||||
pDecomp->m_has_flushed = 0;
|
|
||||||
pDecomp->m_window_bits = window_bits;
|
|
||||||
|
|
||||||
return MZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mz_inflate(mz_streamp pStream, int flush)
|
|
||||||
{
|
|
||||||
inflate_state* pState;
|
|
||||||
mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
|
|
||||||
size_t in_bytes, out_bytes, orig_avail_in;
|
|
||||||
tinfl_status status;
|
|
||||||
|
|
||||||
if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR;
|
|
||||||
if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH;
|
|
||||||
if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
|
|
||||||
|
|
||||||
pState = (inflate_state*)pStream->state;
|
|
||||||
if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
|
|
||||||
orig_avail_in = pStream->avail_in;
|
|
||||||
|
|
||||||
first_call = pState->m_first_call; pState->m_first_call = 0;
|
|
||||||
if (pState->m_last_status < 0) return MZ_DATA_ERROR;
|
|
||||||
|
|
||||||
if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR;
|
|
||||||
pState->m_has_flushed |= (flush == MZ_FINISH);
|
|
||||||
|
|
||||||
if ((flush == MZ_FINISH) && (first_call))
|
|
||||||
{
|
|
||||||
/* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */
|
|
||||||
decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
|
|
||||||
in_bytes = pStream->avail_in; out_bytes = pStream->avail_out;
|
|
||||||
status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
|
|
||||||
pState->m_last_status = status;
|
|
||||||
pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes;
|
|
||||||
pStream->adler = tinfl_get_adler32(&pState->m_decomp);
|
|
||||||
pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes;
|
|
||||||
|
|
||||||
if (status < 0)
|
|
||||||
return MZ_DATA_ERROR;
|
|
||||||
else if (status != TINFL_STATUS_DONE)
|
|
||||||
{
|
|
||||||
pState->m_last_status = TINFL_STATUS_FAILED;
|
|
||||||
return MZ_BUF_ERROR;
|
|
||||||
}
|
|
||||||
return MZ_STREAM_END;
|
|
||||||
}
|
|
||||||
/* flush != MZ_FINISH then we must assume there's more input. */
|
|
||||||
if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
|
|
||||||
|
|
||||||
if (pState->m_dict_avail)
|
|
||||||
{
|
|
||||||
n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
|
|
||||||
memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
|
|
||||||
pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
|
|
||||||
pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
|
|
||||||
return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( ; ; )
|
|
||||||
{
|
|
||||||
in_bytes = pStream->avail_in;
|
|
||||||
out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
|
|
||||||
|
|
||||||
status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
|
|
||||||
pState->m_last_status = status;
|
|
||||||
|
|
||||||
pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes;
|
|
||||||
pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp);
|
|
||||||
|
|
||||||
pState->m_dict_avail = (mz_uint)out_bytes;
|
|
||||||
|
|
||||||
n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
|
|
||||||
memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
|
|
||||||
pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n;
|
|
||||||
pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
|
|
||||||
|
|
||||||
if (status < 0)
|
|
||||||
return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
|
|
||||||
else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
|
|
||||||
return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */
|
|
||||||
else if (flush == MZ_FINISH)
|
|
||||||
{
|
|
||||||
/* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
|
|
||||||
if (status == TINFL_STATUS_DONE)
|
|
||||||
return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
|
|
||||||
/* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */
|
|
||||||
else if (!pStream->avail_out)
|
|
||||||
return MZ_BUF_ERROR;
|
|
||||||
}
|
|
||||||
else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mz_inflateEnd(mz_streamp pStream)
|
|
||||||
{
|
|
||||||
if (!pStream)
|
|
||||||
return MZ_STREAM_ERROR;
|
|
||||||
if (pStream->state)
|
|
||||||
{
|
|
||||||
pStream->zfree(pStream->opaque, pStream->state);
|
|
||||||
pStream->state = NULL;
|
|
||||||
}
|
|
||||||
return MZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make this a drop-in replacement for zlib... */
|
|
||||||
#define voidpf void*
|
|
||||||
#define uInt unsigned int
|
|
||||||
#define z_stream mz_stream
|
|
||||||
#define inflateInit2 mz_inflateInit2
|
|
||||||
#define inflate mz_inflate
|
|
||||||
#define inflateEnd mz_inflateEnd
|
|
||||||
#define Z_SYNC_FLUSH MZ_SYNC_FLUSH
|
|
||||||
#define Z_FINISH MZ_FINISH
|
|
||||||
#define Z_OK MZ_OK
|
|
||||||
#define Z_STREAM_END MZ_STREAM_END
|
|
||||||
#define Z_NEED_DICT MZ_NEED_DICT
|
|
||||||
#define Z_ERRNO MZ_ERRNO
|
|
||||||
#define Z_STREAM_ERROR MZ_STREAM_ERROR
|
|
||||||
#define Z_DATA_ERROR MZ_DATA_ERROR
|
|
||||||
#define Z_MEM_ERROR MZ_MEM_ERROR
|
|
||||||
#define Z_BUF_ERROR MZ_BUF_ERROR
|
|
||||||
#define Z_VERSION_ERROR MZ_VERSION_ERROR
|
|
||||||
#define MAX_WBITS 15
|
|
||||||
|
|
||||||
#endif /* #ifndef TINFL_HEADER_FILE_ONLY */
|
|
||||||
|
|
||||||
/*
|
|
||||||
This is free and unencumbered software released into the public domain.
|
|
||||||
|
|
||||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
||||||
distribute this software, either in source code form or as a compiled
|
|
||||||
binary, for any purpose, commercial or non-commercial, and by any
|
|
||||||
means.
|
|
||||||
|
|
||||||
In jurisdictions that recognize copyright laws, the author or authors
|
|
||||||
of this software dedicate any and all copyright interest in the
|
|
||||||
software to the public domain. We make this dedication for the benefit
|
|
||||||
of the public at large and to the detriment of our heirs and
|
|
||||||
successors. We intend this dedication to be an overt act of
|
|
||||||
relinquishment in perpetuity of all present and future rights to this
|
|
||||||
software under copyright law.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
||||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
||||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
For more information, please refer to <https://unlicense.org/>
|
|
||||||
*/
|
|
188
third_party/physfs/physfs_platform_apple.m
vendored
188
third_party/physfs/physfs_platform_apple.m
vendored
|
@ -1,188 +0,0 @@
|
||||||
/*
|
|
||||||
* Apple platform (macOS, iOS, watchOS, etc) support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_platforms.h"
|
|
||||||
|
|
||||||
#ifdef PHYSFS_PLATFORM_APPLE
|
|
||||||
|
|
||||||
#include <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
int __PHYSFS_platformInit(void)
|
|
||||||
{
|
|
||||||
return 1; /* success. */
|
|
||||||
} /* __PHYSFS_platformInit */
|
|
||||||
|
|
||||||
|
|
||||||
void __PHYSFS_platformDeinit(void)
|
|
||||||
{
|
|
||||||
/* no-op */
|
|
||||||
} /* __PHYSFS_platformDeinit */
|
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
|
||||||
{
|
|
||||||
@autoreleasepool
|
|
||||||
{
|
|
||||||
NSString *path = [[NSBundle mainBundle] bundlePath];
|
|
||||||
BAIL_IF(!path, PHYSFS_ERR_OS_ERROR, NULL);
|
|
||||||
size_t len = [path lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
|
||||||
char *retval = (char *) allocator.Malloc(len + 2);
|
|
||||||
BAIL_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
[path getCString:retval maxLength:len+1 encoding:NSUTF8StringEncoding];
|
|
||||||
retval[len] = '/';
|
|
||||||
retval[len+1] = '\0';
|
|
||||||
return retval; /* whew. */
|
|
||||||
} /* @autoreleasepool */
|
|
||||||
} /* __PHYSFS_platformCalcBaseDir */
|
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app)
|
|
||||||
{
|
|
||||||
@autoreleasepool
|
|
||||||
{
|
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, TRUE);
|
|
||||||
BAIL_IF(!paths, PHYSFS_ERR_OS_ERROR, NULL);
|
|
||||||
NSString *path = (NSString *) [paths objectAtIndex:0];
|
|
||||||
BAIL_IF(!path, PHYSFS_ERR_OS_ERROR, NULL);
|
|
||||||
size_t len = [path lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
|
||||||
const size_t applen = strlen(app);
|
|
||||||
char *retval = (char *) allocator.Malloc(len + applen + 3);
|
|
||||||
BAIL_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
[path getCString:retval maxLength:len+1 encoding:NSUTF8StringEncoding];
|
|
||||||
snprintf(retval + len, applen + 3, "/%s/", app);
|
|
||||||
return retval; /* whew. */
|
|
||||||
} /* @autoreleasepool */
|
|
||||||
} /* __PHYSFS_platformCalcPrefDir */
|
|
||||||
|
|
||||||
|
|
||||||
/* CD-ROM detection code... */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Code based on sample from Apple Developer Connection:
|
|
||||||
* https://developer.apple.com/samplecode/Sample_Code/Devices_and_Hardware/Disks/VolumeToBSDNode/VolumeToBSDNode.c.htm
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(PHYSFS_NO_CDROM_SUPPORT)
|
|
||||||
|
|
||||||
#include <IOKit/IOKitLib.h>
|
|
||||||
#include <IOKit/storage/IOMedia.h>
|
|
||||||
#include <IOKit/storage/IOCDMedia.h>
|
|
||||||
#include <IOKit/storage/IODVDMedia.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
|
|
||||||
static int darwinIsWholeMedia(io_service_t service)
|
|
||||||
{
|
|
||||||
int retval = 0;
|
|
||||||
CFTypeRef wholeMedia;
|
|
||||||
|
|
||||||
if (!IOObjectConformsTo(service, kIOMediaClass))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
wholeMedia = IORegistryEntryCreateCFProperty(service,
|
|
||||||
CFSTR(kIOMediaWholeKey),
|
|
||||||
NULL, 0);
|
|
||||||
if (wholeMedia == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
retval = CFBooleanGetValue(wholeMedia);
|
|
||||||
CFRelease(wholeMedia);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
} /* darwinIsWholeMedia */
|
|
||||||
|
|
||||||
|
|
||||||
static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
|
|
||||||
{
|
|
||||||
int retval = 0;
|
|
||||||
CFMutableDictionaryRef matchingDict;
|
|
||||||
kern_return_t rc;
|
|
||||||
io_iterator_t iter;
|
|
||||||
io_service_t service;
|
|
||||||
|
|
||||||
if ((matchingDict = IOBSDNameMatching(masterPort, 0, bsdName)) == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rc = IOServiceGetMatchingServices(masterPort, matchingDict, &iter);
|
|
||||||
if ((rc != KERN_SUCCESS) || (!iter))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
service = IOIteratorNext(iter);
|
|
||||||
IOObjectRelease(iter);
|
|
||||||
if (!service)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rc = IORegistryEntryCreateIterator(service, kIOServicePlane,
|
|
||||||
kIORegistryIterateRecursively | kIORegistryIterateParents, &iter);
|
|
||||||
|
|
||||||
if (!iter)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (rc != KERN_SUCCESS)
|
|
||||||
{
|
|
||||||
IOObjectRelease(iter);
|
|
||||||
return 0;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
IOObjectRetain(service); /* add an extra object reference... */
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (darwinIsWholeMedia(service))
|
|
||||||
{
|
|
||||||
if ( (IOObjectConformsTo(service, kIOCDMediaClass)) ||
|
|
||||||
(IOObjectConformsTo(service, kIODVDMediaClass)) )
|
|
||||||
{
|
|
||||||
retval = 1;
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
IOObjectRelease(service);
|
|
||||||
} while ((service = IOIteratorNext(iter)) && (!retval));
|
|
||||||
|
|
||||||
IOObjectRelease(iter);
|
|
||||||
IOObjectRelease(service);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
} /* darwinIsMountedDisc */
|
|
||||||
|
|
||||||
#endif /* !defined(PHYSFS_NO_CDROM_SUPPORT) */
|
|
||||||
|
|
||||||
|
|
||||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
|
||||||
{
|
|
||||||
#if !defined(PHYSFS_NO_CDROM_SUPPORT)
|
|
||||||
const char *devPrefix = "/dev/";
|
|
||||||
const int prefixLen = strlen(devPrefix);
|
|
||||||
mach_port_t masterPort = 0;
|
|
||||||
struct statfs *mntbufp;
|
|
||||||
int i, mounts;
|
|
||||||
|
|
||||||
if (IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS)
|
|
||||||
BAIL(PHYSFS_ERR_OS_ERROR, ) /*return void*/;
|
|
||||||
|
|
||||||
mounts = getmntinfo(&mntbufp, MNT_WAIT); /* NOT THREAD SAFE! */
|
|
||||||
for (i = 0; i < mounts; i++)
|
|
||||||
{
|
|
||||||
char *dev = mntbufp[i].f_mntfromname;
|
|
||||||
char *mnt = mntbufp[i].f_mntonname;
|
|
||||||
if (strncmp(dev, devPrefix, prefixLen) != 0) /* a virtual device? */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
dev += prefixLen;
|
|
||||||
if (darwinIsMountedDisc(dev, masterPort))
|
|
||||||
cb(data, mnt);
|
|
||||||
} /* for */
|
|
||||||
#endif /* !defined(PHYSFS_NO_CDROM_SUPPORT) */
|
|
||||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
|
||||||
|
|
||||||
#endif /* PHYSFS_PLATFORM_APPLE */
|
|
||||||
|
|
||||||
/* end of physfs_platform_apple.m ... */
|
|
||||||
|
|
186
third_party/physfs/physfs_platform_haiku.cpp
vendored
186
third_party/physfs/physfs_platform_haiku.cpp
vendored
|
@ -1,186 +0,0 @@
|
||||||
/*
|
|
||||||
* Haiku platform-dependent support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_platforms.h"
|
|
||||||
|
|
||||||
#ifdef PHYSFS_PLATFORM_HAIKU
|
|
||||||
|
|
||||||
#include <os/kernel/OS.h>
|
|
||||||
#include <os/app/Roster.h>
|
|
||||||
#include <os/storage/Volume.h>
|
|
||||||
#include <os/storage/VolumeRoster.h>
|
|
||||||
#include <os/storage/Directory.h>
|
|
||||||
#include <os/storage/Entry.h>
|
|
||||||
#include <os/storage/Path.h>
|
|
||||||
#include <os/kernel/fs_info.h>
|
|
||||||
#include <os/device/scsi.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
int __PHYSFS_platformInit(void)
|
|
||||||
{
|
|
||||||
return 1; /* always succeed. */
|
|
||||||
} /* __PHYSFS_platformInit */
|
|
||||||
|
|
||||||
|
|
||||||
void __PHYSFS_platformDeinit(void)
|
|
||||||
{
|
|
||||||
/* no-op */
|
|
||||||
} /* __PHYSFS_platformDeinit */
|
|
||||||
|
|
||||||
|
|
||||||
static char *getMountPoint(const char *devname, char *buf, size_t bufsize)
|
|
||||||
{
|
|
||||||
BVolumeRoster mounts;
|
|
||||||
BVolume vol;
|
|
||||||
|
|
||||||
mounts.Rewind();
|
|
||||||
while (mounts.GetNextVolume(&vol) == B_NO_ERROR)
|
|
||||||
{
|
|
||||||
fs_info fsinfo;
|
|
||||||
fs_stat_dev(vol.Device(), &fsinfo);
|
|
||||||
if (strcmp(devname, fsinfo.device_name) == 0)
|
|
||||||
{
|
|
||||||
BDirectory directory;
|
|
||||||
BEntry entry;
|
|
||||||
BPath path;
|
|
||||||
const char *str;
|
|
||||||
|
|
||||||
if ( (vol.GetRootDirectory(&directory) < B_OK) ||
|
|
||||||
(directory.GetEntry(&entry) < B_OK) ||
|
|
||||||
(entry.GetPath(&path) < B_OK) ||
|
|
||||||
( (str = path.Path()) == NULL) )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
strncpy(buf, str, bufsize-1);
|
|
||||||
buf[bufsize-1] = '\0';
|
|
||||||
return buf;
|
|
||||||
} /* if */
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
} /* getMountPoint */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function is lifted from Simple Directmedia Layer (SDL):
|
|
||||||
* https://www.libsdl.org/ ... this is zlib-licensed code, too.
|
|
||||||
*/
|
|
||||||
static void tryDir(const char *d, PHYSFS_StringCallback callback, void *data)
|
|
||||||
{
|
|
||||||
BDirectory dir;
|
|
||||||
dir.SetTo(d);
|
|
||||||
if (dir.InitCheck() != B_NO_ERROR)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dir.Rewind();
|
|
||||||
BEntry entry;
|
|
||||||
while (dir.GetNextEntry(&entry) >= 0)
|
|
||||||
{
|
|
||||||
BPath path;
|
|
||||||
const char *name;
|
|
||||||
entry_ref e;
|
|
||||||
|
|
||||||
if (entry.GetPath(&path) != B_NO_ERROR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
name = path.Path();
|
|
||||||
|
|
||||||
if (entry.GetRef(&e) != B_NO_ERROR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (entry.IsDirectory())
|
|
||||||
{
|
|
||||||
if (strcmp(e.name, "floppy") != 0)
|
|
||||||
tryDir(name, callback, data);
|
|
||||||
continue;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
const int devfd = open(name, O_RDONLY);
|
|
||||||
if (devfd < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
device_geometry g;
|
|
||||||
const int rc = ioctl(devfd, B_GET_GEOMETRY, &g, sizeof (g));
|
|
||||||
close(devfd);
|
|
||||||
if (rc < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (g.device_type != B_CD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
char mntpnt[B_FILE_NAME_LENGTH];
|
|
||||||
if (getMountPoint(name, mntpnt, sizeof (mntpnt)))
|
|
||||||
callback(data, mntpnt);
|
|
||||||
} /* while */
|
|
||||||
} /* tryDir */
|
|
||||||
|
|
||||||
|
|
||||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
|
||||||
{
|
|
||||||
tryDir("/dev/disk", cb, data);
|
|
||||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
|
||||||
|
|
||||||
|
|
||||||
static team_id getTeamID(void)
|
|
||||||
{
|
|
||||||
thread_info info;
|
|
||||||
thread_id tid = find_thread(NULL);
|
|
||||||
get_thread_info(tid, &info);
|
|
||||||
return info.team;
|
|
||||||
} /* getTeamID */
|
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
|
||||||
{
|
|
||||||
image_info info;
|
|
||||||
int32 cookie = 0;
|
|
||||||
|
|
||||||
while (get_next_image_info(0, &cookie, &info) == B_OK)
|
|
||||||
{
|
|
||||||
if (info.type == B_APP_IMAGE)
|
|
||||||
break;
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
BEntry entry(info.name, true);
|
|
||||||
BPath path;
|
|
||||||
status_t rc = entry.GetPath(&path); /* (path) now has binary's path. */
|
|
||||||
assert(rc == B_OK);
|
|
||||||
rc = path.GetParent(&path); /* chop filename, keep directory. */
|
|
||||||
assert(rc == B_OK);
|
|
||||||
const char *str = path.Path();
|
|
||||||
assert(str != NULL);
|
|
||||||
const size_t len = strlen(str);
|
|
||||||
char *retval = (char *) allocator.Malloc(len + 2);
|
|
||||||
BAIL_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
strcpy(retval, str);
|
|
||||||
retval[len] = '/';
|
|
||||||
retval[len+1] = '\0';
|
|
||||||
return retval;
|
|
||||||
} /* __PHYSFS_platformCalcBaseDir */
|
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app)
|
|
||||||
{
|
|
||||||
const char *userdir = __PHYSFS_getUserDir();
|
|
||||||
const char *append = "config/settings/";
|
|
||||||
const size_t len = strlen(userdir) + strlen(append) + strlen(app) + 2;
|
|
||||||
char *retval = (char *) allocator.Malloc(len);
|
|
||||||
BAIL_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
snprintf(retval, len, "%s%s%s/", userdir, append, app);
|
|
||||||
return retval;
|
|
||||||
} /* __PHYSFS_platformCalcPrefDir */
|
|
||||||
|
|
||||||
#endif /* PHYSFS_PLATFORM_HAIKU */
|
|
||||||
|
|
||||||
/* end of physfs_platform_haiku.cpp ... */
|
|
||||||
|
|
417
third_party/physfs/physfs_platform_posix.c
vendored
417
third_party/physfs/physfs_platform_posix.c
vendored
|
@ -1,417 +0,0 @@
|
||||||
/*
|
|
||||||
* Posix-esque support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* !!! FIXME: check for EINTR? */
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_platforms.h"
|
|
||||||
|
|
||||||
#ifdef PHYSFS_PLATFORM_POSIX
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
|
|
||||||
static PHYSFS_ErrorCode errcodeFromErrnoError(const int err)
|
|
||||||
{
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
case 0: return PHYSFS_ERR_OK;
|
|
||||||
case EACCES: return PHYSFS_ERR_PERMISSION;
|
|
||||||
case EPERM: return PHYSFS_ERR_PERMISSION;
|
|
||||||
case EDQUOT: return PHYSFS_ERR_NO_SPACE;
|
|
||||||
case EIO: return PHYSFS_ERR_IO;
|
|
||||||
case ELOOP: return PHYSFS_ERR_SYMLINK_LOOP;
|
|
||||||
case EMLINK: return PHYSFS_ERR_NO_SPACE;
|
|
||||||
case ENAMETOOLONG: return PHYSFS_ERR_BAD_FILENAME;
|
|
||||||
case ENOENT: return PHYSFS_ERR_NOT_FOUND;
|
|
||||||
case ENOSPC: return PHYSFS_ERR_NO_SPACE;
|
|
||||||
case ENOTDIR: return PHYSFS_ERR_NOT_FOUND;
|
|
||||||
case EISDIR: return PHYSFS_ERR_NOT_A_FILE;
|
|
||||||
case EROFS: return PHYSFS_ERR_READ_ONLY;
|
|
||||||
case ETXTBSY: return PHYSFS_ERR_BUSY;
|
|
||||||
case EBUSY: return PHYSFS_ERR_BUSY;
|
|
||||||
case ENOMEM: return PHYSFS_ERR_OUT_OF_MEMORY;
|
|
||||||
case ENOTEMPTY: return PHYSFS_ERR_DIR_NOT_EMPTY;
|
|
||||||
default: return PHYSFS_ERR_OS_ERROR;
|
|
||||||
} /* switch */
|
|
||||||
} /* errcodeFromErrnoError */
|
|
||||||
|
|
||||||
|
|
||||||
static inline PHYSFS_ErrorCode errcodeFromErrno(void)
|
|
||||||
{
|
|
||||||
return errcodeFromErrnoError(errno);
|
|
||||||
} /* errcodeFromErrno */
|
|
||||||
|
|
||||||
|
|
||||||
static char *getUserDirByUID(void)
|
|
||||||
{
|
|
||||||
uid_t uid = getuid();
|
|
||||||
struct passwd *pw;
|
|
||||||
char *retval = NULL;
|
|
||||||
|
|
||||||
pw = getpwuid(uid);
|
|
||||||
if ((pw != NULL) && (pw->pw_dir != NULL) && (*pw->pw_dir != '\0'))
|
|
||||||
{
|
|
||||||
const size_t dlen = strlen(pw->pw_dir);
|
|
||||||
const size_t add_dirsep = (pw->pw_dir[dlen-1] != '/') ? 1 : 0;
|
|
||||||
retval = (char *) allocator.Malloc(dlen + 1 + add_dirsep);
|
|
||||||
if (retval != NULL)
|
|
||||||
{
|
|
||||||
strcpy(retval, pw->pw_dir);
|
|
||||||
if (add_dirsep)
|
|
||||||
{
|
|
||||||
retval[dlen] = '/';
|
|
||||||
retval[dlen+1] = '\0';
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
} /* getUserDirByUID */
|
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformCalcUserDir(void)
|
|
||||||
{
|
|
||||||
char *retval = NULL;
|
|
||||||
char *envr = getenv("HOME");
|
|
||||||
|
|
||||||
/* if the environment variable was set, make sure it's really a dir. */
|
|
||||||
if (envr != NULL)
|
|
||||||
{
|
|
||||||
struct stat statbuf;
|
|
||||||
if ((stat(envr, &statbuf) != -1) && (S_ISDIR(statbuf.st_mode)))
|
|
||||||
{
|
|
||||||
const size_t envrlen = strlen(envr);
|
|
||||||
const size_t add_dirsep = (envr[envrlen-1] != '/') ? 1 : 0;
|
|
||||||
retval = allocator.Malloc(envrlen + 1 + add_dirsep);
|
|
||||||
if (retval)
|
|
||||||
{
|
|
||||||
strcpy(retval, envr);
|
|
||||||
if (add_dirsep)
|
|
||||||
{
|
|
||||||
retval[envrlen] = '/';
|
|
||||||
retval[envrlen+1] = '\0';
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (retval == NULL)
|
|
||||||
retval = getUserDirByUID();
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
} /* __PHYSFS_platformCalcUserDir */
|
|
||||||
|
|
||||||
|
|
||||||
PHYSFS_EnumerateCallbackResult __PHYSFS_platformEnumerate(const char *dirname,
|
|
||||||
PHYSFS_EnumerateCallback callback,
|
|
||||||
const char *origdir, void *callbackdata)
|
|
||||||
{
|
|
||||||
DIR *dir;
|
|
||||||
struct dirent *ent;
|
|
||||||
PHYSFS_EnumerateCallbackResult retval = PHYSFS_ENUM_OK;
|
|
||||||
|
|
||||||
dir = opendir(dirname);
|
|
||||||
BAIL_IF(dir == NULL, errcodeFromErrno(), PHYSFS_ENUM_ERROR);
|
|
||||||
|
|
||||||
while ((retval == PHYSFS_ENUM_OK) && ((ent = readdir(dir)) != NULL))
|
|
||||||
{
|
|
||||||
const char *name = ent->d_name;
|
|
||||||
if (name[0] == '.') /* ignore "." and ".." */
|
|
||||||
{
|
|
||||||
if ((name[1] == '\0') || ((name[1] == '.') && (name[2] == '\0')))
|
|
||||||
continue;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
retval = callback(callbackdata, origdir, name);
|
|
||||||
if (retval == PHYSFS_ENUM_ERROR)
|
|
||||||
PHYSFS_setErrorCode(PHYSFS_ERR_APP_CALLBACK);
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
} /* __PHYSFS_platformEnumerate */
|
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformMkDir(const char *path)
|
|
||||||
{
|
|
||||||
const int rc = mkdir(path, S_IRWXU);
|
|
||||||
BAIL_IF(rc == -1, errcodeFromErrno(), 0);
|
|
||||||
return 1;
|
|
||||||
} /* __PHYSFS_platformMkDir */
|
|
||||||
|
|
||||||
|
|
||||||
static void *doOpen(const char *filename, int mode)
|
|
||||||
{
|
|
||||||
const int appending = (mode & O_APPEND);
|
|
||||||
int fd;
|
|
||||||
int *retval;
|
|
||||||
errno = 0;
|
|
||||||
|
|
||||||
/* O_APPEND doesn't actually behave as we'd like. */
|
|
||||||
mode &= ~O_APPEND;
|
|
||||||
|
|
||||||
fd = open(filename, mode, S_IRUSR | S_IWUSR);
|
|
||||||
BAIL_IF(fd < 0, errcodeFromErrno(), NULL);
|
|
||||||
|
|
||||||
if (appending)
|
|
||||||
{
|
|
||||||
if (lseek(fd, 0, SEEK_END) < 0)
|
|
||||||
{
|
|
||||||
const int err = errno;
|
|
||||||
close(fd);
|
|
||||||
BAIL(errcodeFromErrnoError(err), NULL);
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
retval = (int *) allocator.Malloc(sizeof (int));
|
|
||||||
if (!retval)
|
|
||||||
{
|
|
||||||
close(fd);
|
|
||||||
BAIL(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
*retval = fd;
|
|
||||||
return ((void *) retval);
|
|
||||||
} /* doOpen */
|
|
||||||
|
|
||||||
|
|
||||||
void *__PHYSFS_platformOpenRead(const char *filename)
|
|
||||||
{
|
|
||||||
return doOpen(filename, O_RDONLY);
|
|
||||||
} /* __PHYSFS_platformOpenRead */
|
|
||||||
|
|
||||||
|
|
||||||
void *__PHYSFS_platformOpenWrite(const char *filename)
|
|
||||||
{
|
|
||||||
return doOpen(filename, O_WRONLY | O_CREAT | O_TRUNC);
|
|
||||||
} /* __PHYSFS_platformOpenWrite */
|
|
||||||
|
|
||||||
|
|
||||||
void *__PHYSFS_platformOpenAppend(const char *filename)
|
|
||||||
{
|
|
||||||
return doOpen(filename, O_WRONLY | O_CREAT | O_APPEND);
|
|
||||||
} /* __PHYSFS_platformOpenAppend */
|
|
||||||
|
|
||||||
|
|
||||||
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
|
|
||||||
PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
const int fd = *((int *) opaque);
|
|
||||||
ssize_t rc = 0;
|
|
||||||
|
|
||||||
if (!__PHYSFS_ui64FitsAddressSpace(len))
|
|
||||||
BAIL(PHYSFS_ERR_INVALID_ARGUMENT, -1);
|
|
||||||
|
|
||||||
rc = read(fd, buffer, (size_t) len);
|
|
||||||
BAIL_IF(rc == -1, errcodeFromErrno(), -1);
|
|
||||||
assert(rc >= 0);
|
|
||||||
assert(rc <= len);
|
|
||||||
return (PHYSFS_sint64) rc;
|
|
||||||
} /* __PHYSFS_platformRead */
|
|
||||||
|
|
||||||
|
|
||||||
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
|
|
||||||
PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
const int fd = *((int *) opaque);
|
|
||||||
ssize_t rc = 0;
|
|
||||||
|
|
||||||
if (!__PHYSFS_ui64FitsAddressSpace(len))
|
|
||||||
BAIL(PHYSFS_ERR_INVALID_ARGUMENT, -1);
|
|
||||||
|
|
||||||
rc = write(fd, (void *) buffer, (size_t) len);
|
|
||||||
BAIL_IF(rc == -1, errcodeFromErrno(), rc);
|
|
||||||
assert(rc >= 0);
|
|
||||||
assert(rc <= len);
|
|
||||||
return (PHYSFS_sint64) rc;
|
|
||||||
} /* __PHYSFS_platformWrite */
|
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
|
|
||||||
{
|
|
||||||
const int fd = *((int *) opaque);
|
|
||||||
const off_t rc = lseek(fd, (off_t) pos, SEEK_SET);
|
|
||||||
BAIL_IF(rc == -1, errcodeFromErrno(), 0);
|
|
||||||
return 1;
|
|
||||||
} /* __PHYSFS_platformSeek */
|
|
||||||
|
|
||||||
|
|
||||||
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
|
|
||||||
{
|
|
||||||
const int fd = *((int *) opaque);
|
|
||||||
PHYSFS_sint64 retval;
|
|
||||||
retval = (PHYSFS_sint64) lseek(fd, 0, SEEK_CUR);
|
|
||||||
BAIL_IF(retval == -1, errcodeFromErrno(), -1);
|
|
||||||
return retval;
|
|
||||||
} /* __PHYSFS_platformTell */
|
|
||||||
|
|
||||||
|
|
||||||
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
|
|
||||||
{
|
|
||||||
const int fd = *((int *) opaque);
|
|
||||||
struct stat statbuf;
|
|
||||||
BAIL_IF(fstat(fd, &statbuf) == -1, errcodeFromErrno(), -1);
|
|
||||||
return ((PHYSFS_sint64) statbuf.st_size);
|
|
||||||
} /* __PHYSFS_platformFileLength */
|
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformFlush(void *opaque)
|
|
||||||
{
|
|
||||||
const int fd = *((int *) opaque);
|
|
||||||
if ((fcntl(fd, F_GETFL) & O_ACCMODE) != O_RDONLY)
|
|
||||||
BAIL_IF(fsync(fd) == -1, errcodeFromErrno(), 0);
|
|
||||||
return 1;
|
|
||||||
} /* __PHYSFS_platformFlush */
|
|
||||||
|
|
||||||
|
|
||||||
void __PHYSFS_platformClose(void *opaque)
|
|
||||||
{
|
|
||||||
const int fd = *((int *) opaque);
|
|
||||||
(void) close(fd); /* we don't check this. You should have used flush! */
|
|
||||||
allocator.Free(opaque);
|
|
||||||
} /* __PHYSFS_platformClose */
|
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformDelete(const char *path)
|
|
||||||
{
|
|
||||||
BAIL_IF(remove(path) == -1, errcodeFromErrno(), 0);
|
|
||||||
return 1;
|
|
||||||
} /* __PHYSFS_platformDelete */
|
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformStat(const char *fname, PHYSFS_Stat *st, const int follow)
|
|
||||||
{
|
|
||||||
struct stat statbuf;
|
|
||||||
const int rc = follow ? stat(fname, &statbuf) : lstat(fname, &statbuf);
|
|
||||||
BAIL_IF(rc == -1, errcodeFromErrno(), 0);
|
|
||||||
|
|
||||||
if (S_ISREG(statbuf.st_mode))
|
|
||||||
{
|
|
||||||
st->filetype = PHYSFS_FILETYPE_REGULAR;
|
|
||||||
st->filesize = statbuf.st_size;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
else if(S_ISDIR(statbuf.st_mode))
|
|
||||||
{
|
|
||||||
st->filetype = PHYSFS_FILETYPE_DIRECTORY;
|
|
||||||
st->filesize = 0;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else if(S_ISLNK(statbuf.st_mode))
|
|
||||||
{
|
|
||||||
st->filetype = PHYSFS_FILETYPE_SYMLINK;
|
|
||||||
st->filesize = 0;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
st->filetype = PHYSFS_FILETYPE_OTHER;
|
|
||||||
st->filesize = statbuf.st_size;
|
|
||||||
} /* else */
|
|
||||||
|
|
||||||
st->modtime = statbuf.st_mtime;
|
|
||||||
st->createtime = statbuf.st_ctime;
|
|
||||||
st->accesstime = statbuf.st_atime;
|
|
||||||
|
|
||||||
st->readonly = (access(fname, W_OK) == -1);
|
|
||||||
return 1;
|
|
||||||
} /* __PHYSFS_platformStat */
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
pthread_t owner;
|
|
||||||
PHYSFS_uint32 count;
|
|
||||||
} PthreadMutex;
|
|
||||||
|
|
||||||
|
|
||||||
void *__PHYSFS_platformGetThreadID(void)
|
|
||||||
{
|
|
||||||
return ( (void *) ((size_t) pthread_self()) );
|
|
||||||
} /* __PHYSFS_platformGetThreadID */
|
|
||||||
|
|
||||||
|
|
||||||
void *__PHYSFS_platformCreateMutex(void)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
PthreadMutex *m = (PthreadMutex *) allocator.Malloc(sizeof (PthreadMutex));
|
|
||||||
BAIL_IF(!m, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
rc = pthread_mutex_init(&m->mutex, NULL);
|
|
||||||
if (rc != 0)
|
|
||||||
{
|
|
||||||
allocator.Free(m);
|
|
||||||
BAIL(PHYSFS_ERR_OS_ERROR, NULL);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
m->count = 0;
|
|
||||||
m->owner = (pthread_t) 0xDEADBEEF;
|
|
||||||
return ((void *) m);
|
|
||||||
} /* __PHYSFS_platformCreateMutex */
|
|
||||||
|
|
||||||
|
|
||||||
void __PHYSFS_platformDestroyMutex(void *mutex)
|
|
||||||
{
|
|
||||||
PthreadMutex *m = (PthreadMutex *) mutex;
|
|
||||||
|
|
||||||
/* Destroying a locked mutex is a bug, but we'll try to be helpful. */
|
|
||||||
if ((m->owner == pthread_self()) && (m->count > 0))
|
|
||||||
pthread_mutex_unlock(&m->mutex);
|
|
||||||
|
|
||||||
pthread_mutex_destroy(&m->mutex);
|
|
||||||
allocator.Free(m);
|
|
||||||
} /* __PHYSFS_platformDestroyMutex */
|
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformGrabMutex(void *mutex)
|
|
||||||
{
|
|
||||||
PthreadMutex *m = (PthreadMutex *) mutex;
|
|
||||||
pthread_t tid = pthread_self();
|
|
||||||
if (m->owner != tid)
|
|
||||||
{
|
|
||||||
if (pthread_mutex_lock(&m->mutex) != 0)
|
|
||||||
return 0;
|
|
||||||
m->owner = tid;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
m->count++;
|
|
||||||
return 1;
|
|
||||||
} /* __PHYSFS_platformGrabMutex */
|
|
||||||
|
|
||||||
|
|
||||||
void __PHYSFS_platformReleaseMutex(void *mutex)
|
|
||||||
{
|
|
||||||
PthreadMutex *m = (PthreadMutex *) mutex;
|
|
||||||
assert(m->owner == pthread_self()); /* catch programming errors. */
|
|
||||||
assert(m->count > 0); /* catch programming errors. */
|
|
||||||
if (m->owner == pthread_self())
|
|
||||||
{
|
|
||||||
if (--m->count == 0)
|
|
||||||
{
|
|
||||||
m->owner = (pthread_t) 0xDEADBEEF;
|
|
||||||
pthread_mutex_unlock(&m->mutex);
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
} /* __PHYSFS_platformReleaseMutex */
|
|
||||||
|
|
||||||
#endif /* PHYSFS_PLATFORM_POSIX */
|
|
||||||
|
|
||||||
/* end of physfs_platform_posix.c ... */
|
|
||||||
|
|
367
third_party/physfs/physfs_platform_unix.c
vendored
367
third_party/physfs/physfs_platform_unix.c
vendored
|
@ -1,367 +0,0 @@
|
||||||
/*
|
|
||||||
* Unix support routines for PhysicsFS.
|
|
||||||
*
|
|
||||||
* Please see the file LICENSE.txt in the source's root directory.
|
|
||||||
*
|
|
||||||
* This file written by Ryan C. Gordon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_platforms.h"
|
|
||||||
|
|
||||||
#ifdef PHYSFS_PLATFORM_UNIX
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#if PHYSFS_NO_CDROM_SUPPORT
|
|
||||||
#elif PHYSFS_PLATFORM_LINUX
|
|
||||||
# define PHYSFS_HAVE_MNTENT_H 1
|
|
||||||
#elif defined __CYGWIN__
|
|
||||||
# define PHYSFS_HAVE_MNTENT_H 1
|
|
||||||
#elif PHYSFS_PLATFORM_SOLARIS
|
|
||||||
# define PHYSFS_HAVE_SYS_MNTTAB_H 1
|
|
||||||
#elif PHYSFS_PLATFORM_BSD
|
|
||||||
# define PHYSFS_HAVE_SYS_UCRED_H 1
|
|
||||||
#else
|
|
||||||
# warning No CD-ROM support included. Either define your platform here,
|
|
||||||
# warning or define PHYSFS_NO_CDROM_SUPPORT=1 to confirm this is intentional.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PHYSFS_HAVE_SYS_UCRED_H
|
|
||||||
# ifdef PHYSFS_HAVE_MNTENT_H
|
|
||||||
# undef PHYSFS_HAVE_MNTENT_H /* don't do both... */
|
|
||||||
# endif
|
|
||||||
# include <sys/mount.h>
|
|
||||||
# include <sys/ucred.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PHYSFS_HAVE_MNTENT_H
|
|
||||||
#include <mntent.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PHYSFS_HAVE_SYS_MNTTAB_H
|
|
||||||
#include <sys/mnttab.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PHYSFS_PLATFORM_FREEBSD
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
int __PHYSFS_platformInit(void)
|
|
||||||
{
|
|
||||||
return 1; /* always succeed. */
|
|
||||||
} /* __PHYSFS_platformInit */
|
|
||||||
|
|
||||||
|
|
||||||
void __PHYSFS_platformDeinit(void)
|
|
||||||
{
|
|
||||||
/* no-op */
|
|
||||||
} /* __PHYSFS_platformDeinit */
|
|
||||||
|
|
||||||
|
|
||||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
|
||||||
{
|
|
||||||
#if (defined PHYSFS_NO_CDROM_SUPPORT)
|
|
||||||
/* no-op. */
|
|
||||||
|
|
||||||
#elif (defined PHYSFS_HAVE_SYS_UCRED_H)
|
|
||||||
int i;
|
|
||||||
struct statfs *mntbufp = NULL;
|
|
||||||
int mounts = getmntinfo(&mntbufp, MNT_NOWAIT);
|
|
||||||
|
|
||||||
for (i = 0; i < mounts; i++)
|
|
||||||
{
|
|
||||||
int add_it = 0;
|
|
||||||
|
|
||||||
if (strcmp(mntbufp[i].f_fstypename, "iso9660") == 0)
|
|
||||||
add_it = 1;
|
|
||||||
else if (strcmp( mntbufp[i].f_fstypename, "cd9660") == 0)
|
|
||||||
add_it = 1;
|
|
||||||
|
|
||||||
/* add other mount types here */
|
|
||||||
|
|
||||||
if (add_it)
|
|
||||||
cb(data, mntbufp[i].f_mntonname);
|
|
||||||
} /* for */
|
|
||||||
|
|
||||||
#elif (defined PHYSFS_HAVE_MNTENT_H)
|
|
||||||
FILE *mounts = NULL;
|
|
||||||
struct mntent *ent = NULL;
|
|
||||||
|
|
||||||
mounts = setmntent("/etc/mtab", "r");
|
|
||||||
BAIL_IF(mounts == NULL, PHYSFS_ERR_IO, /*return void*/);
|
|
||||||
|
|
||||||
while ( (ent = getmntent(mounts)) != NULL )
|
|
||||||
{
|
|
||||||
int add_it = 0;
|
|
||||||
if (strcmp(ent->mnt_type, "iso9660") == 0)
|
|
||||||
add_it = 1;
|
|
||||||
else if (strcmp(ent->mnt_type, "udf") == 0)
|
|
||||||
add_it = 1;
|
|
||||||
|
|
||||||
/* !!! FIXME: these might pick up floppy drives, right? */
|
|
||||||
else if (strcmp(ent->mnt_type, "auto") == 0)
|
|
||||||
add_it = 1;
|
|
||||||
else if (strcmp(ent->mnt_type, "supermount") == 0)
|
|
||||||
add_it = 1;
|
|
||||||
|
|
||||||
/* add other mount types here */
|
|
||||||
|
|
||||||
if (add_it)
|
|
||||||
cb(data, ent->mnt_dir);
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
endmntent(mounts);
|
|
||||||
|
|
||||||
#elif (defined PHYSFS_HAVE_SYS_MNTTAB_H)
|
|
||||||
FILE *mounts = fopen(MNTTAB, "r");
|
|
||||||
struct mnttab ent;
|
|
||||||
|
|
||||||
BAIL_IF(mounts == NULL, PHYSFS_ERR_IO, /*return void*/);
|
|
||||||
while (getmntent(mounts, &ent) == 0)
|
|
||||||
{
|
|
||||||
int add_it = 0;
|
|
||||||
if (strcmp(ent.mnt_fstype, "hsfs") == 0)
|
|
||||||
add_it = 1;
|
|
||||||
|
|
||||||
/* add other mount types here */
|
|
||||||
|
|
||||||
if (add_it)
|
|
||||||
cb(data, ent.mnt_mountp);
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
fclose(mounts);
|
|
||||||
#endif
|
|
||||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See where program (bin) resides in the $PATH specified by (envr).
|
|
||||||
* returns a copy of the first element in envr that contains it, or NULL
|
|
||||||
* if it doesn't exist or there were other problems. PHYSFS_SetError() is
|
|
||||||
* called if we have a problem.
|
|
||||||
*
|
|
||||||
* (envr) will be scribbled over, and you are expected to allocator.Free() the
|
|
||||||
* return value when you're done with it.
|
|
||||||
*/
|
|
||||||
static char *findBinaryInPath(const char *bin, char *envr)
|
|
||||||
{
|
|
||||||
size_t alloc_size = 0;
|
|
||||||
char *exe = NULL;
|
|
||||||
char *start = envr;
|
|
||||||
char *ptr;
|
|
||||||
|
|
||||||
assert(bin != NULL);
|
|
||||||
assert(envr != NULL);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
size_t binlen;
|
|
||||||
|
|
||||||
ptr = strchr(start, ':'); /* find next $PATH separator. */
|
|
||||||
if (ptr)
|
|
||||||
*ptr = '\0';
|
|
||||||
|
|
||||||
binlen = strlen(bin);
|
|
||||||
size = strlen(start) + binlen + 2;
|
|
||||||
if (size >= alloc_size)
|
|
||||||
{
|
|
||||||
char *x = (char *) allocator.Realloc(exe, size);
|
|
||||||
if (!x)
|
|
||||||
{
|
|
||||||
if (exe != NULL)
|
|
||||||
allocator.Free(exe);
|
|
||||||
BAIL(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
alloc_size = size;
|
|
||||||
exe = x;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
/* build full binary path... */
|
|
||||||
strcpy(exe, start);
|
|
||||||
if ((exe[0] == '\0') || (exe[strlen(exe) - 1] != '/'))
|
|
||||||
strcat(exe, "/");
|
|
||||||
strcat(exe, bin);
|
|
||||||
|
|
||||||
if (access(exe, X_OK) == 0) /* Exists as executable? We're done. */
|
|
||||||
{
|
|
||||||
exe[(size - binlen) - 1] = '\0'; /* chop off filename, leave '/' */
|
|
||||||
return exe;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
start = ptr + 1; /* start points to beginning of next element. */
|
|
||||||
} while (ptr != NULL);
|
|
||||||
|
|
||||||
if (exe != NULL)
|
|
||||||
allocator.Free(exe);
|
|
||||||
|
|
||||||
return NULL; /* doesn't exist in path. */
|
|
||||||
} /* findBinaryInPath */
|
|
||||||
|
|
||||||
|
|
||||||
static char *readSymLink(const char *path)
|
|
||||||
{
|
|
||||||
ssize_t len = 64;
|
|
||||||
ssize_t rc = -1;
|
|
||||||
char *retval = NULL;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
char *ptr = (char *) allocator.Realloc(retval, (size_t) len);
|
|
||||||
if (ptr == NULL)
|
|
||||||
break; /* out of memory. */
|
|
||||||
retval = ptr;
|
|
||||||
|
|
||||||
rc = readlink(path, retval, len);
|
|
||||||
if (rc == -1)
|
|
||||||
break; /* not a symlink, i/o error, etc. */
|
|
||||||
|
|
||||||
else if (rc < len)
|
|
||||||
{
|
|
||||||
retval[rc] = '\0'; /* readlink doesn't null-terminate. */
|
|
||||||
return retval; /* we're good to go. */
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
len *= 2; /* grow buffer, try again. */
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
if (retval != NULL)
|
|
||||||
allocator.Free(retval);
|
|
||||||
return NULL;
|
|
||||||
} /* readSymLink */
|
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
|
||||||
{
|
|
||||||
char *retval = NULL;
|
|
||||||
const char *envr = NULL;
|
|
||||||
|
|
||||||
/* Try to avoid using argv0 unless forced to. Try system-specific stuff. */
|
|
||||||
|
|
||||||
#if defined(PHYSFS_PLATFORM_FREEBSD)
|
|
||||||
{
|
|
||||||
char fullpath[PATH_MAX];
|
|
||||||
size_t buflen = sizeof (fullpath);
|
|
||||||
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
|
|
||||||
if (sysctl(mib, 4, fullpath, &buflen, NULL, 0) != -1)
|
|
||||||
retval = __PHYSFS_strdup(fullpath);
|
|
||||||
}
|
|
||||||
#elif defined(PHYSFS_PLATFORM_SOLARIS)
|
|
||||||
{
|
|
||||||
const char *path = getexecname();
|
|
||||||
if ((path != NULL) && (path[0] == '/')) /* must be absolute path... */
|
|
||||||
retval = __PHYSFS_strdup(path);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If there's a Linux-like /proc filesystem, you can get the full path to
|
|
||||||
* the current process from a symlink in there.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!retval && (access("/proc", F_OK) == 0))
|
|
||||||
{
|
|
||||||
retval = readSymLink("/proc/self/exe");
|
|
||||||
if (!retval) retval = readSymLink("/proc/curproc/file");
|
|
||||||
if (!retval) retval = readSymLink("/proc/curproc/exe");
|
|
||||||
if (retval == NULL)
|
|
||||||
{
|
|
||||||
/* older kernels don't have /proc/self ... try PID version... */
|
|
||||||
const unsigned long long pid = (unsigned long long) getpid();
|
|
||||||
char path[64];
|
|
||||||
const int rc = (int) snprintf(path,sizeof(path),"/proc/%llu/exe",pid);
|
|
||||||
if ( (rc > 0) && (rc < sizeof(path)) )
|
|
||||||
retval = readSymLink(path);
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (retval != NULL) /* chop off filename. */
|
|
||||||
{
|
|
||||||
char *ptr = strrchr(retval, '/');
|
|
||||||
if (ptr != NULL)
|
|
||||||
*(ptr+1) = '\0';
|
|
||||||
else /* shouldn't happen, but just in case... */
|
|
||||||
{
|
|
||||||
allocator.Free(retval);
|
|
||||||
retval = NULL;
|
|
||||||
} /* else */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
/* No /proc/self/exe, etc, but we have an argv[0] we can parse? */
|
|
||||||
if ((retval == NULL) && (argv0 != NULL))
|
|
||||||
{
|
|
||||||
/* fast path: default behaviour can handle this. */
|
|
||||||
if (strchr(argv0, '/') != NULL)
|
|
||||||
return NULL; /* higher level parses out real path from argv0. */
|
|
||||||
|
|
||||||
/* If there's no dirsep on argv0, then look through $PATH for it. */
|
|
||||||
envr = getenv("PATH");
|
|
||||||
if (envr != NULL)
|
|
||||||
{
|
|
||||||
char *path = (char *) __PHYSFS_smallAlloc(strlen(envr) + 1);
|
|
||||||
BAIL_IF(!path, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
strcpy(path, envr);
|
|
||||||
retval = findBinaryInPath(argv0, path);
|
|
||||||
__PHYSFS_smallFree(path);
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
if (retval != NULL)
|
|
||||||
{
|
|
||||||
/* try to shrink buffer... */
|
|
||||||
char *ptr = (char *) allocator.Realloc(retval, strlen(retval) + 1);
|
|
||||||
if (ptr != NULL)
|
|
||||||
retval = ptr; /* oh well if it failed. */
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
} /* __PHYSFS_platformCalcBaseDir */
|
|
||||||
|
|
||||||
|
|
||||||
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* We use XDG's base directory spec, even if you're not on Linux.
|
|
||||||
* This isn't strictly correct, but the results are relatively sane
|
|
||||||
* in any case.
|
|
||||||
*
|
|
||||||
* https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
|
||||||
*/
|
|
||||||
const char *envr = getenv("XDG_DATA_HOME");
|
|
||||||
const char *append = "/";
|
|
||||||
char *retval = NULL;
|
|
||||||
size_t len = 0;
|
|
||||||
|
|
||||||
if (!envr)
|
|
||||||
{
|
|
||||||
/* You end up with "$HOME/.local/share/Game Name 2" */
|
|
||||||
envr = __PHYSFS_getUserDir();
|
|
||||||
BAIL_IF_ERRPASS(!envr, NULL); /* oh well. */
|
|
||||||
append = ".local/share/";
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
len = strlen(envr) + strlen(append) + strlen(app) + 2;
|
|
||||||
retval = (char *) allocator.Malloc(len);
|
|
||||||
BAIL_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
|
||||||
snprintf(retval, len, "%s%s%s/", envr, append, app);
|
|
||||||
return retval;
|
|
||||||
} /* __PHYSFS_platformCalcPrefDir */
|
|
||||||
|
|
||||||
#endif /* PHYSFS_PLATFORM_UNIX */
|
|
||||||
|
|
||||||
/* end of physfs_platform_unix.c ... */
|
|
||||||
|
|
1028
third_party/physfs/physfs_platform_windows.c
vendored
1028
third_party/physfs/physfs_platform_windows.c
vendored
File diff suppressed because it is too large
Load diff
80
third_party/physfs/physfs_platforms.h
vendored
80
third_party/physfs/physfs_platforms.h
vendored
|
@ -1,80 +0,0 @@
|
||||||
#ifndef _INCL_PHYSFS_PLATFORMS
|
|
||||||
#define _INCL_PHYSFS_PLATFORMS
|
|
||||||
|
|
||||||
#ifndef __PHYSICSFS_INTERNAL__
|
|
||||||
#error Do not include this header from your applications.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These only define the platforms to determine which files in the platforms
|
|
||||||
* directory should be compiled. For example, technically BeOS can be called
|
|
||||||
* a "unix" system, but since it doesn't use unix.c, we don't define
|
|
||||||
* PHYSFS_PLATFORM_UNIX on that system.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (defined __HAIKU__)
|
|
||||||
# define PHYSFS_PLATFORM_HAIKU 1
|
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
|
||||||
#elif ((defined __BEOS__) || (defined __beos__))
|
|
||||||
# error BeOS support was dropped since PhysicsFS 2.1. Sorry. Try Haiku!
|
|
||||||
#elif (defined _WIN32_WCE) || (defined _WIN64_WCE)
|
|
||||||
# error PocketPC support was dropped since PhysicsFS 2.1. Sorry. Try WinRT!
|
|
||||||
#elif (defined(_MSC_VER) && (_MSC_VER >= 1700) && !_USING_V110_SDK71_) /* _MSC_VER==1700 for MSVC 2012 */
|
|
||||||
# include <winapifamily.h>
|
|
||||||
# define PHYSFS_PLATFORM_WINDOWS 1
|
|
||||||
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
|
||||||
# define PHYSFS_NO_CDROM_SUPPORT 1
|
|
||||||
# define PHYSFS_PLATFORM_WINRT 1
|
|
||||||
# endif
|
|
||||||
#elif (((defined _WIN32) || (defined _WIN64)) && (!defined __CYGWIN__))
|
|
||||||
# define PHYSFS_PLATFORM_WINDOWS 1
|
|
||||||
#elif defined(__OS2__) || defined(OS2)
|
|
||||||
# define PHYSFS_PLATFORM_OS2 1
|
|
||||||
#elif ((defined __MACH__) && (defined __APPLE__))
|
|
||||||
/* To check if iOS or not, we need to include this file */
|
|
||||||
# include <TargetConditionals.h>
|
|
||||||
# if ((TARGET_IPHONE_SIMULATOR) || (TARGET_OS_IPHONE))
|
|
||||||
# define PHYSFS_NO_CDROM_SUPPORT 1
|
|
||||||
# endif
|
|
||||||
# define PHYSFS_PLATFORM_APPLE 1
|
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
|
||||||
#elif defined(macintosh)
|
|
||||||
# error Classic Mac OS support was dropped from PhysicsFS 2.0. Move to OS X.
|
|
||||||
#elif defined(ANDROID)
|
|
||||||
# define PHYSFS_PLATFORM_LINUX 1
|
|
||||||
# define PHYSFS_PLATFORM_UNIX 1
|
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
|
||||||
# define PHYSFS_NO_CDROM_SUPPORT 1
|
|
||||||
#elif defined(__linux)
|
|
||||||
# define PHYSFS_PLATFORM_LINUX 1
|
|
||||||
# define PHYSFS_PLATFORM_UNIX 1
|
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
|
||||||
#elif defined(__sun) || defined(sun)
|
|
||||||
# define PHYSFS_PLATFORM_SOLARIS 1
|
|
||||||
# define PHYSFS_PLATFORM_UNIX 1
|
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
|
||||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
|
||||||
# define PHYSFS_PLATFORM_FREEBSD 1
|
|
||||||
# define PHYSFS_PLATFORM_BSD 1
|
|
||||||
# define PHYSFS_PLATFORM_UNIX 1
|
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
|
||||||
#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
|
|
||||||
# define PHYSFS_PLATFORM_BSD 1
|
|
||||||
# define PHYSFS_PLATFORM_UNIX 1
|
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
|
||||||
#elif defined(__EMSCRIPTEN__)
|
|
||||||
# define PHYSFS_NO_CDROM_SUPPORT 1
|
|
||||||
# define PHYSFS_PLATFORM_UNIX 1
|
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
|
||||||
#elif defined(__QNX__)
|
|
||||||
# define PHYSFS_PLATFORM_QNX 1
|
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
|
||||||
#elif defined(unix) || defined(__unix__)
|
|
||||||
# define PHYSFS_PLATFORM_UNIX 1
|
|
||||||
# define PHYSFS_PLATFORM_POSIX 1
|
|
||||||
#else
|
|
||||||
# error Unknown platform.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* include-once blocker. */
|
|
||||||
|
|
567
third_party/physfs/physfs_unicode.c
vendored
567
third_party/physfs/physfs_unicode.c
vendored
|
@ -1,567 +0,0 @@
|
||||||
#define __PHYSICSFS_INTERNAL__
|
|
||||||
#include "physfs_internal.h"
|
|
||||||
|
|
||||||
#include "physfs_casefolding.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* From rfc3629, the UTF-8 spec:
|
|
||||||
* https://www.ietf.org/rfc/rfc3629.txt
|
|
||||||
*
|
|
||||||
* Char. number range | UTF-8 octet sequence
|
|
||||||
* (hexadecimal) | (binary)
|
|
||||||
* --------------------+---------------------------------------------
|
|
||||||
* 0000 0000-0000 007F | 0xxxxxxx
|
|
||||||
* 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
|
|
||||||
* 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
|
||||||
* 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This may not be the best value, but it's one that isn't represented
|
|
||||||
* in Unicode (0x10FFFF is the largest codepoint value). We return this
|
|
||||||
* value from utf8codepoint() if there's bogus bits in the
|
|
||||||
* stream. utf8codepoint() will turn this value into something
|
|
||||||
* reasonable (like a question mark), for text that wants to try to recover,
|
|
||||||
* whereas utf8valid() will use the value to determine if a string has bad
|
|
||||||
* bits.
|
|
||||||
*/
|
|
||||||
#define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the codepoint we currently return when there was bogus bits in a
|
|
||||||
* UTF-8 string. May not fly in Asian locales?
|
|
||||||
*/
|
|
||||||
#define UNICODE_BOGUS_CHAR_CODEPOINT '?'
|
|
||||||
|
|
||||||
static PHYSFS_uint32 utf8codepoint(const char **_str)
|
|
||||||
{
|
|
||||||
const char *str = *_str;
|
|
||||||
PHYSFS_uint32 retval = 0;
|
|
||||||
PHYSFS_uint32 octet = (PHYSFS_uint32) ((PHYSFS_uint8) *str);
|
|
||||||
PHYSFS_uint32 octet2, octet3, octet4;
|
|
||||||
|
|
||||||
if (octet == 0) /* null terminator, end of string. */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
else if (octet < 128) /* one octet char: 0 to 127 */
|
|
||||||
{
|
|
||||||
(*_str)++; /* skip to next possible start of codepoint. */
|
|
||||||
return octet;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else if ((octet > 127) && (octet < 192)) /* bad (starts with 10xxxxxx). */
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Apparently each of these is supposed to be flagged as a bogus
|
|
||||||
* char, instead of just resyncing to the next valid codepoint.
|
|
||||||
*/
|
|
||||||
(*_str)++; /* skip to next possible start of codepoint. */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else if (octet < 224) /* two octets */
|
|
||||||
{
|
|
||||||
(*_str)++; /* advance at least one byte in case of an error */
|
|
||||||
octet -= (128+64);
|
|
||||||
octet2 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
*_str += 1; /* skip to next possible start of codepoint. */
|
|
||||||
retval = ((octet << 6) | (octet2 - 128));
|
|
||||||
if ((retval >= 0x80) && (retval <= 0x7FF))
|
|
||||||
return retval;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else if (octet < 240) /* three octets */
|
|
||||||
{
|
|
||||||
(*_str)++; /* advance at least one byte in case of an error */
|
|
||||||
octet -= (128+64+32);
|
|
||||||
octet2 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
octet3 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
*_str += 2; /* skip to next possible start of codepoint. */
|
|
||||||
retval = ( ((octet << 12)) | ((octet2-128) << 6) | ((octet3-128)) );
|
|
||||||
|
|
||||||
/* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */
|
|
||||||
switch (retval)
|
|
||||||
{
|
|
||||||
case 0xD800:
|
|
||||||
case 0xDB7F:
|
|
||||||
case 0xDB80:
|
|
||||||
case 0xDBFF:
|
|
||||||
case 0xDC00:
|
|
||||||
case 0xDF80:
|
|
||||||
case 0xDFFF:
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
} /* switch */
|
|
||||||
|
|
||||||
/* 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge. */
|
|
||||||
if ((retval >= 0x800) && (retval <= 0xFFFD))
|
|
||||||
return retval;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else if (octet < 248) /* four octets */
|
|
||||||
{
|
|
||||||
(*_str)++; /* advance at least one byte in case of an error */
|
|
||||||
octet -= (128+64+32+16);
|
|
||||||
octet2 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
octet3 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
octet4 = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet4 & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
*_str += 3; /* skip to next possible start of codepoint. */
|
|
||||||
retval = ( ((octet << 18)) | ((octet2 - 128) << 12) |
|
|
||||||
((octet3 - 128) << 6) | ((octet4 - 128)) );
|
|
||||||
if ((retval >= 0x10000) && (retval <= 0x10FFFF))
|
|
||||||
return retval;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Five and six octet sequences became illegal in rfc3629.
|
|
||||||
* We throw the codepoint away, but parse them to make sure we move
|
|
||||||
* ahead the right number of bytes and don't overflow the buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
else if (octet < 252) /* five octets */
|
|
||||||
{
|
|
||||||
(*_str)++; /* advance at least one byte in case of an error */
|
|
||||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
*_str += 4; /* skip to next possible start of codepoint. */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else /* six octets */
|
|
||||||
{
|
|
||||||
(*_str)++; /* advance at least one byte in case of an error */
|
|
||||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
octet = (PHYSFS_uint32) ((PHYSFS_uint8) *(++str));
|
|
||||||
if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
|
|
||||||
*_str += 6; /* skip to next possible start of codepoint. */
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
return UNICODE_BOGUS_CHAR_VALUE;
|
|
||||||
} /* utf8codepoint */
|
|
||||||
|
|
||||||
static PHYSFS_uint32 utf16codepoint(const PHYSFS_uint16 **_str)
|
|
||||||
{
|
|
||||||
const PHYSFS_uint16 *src = *_str;
|
|
||||||
PHYSFS_uint32 cp = (PHYSFS_uint32) *(src++);
|
|
||||||
|
|
||||||
if (cp == 0) /* null terminator, end of string. */
|
|
||||||
return 0;
|
|
||||||
/* Orphaned second half of surrogate pair? */
|
|
||||||
else if ((cp >= 0xDC00) && (cp <= 0xDFFF))
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
else if ((cp >= 0xD800) && (cp <= 0xDBFF)) /* start surrogate pair! */
|
|
||||||
{
|
|
||||||
const PHYSFS_uint32 pair = (PHYSFS_uint32) *src;
|
|
||||||
if (pair == 0)
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
else if ((pair < 0xDC00) || (pair > 0xDFFF))
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
src++; /* eat the other surrogate. */
|
|
||||||
cp = (((cp - 0xD800) << 10) | (pair - 0xDC00));
|
|
||||||
} /* else */
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
*_str = src;
|
|
||||||
return cp;
|
|
||||||
} /* utf16codepoint */
|
|
||||||
|
|
||||||
static PHYSFS_uint32 utf32codepoint(const PHYSFS_uint32 **_str)
|
|
||||||
{
|
|
||||||
const PHYSFS_uint32 *src = *_str;
|
|
||||||
PHYSFS_uint32 cp = *(src++);
|
|
||||||
|
|
||||||
if (cp == 0) /* null terminator, end of string. */
|
|
||||||
return 0;
|
|
||||||
else if (cp > 0x10FFF)
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
|
|
||||||
*_str = src;
|
|
||||||
return cp;
|
|
||||||
} /* utf32codepoint */
|
|
||||||
|
|
||||||
|
|
||||||
void PHYSFS_utf8ToUcs4(const char *src, PHYSFS_uint32 *dst, PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
len -= sizeof (PHYSFS_uint32); /* save room for null char. */
|
|
||||||
while (len >= sizeof (PHYSFS_uint32))
|
|
||||||
{
|
|
||||||
PHYSFS_uint32 cp = utf8codepoint(&src);
|
|
||||||
if (cp == 0)
|
|
||||||
break;
|
|
||||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
*(dst++) = cp;
|
|
||||||
len -= sizeof (PHYSFS_uint32);
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
*dst = 0;
|
|
||||||
} /* PHYSFS_utf8ToUcs4 */
|
|
||||||
|
|
||||||
|
|
||||||
void PHYSFS_utf8ToUcs2(const char *src, PHYSFS_uint16 *dst, PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
len -= sizeof (PHYSFS_uint16); /* save room for null char. */
|
|
||||||
while (len >= sizeof (PHYSFS_uint16))
|
|
||||||
{
|
|
||||||
PHYSFS_uint32 cp = utf8codepoint(&src);
|
|
||||||
if (cp == 0)
|
|
||||||
break;
|
|
||||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
|
|
||||||
if (cp > 0xFFFF) /* UTF-16 surrogates (bogus chars in UCS-2) */
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
|
|
||||||
*(dst++) = cp;
|
|
||||||
len -= sizeof (PHYSFS_uint16);
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
*dst = 0;
|
|
||||||
} /* PHYSFS_utf8ToUcs2 */
|
|
||||||
|
|
||||||
|
|
||||||
void PHYSFS_utf8ToUtf16(const char *src, PHYSFS_uint16 *dst, PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
len -= sizeof (PHYSFS_uint16); /* save room for null char. */
|
|
||||||
while (len >= sizeof (PHYSFS_uint16))
|
|
||||||
{
|
|
||||||
PHYSFS_uint32 cp = utf8codepoint(&src);
|
|
||||||
if (cp == 0)
|
|
||||||
break;
|
|
||||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
|
|
||||||
if (cp > 0xFFFF) /* encode as surrogate pair */
|
|
||||||
{
|
|
||||||
if (len < (sizeof (PHYSFS_uint16) * 2))
|
|
||||||
break; /* not enough room for the pair, stop now. */
|
|
||||||
|
|
||||||
cp -= 0x10000; /* Make this a 20-bit value */
|
|
||||||
|
|
||||||
*(dst++) = 0xD800 + ((cp >> 10) & 0x3FF);
|
|
||||||
len -= sizeof (PHYSFS_uint16);
|
|
||||||
|
|
||||||
cp = 0xDC00 + (cp & 0x3FF);
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
*(dst++) = cp;
|
|
||||||
len -= sizeof (PHYSFS_uint16);
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
*dst = 0;
|
|
||||||
} /* PHYSFS_utf8ToUtf16 */
|
|
||||||
|
|
||||||
static void utf8fromcodepoint(PHYSFS_uint32 cp, char **_dst, PHYSFS_uint64 *_len)
|
|
||||||
{
|
|
||||||
char *dst = *_dst;
|
|
||||||
PHYSFS_uint64 len = *_len;
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (cp > 0x10FFFF)
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
else if ((cp == 0xFFFE) || (cp == 0xFFFF)) /* illegal values. */
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */
|
|
||||||
switch (cp)
|
|
||||||
{
|
|
||||||
case 0xD800:
|
|
||||||
case 0xDB7F:
|
|
||||||
case 0xDB80:
|
|
||||||
case 0xDBFF:
|
|
||||||
case 0xDC00:
|
|
||||||
case 0xDF80:
|
|
||||||
case 0xDFFF:
|
|
||||||
cp = UNICODE_BOGUS_CHAR_CODEPOINT;
|
|
||||||
} /* switch */
|
|
||||||
} /* else */
|
|
||||||
|
|
||||||
/* Do the encoding... */
|
|
||||||
if (cp < 0x80)
|
|
||||||
{
|
|
||||||
*(dst++) = (char) cp;
|
|
||||||
len--;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
else if (cp < 0x800)
|
|
||||||
{
|
|
||||||
if (len < 2)
|
|
||||||
len = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(dst++) = (char) ((cp >> 6) | 128 | 64);
|
|
||||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
|
||||||
len -= 2;
|
|
||||||
} /* else */
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else if (cp < 0x10000)
|
|
||||||
{
|
|
||||||
if (len < 3)
|
|
||||||
len = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(dst++) = (char) ((cp >> 12) | 128 | 64 | 32);
|
|
||||||
*(dst++) = (char) ((cp >> 6) & 0x3F) | 128;
|
|
||||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
|
||||||
len -= 3;
|
|
||||||
} /* else */
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (len < 4)
|
|
||||||
len = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(dst++) = (char) ((cp >> 18) | 128 | 64 | 32 | 16);
|
|
||||||
*(dst++) = (char) ((cp >> 12) & 0x3F) | 128;
|
|
||||||
*(dst++) = (char) ((cp >> 6) & 0x3F) | 128;
|
|
||||||
*(dst++) = (char) (cp & 0x3F) | 128;
|
|
||||||
len -= 4;
|
|
||||||
} /* else if */
|
|
||||||
} /* else */
|
|
||||||
|
|
||||||
*_dst = dst;
|
|
||||||
*_len = len;
|
|
||||||
} /* utf8fromcodepoint */
|
|
||||||
|
|
||||||
#define UTF8FROMTYPE(typ, src, dst, len) \
|
|
||||||
if (len == 0) return; \
|
|
||||||
len--; \
|
|
||||||
while (len) \
|
|
||||||
{ \
|
|
||||||
const PHYSFS_uint32 cp = (PHYSFS_uint32) ((typ) (*(src++))); \
|
|
||||||
if (cp == 0) break; \
|
|
||||||
utf8fromcodepoint(cp, &dst, &len); \
|
|
||||||
} \
|
|
||||||
*dst = '\0'; \
|
|
||||||
|
|
||||||
void PHYSFS_utf8FromUcs4(const PHYSFS_uint32 *src, char *dst, PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
UTF8FROMTYPE(PHYSFS_uint32, src, dst, len);
|
|
||||||
} /* PHYSFS_utf8FromUcs4 */
|
|
||||||
|
|
||||||
void PHYSFS_utf8FromUcs2(const PHYSFS_uint16 *src, char *dst, PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
UTF8FROMTYPE(PHYSFS_uint64, src, dst, len);
|
|
||||||
} /* PHYSFS_utf8FromUcs2 */
|
|
||||||
|
|
||||||
/* latin1 maps to unicode codepoints directly, we just utf-8 encode it. */
|
|
||||||
void PHYSFS_utf8FromLatin1(const char *src, char *dst, PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
UTF8FROMTYPE(PHYSFS_uint8, src, dst, len);
|
|
||||||
} /* PHYSFS_utf8FromLatin1 */
|
|
||||||
|
|
||||||
#undef UTF8FROMTYPE
|
|
||||||
|
|
||||||
|
|
||||||
void PHYSFS_utf8FromUtf16(const PHYSFS_uint16 *src, char *dst, PHYSFS_uint64 len)
|
|
||||||
{
|
|
||||||
if (len == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
len--;
|
|
||||||
while (len)
|
|
||||||
{
|
|
||||||
const PHYSFS_uint32 cp = utf16codepoint(&src);
|
|
||||||
if (!cp)
|
|
||||||
break;
|
|
||||||
utf8fromcodepoint(cp, &dst, &len);
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
*dst = '\0';
|
|
||||||
} /* PHYSFS_utf8FromUtf16 */
|
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_caseFold(const PHYSFS_uint32 from, PHYSFS_uint32 *to)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (from < 128) /* low-ASCII, easy! */
|
|
||||||
{
|
|
||||||
if ((from >= 'A') && (from <= 'Z'))
|
|
||||||
*to = from - ('A' - 'a');
|
|
||||||
else
|
|
||||||
*to = from;
|
|
||||||
return 1;
|
|
||||||
} /* if */
|
|
||||||
|
|
||||||
else if (from <= 0xFFFF)
|
|
||||||
{
|
|
||||||
const PHYSFS_uint8 hash = ((from ^ (from >> 8)) & 0xFF);
|
|
||||||
const PHYSFS_uint16 from16 = (PHYSFS_uint16) from;
|
|
||||||
|
|
||||||
{
|
|
||||||
const CaseFoldHashBucket1_16 *bucket = &case_fold_hash1_16[hash];
|
|
||||||
const int count = (int) bucket->count;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
const CaseFoldMapping1_16 *mapping = &bucket->list[i];
|
|
||||||
if (mapping->from == from16)
|
|
||||||
{
|
|
||||||
*to = mapping->to0;
|
|
||||||
return 1;
|
|
||||||
} /* if */
|
|
||||||
} /* for */
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const CaseFoldHashBucket2_16 *bucket = &case_fold_hash2_16[hash & 15];
|
|
||||||
const int count = (int) bucket->count;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
const CaseFoldMapping2_16 *mapping = &bucket->list[i];
|
|
||||||
if (mapping->from == from16)
|
|
||||||
{
|
|
||||||
to[0] = mapping->to0;
|
|
||||||
to[1] = mapping->to1;
|
|
||||||
return 2;
|
|
||||||
} /* if */
|
|
||||||
} /* for */
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const CaseFoldHashBucket3_16 *bucket = &case_fold_hash3_16[hash & 3];
|
|
||||||
const int count = (int) bucket->count;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
const CaseFoldMapping3_16 *mapping = &bucket->list[i];
|
|
||||||
if (mapping->from == from16)
|
|
||||||
{
|
|
||||||
to[0] = mapping->to0;
|
|
||||||
to[1] = mapping->to1;
|
|
||||||
to[2] = mapping->to2;
|
|
||||||
return 3;
|
|
||||||
} /* if */
|
|
||||||
} /* for */
|
|
||||||
}
|
|
||||||
} /* else if */
|
|
||||||
|
|
||||||
else /* codepoint that doesn't fit in 16 bits. */
|
|
||||||
{
|
|
||||||
const PHYSFS_uint8 hash = ((from ^ (from >> 8)) & 0xFF);
|
|
||||||
const CaseFoldHashBucket1_32 *bucket = &case_fold_hash1_32[hash & 15];
|
|
||||||
const int count = (int) bucket->count;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
const CaseFoldMapping1_32 *mapping = &bucket->list[i];
|
|
||||||
if (mapping->from == from)
|
|
||||||
{
|
|
||||||
*to = mapping->to0;
|
|
||||||
return 1;
|
|
||||||
} /* if */
|
|
||||||
} /* for */
|
|
||||||
} /* else */
|
|
||||||
|
|
||||||
|
|
||||||
/* Not found...there's no remapping for this codepoint. */
|
|
||||||
*to = from;
|
|
||||||
return 1;
|
|
||||||
} /* PHYSFS_caseFold */
|
|
||||||
|
|
||||||
|
|
||||||
#define UTFSTRICMP(bits) \
|
|
||||||
PHYSFS_uint32 folded1[3], folded2[3]; \
|
|
||||||
int head1 = 0, tail1 = 0, head2 = 0, tail2 = 0; \
|
|
||||||
while (1) { \
|
|
||||||
PHYSFS_uint32 cp1, cp2; \
|
|
||||||
if (head1 != tail1) { \
|
|
||||||
cp1 = folded1[tail1++]; \
|
|
||||||
} else { \
|
|
||||||
head1 = PHYSFS_caseFold(utf##bits##codepoint(&str1), folded1); \
|
|
||||||
cp1 = folded1[0]; \
|
|
||||||
tail1 = 1; \
|
|
||||||
} \
|
|
||||||
if (head2 != tail2) { \
|
|
||||||
cp2 = folded2[tail2++]; \
|
|
||||||
} else { \
|
|
||||||
head2 = PHYSFS_caseFold(utf##bits##codepoint(&str2), folded2); \
|
|
||||||
cp2 = folded2[0]; \
|
|
||||||
tail2 = 1; \
|
|
||||||
} \
|
|
||||||
if (cp1 < cp2) { \
|
|
||||||
return -1; \
|
|
||||||
} else if (cp1 > cp2) { \
|
|
||||||
return 1; \
|
|
||||||
} else if (cp1 == 0) { \
|
|
||||||
break; /* complete match. */ \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
return 0
|
|
||||||
|
|
||||||
int PHYSFS_utf8stricmp(const char *str1, const char *str2)
|
|
||||||
{
|
|
||||||
UTFSTRICMP(8);
|
|
||||||
} /* PHYSFS_utf8stricmp */
|
|
||||||
|
|
||||||
int PHYSFS_utf16stricmp(const PHYSFS_uint16 *str1, const PHYSFS_uint16 *str2)
|
|
||||||
{
|
|
||||||
UTFSTRICMP(16);
|
|
||||||
} /* PHYSFS_utf16stricmp */
|
|
||||||
|
|
||||||
int PHYSFS_ucs4stricmp(const PHYSFS_uint32 *str1, const PHYSFS_uint32 *str2)
|
|
||||||
{
|
|
||||||
UTFSTRICMP(32);
|
|
||||||
} /* PHYSFS_ucs4stricmp */
|
|
||||||
|
|
||||||
#undef UTFSTRICMP
|
|
||||||
|
|
||||||
/* end of physfs_unicode.c ... */
|
|
||||||
|
|
Loading…
Reference in a new issue