1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-26 22:37:45 +00:00

Merge branch 'develop' of https://github.com/SapphireMordred/Sapphire into develop

This commit is contained in:
Matheus Ogeda 2018-11-14 18:46:06 -02:00
commit fffa93bd81
624 changed files with 59898 additions and 18728 deletions

View file

@ -1,16 +1,14 @@
os:
- Visual Studio 2015
- Visual Studio 2017
configuration:
- Debug
platform:
- Win32
- Win64
environment:
MSVC_DEFAULT_OPTIONS: ON
BOOST_ROOT_DIR: "C:\\Libraries\\boost_1_63_0"
BOOST_LIB_DIR: "C:\\Libraries\\boost_1_63_0\\lib32-msvc-14.0"
MYSQL_PWD: "Password12!"
services:
@ -22,7 +20,7 @@ before_build:
- git submodule update --init
- mkdir build
- cd build
- cmake .. -G "Visual Studio 14 2015"
- cmake .. -G "Visual Studio 15 2017 Win64"
- cmake --build . --target ALL_BUILD --config Debug
build_script:

10
.gitmodules vendored
View file

@ -1,4 +1,6 @@
[submodule "src/libraries"]
path = src/libraries
url = https://github.com/SapphireMordred/SapphireLibs.git
ignore = dirty
[submodule "deps/asio"]
path = deps/asio
url = https://github.com/chriskohlhoff/asio.git
[submodule "deps/spdlog"]
path = deps/spdlog
url = https://github.com/gabime/spdlog.git

View file

@ -18,7 +18,7 @@ matrix:
- clang-6.0
- g++-7
env:
- MATRIX_EVAL="CC=clang-6.0 && CXX=clang++-6.0"
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
# Setup cache
cache:
@ -32,7 +32,6 @@ before_install:
- gem install --no-ri --no-rdoc mtime_cache
- sudo add-apt-repository -y ppa:rexut/recoil
- sudo apt-get update
- sudo apt-get install -y libboost1.63-dev libboost1.63-all-dev
- sudo apt-get install -y libmysqlclient-dev
# Build steps
@ -41,6 +40,6 @@ script:
- mtime_cache src/**/*.{%{cpp}} -c .mtime_cache/cache.json
- mkdir -p build
- cd build
- cmake .. -DSAPPHIRE_BOOST_VER="1.63.0" && make -j 3
- cmake .. && make -j 3
- cd ..
- bash sql_import.sh

View file

@ -1,33 +1,17 @@
cmake_policy(SET CMP0014 NEW)
cmake_minimum_required(VERSION 3.0.2)
project (Sapphire)
cmake_policy( SET CMP0014 NEW )
cmake_minimum_required( VERSION 3.0.2 )
project( Sapphire )
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set( CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin )
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
set(EXECUTABLE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set( EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin )
set( LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin )
set( EXECUTABLE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin )
set(PROJECT_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
##########################################################################
# Boost stuff
# set(Boost_DEBUG 1)
if( NOT SAPPHIRE_BOOST_VER )
set( SAPPHIRE_BOOST_VER 1.63.0 )
endif()
set( SAPPHIRE_BOOST_FOLDER_NAME boost_1_63_0 )
##########################################################################
# Common and library path
set( LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/libraries" )
set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake )
##########################################################################
# Dependencies and compiler settings
include( "cmake/boost.cmake" )
include( "cmake/mysql.cmake" )
include( "cmake/compiler.cmake" )
include( "cmake/cotire.cmake" )
@ -40,12 +24,20 @@ git_describe( VERSION --all --dirty=-d )
configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/src/common/Version.cpp.in"
"${CMAKE_CURRENT_SOURCE_DIR}/src/common/Version.cpp" @ONLY )
##############################
# Mysql #
##############################
find_package( MySQL )
##########################################################################
add_subdirectory( "src/libraries/sapphire/datReader" )
add_subdirectory( "src/libraries/sapphire/mysqlConnector" )
add_subdirectory( "deps/zlib" )
add_subdirectory( "deps/MySQL" )
add_subdirectory( "deps/datReader" )
add_subdirectory( "deps/mysqlConnector" )
add_subdirectory( "src/common" )
add_subdirectory( "src/servers" )
#add_subdirectory( "src/dbm" )
add_subdirectory( "src/tools/exd_common_gen" )
add_subdirectory( "src/tools/exd_struct_gen" )
@ -53,5 +45,5 @@ add_subdirectory( "src/tools/exd_struct_test" )
add_subdirectory( "src/tools/quest_parser" )
add_subdirectory( "src/tools/discovery_parser" )
add_subdirectory( "src/tools/mob_parse" )
#add_subdirectory("src/tools/pcb_reader")
#add_subdirectory("src/tools/event_object_parser")
add_subdirectory( "src/tools/pcb_reader" )
add_subdirectory( "src/tools/event_object_parser" )

View file

@ -1,75 +1,13 @@
{
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
"configurations": [
{
"name": "x86-Debug",
"generator": "Visual Studio 14 2015",
"configurationType": "Debug",
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "-DCMAKE_BUILD_TYPE=\"Debug\"",
"buildCommandArgs": "-m -v:minimal",
"variables": [
{
"name": "Boost_COMPILER",
"value": "-vc140"
}
]
},
{
"name": "x86-Release",
"generator": "Visual Studio 14 2015",
"configurationType": "Release",
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal",
"variables": [
{
"name": "Boost_COMPILER",
"value": "-vc140"
}
]
},
{
"name": "x64-Debug",
"generator": "Visual Studio 14 2015 Win64",
"configurationType": "Debug",
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "-DCMAKE_BUILD_TYPE=\"Debug\"",
"buildCommandArgs": "-m -v:minimal",
"variables": [
{
"name": "Boost_COMPILER",
"value": "-vc140"
}
]
},
{
"name": "x64-Release",
"generator": "Visual Studio 14 2015 Win64",
"configurationType": "Release",
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal",
"variables": [
{
"name": "Boost_COMPILER",
"value": "-vc140"
}
]
},
{
"name": "x86-Debug",
"generator": "Visual Studio 15 2017",
"configurationType": "Debug",
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "-DCMAKE_BUILD_TYPE=\"Debug\"",
"buildCommandArgs": "-m -v:minimal",
"variables": [
{
"name": "Boost_COMPILER",
"value": "-vc141"
}
]
"buildCommandArgs": "-m -v:minimal"
},
{
"name": "x86-Release",
@ -77,13 +15,7 @@
"configurationType": "Release",
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal",
"variables": [
{
"name": "Boost_COMPILER",
"value": "-vc141"
}
]
"buildCommandArgs": "-m -v:minimal"
},
{
"name": "x64-Debug",
@ -91,13 +23,7 @@
"configurationType": "Debug",
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "-DCMAKE_BUILD_TYPE=\"Debug\"",
"buildCommandArgs": "-m -v:minimal",
"variables": [
{
"name": "Boost_COMPILER",
"value": "-vc141"
}
]
"buildCommandArgs": "-m -v:minimal"
},
{
"name": "x64-Release",
@ -105,13 +31,7 @@
"configurationType": "Release",
"buildRoot": "${env.USERPROFILE}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal",
"variables": [
{
"name": "Boost_COMPILER",
"value": "-vc141"
}
]
"buildCommandArgs": "-m -v:minimal"
}
]
}

View file

@ -1,8 +1,13 @@
# Sapphire - FINAL FANTASY XIV Server Emulator
<p align="center">
<img src="https://i.imgur.com/I4bj1tR.png" alt="FFXIV Sapphire"/>
</p>
[![Discord Server](https://img.shields.io/badge/discord-Sapphire-7289DA.svg)](https://discord.gg/xxcdCER)
[![Linux Build Status](https://travis-ci.org/SapphireMordred/Sapphire.svg?branch=master)](https://travis-ci.org/SapphireMordred/Sapphire)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/lil7lxa3ty165emm?svg=true)](https://ci.appveyor.com/project/SapphireMordred/Sapphire)
![FFXIV Sapphire](http://i.imgur.com/I4bj1tR.png)
Sapphire is a FINAL FANTASY XIV 4.0+ Server Emulator currently in development.
@ -13,8 +18,7 @@ Sapphire requires the following software:
| *Name* | *Windows* | *Linux* |
| ------ | --------- | ------- |
| CMake 3.0.2+ and C++14 capable compiler | [Visual Studio 2017](https://www.visualstudio.com/) | `gcc 4.9` and `g++ 4.9` or newer |
| Boost 1.63.0 | [Win32 precompiled binaries](https://sourceforge.net/projects/boost/files/boost-binaries/1.63.0/boost_1_63_0-msvc-14.0-32.exe/download) | Boost libraries from your distribution's package manager |
| CMake 3.0.2+ and C++17 capable compiler | [Visual Studio 2017](https://www.visualstudio.com/) | `gcc 7` and `g++ 7` or newer |
| MySQL Server 5.7 | [Official Site](https://dev.mysql.com/downloads/mysql/) | MySQL server from your distribution's package manager |
Please check the [wiki](https://github.com/SapphireMordred/Sapphire/wiki) for detailed installation/build instructions for your OS.

View file

@ -0,0 +1,58 @@
[Database]
Host = 127.0.0.1
Port = 3306
Database = sapphire
Username = sapphire
Password =
SyncThreads = 2
AsyncThreads = 2
[GlobalParameters]
ServerSecret = default
DataPath = C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack
[GlobalNetwork]
; Values definining how Users and other servers will access - these have to be set to your public IP when running a public server
ZoneHost = 127.0.0.1
ZonePort = 54992
LobbyHost = 127.0.0.1
LobbyPort = 54994
RestHost = 127.0.0.1
RestPort = 80
[Lobby]
WorldID = 67
AllowNoSessionConnect = false
WorldName = Sapphire
[LobbyNetwork]
ListenIp = 0.0.0.0
ListenPort = 54994
[CharacterCreation]
DefaultGMRank = 255
[RestNetwork]
ListenIp = 0.0.0.0
ListenPort = 80
[Scripts]
; where compiled script modules are located
Path = ./compiledscripts/
; relative to Path, where we copy and load modules from
CachePath = ./cache/
; whether we should detect changes to script modules and reload them
HotSwap = true
[Network]
DisconnectTimeout = 20
[ZoneNetwork]
ListenIp = 0.0.0.0
ListenPort = 54992
[General]
; Sent on login - each line must be shorter than 307 characters, split lines with ';'
MotD = Welcome to Sapphire!;This is a very good server;You can change these messages by editing General.MotD in config/zone.ini

View file

@ -1,23 +0,0 @@
[Database]
Host = 127.0.0.1
Port = 3306
Database = sapphire
Username = root
Password =
SyncThreads = 2
AsyncThreads = 2
[GlobalParameters]
ServerSecret = default
DataPath = C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack
[GlobalNetwork]
; Values definining how Users and other servers will access - these have to be set to your public IP when running a public server
ZoneHost = 127.0.0.1
ZonePort = 54992
LobbyHost = 127.0.0.1
LobbyPort = 54994
RestHost = 127.0.0.1
RestPort = 80

View file

@ -1,8 +0,0 @@
[Lobby]
WorldID = 67
AllowNoSessionConnect = false
WorldName = Sapphire
[LobbyNetwork]
ListenIp = 0.0.0.0
ListenPort = 54994

View file

@ -1,6 +0,0 @@
[CharacterCreation]
DefaultGMRank = 255
[RestNetwork]
ListenIp = 0.0.0.0
ListenPort = 80

View file

@ -1,18 +0,0 @@
[Scripts]
; where compiled script modules are located
Path = ./compiledscripts/
; relative to Path, where we copy and load modules from
CachePath = ./cache/
; whether we should detect changes to script modules and reload them
HotSwap = true
[Network]
DisconnectTimeout = 20
[ZoneNetwork]
ListenIp = 0.0.0.0
ListenPort = 54992
[General]
; Sent on login - each line must be shorter than 307 characters, split lines with ';'
MotD = Welcome to Sapphire!;This is a very good server;You can change these messages by editing General.MotD in config/zone.ini

Binary file not shown.

291
cmake/FindMySQL.cmake Normal file
View file

@ -0,0 +1,291 @@
#
# Find the MySQL client includes and library
#
# This module defines
# MYSQL_INCLUDE_DIR, where to find mysql.h
# MYSQL_LIBRARIES, the libraries to link against to connect to MySQL
# MYSQL_EXECUTABLE, the MySQL executable.
# MYSQL_FOUND, if false, you cannot build anything that requires MySQL.
# also defined, but not for general use are
# MYSQL_LIBRARY, where to find the MySQL library.
set( MYSQL_FOUND 0 )
if( UNIX )
set(MYSQL_CONFIG_PREFER_PATH "$ENV{MYSQL_HOME}/bin" CACHE FILEPATH
"preferred path to MySQL (mysql_config)"
)
find_program(MYSQL_CONFIG mysql_config
${MYSQL_CONFIG_PREFER_PATH}
/usr/local/mysql/bin/
/usr/local/bin/
/usr/bin/
)
if( MYSQL_CONFIG )
message(STATUS "Using mysql-config: ${MYSQL_CONFIG}")
# set INCLUDE_DIR
exec_program(${MYSQL_CONFIG}
ARGS --include
OUTPUT_VARIABLE MY_TMP
)
string(REGEX REPLACE "-I([^ ]*)( .*)?" "\\1" MY_TMP "${MY_TMP}")
set(MYSQL_ADD_INCLUDE_PATH ${MY_TMP} CACHE FILEPATH INTERNAL)
#message("[DEBUG] MYSQL ADD_INCLUDE_PATH : ${MYSQL_ADD_INCLUDE_PATH}")
# set LIBRARY_DIR
exec_program(${MYSQL_CONFIG}
ARGS --libs_r
OUTPUT_VARIABLE MY_TMP
)
set(MYSQL_ADD_LIBRARIES "")
string(REGEX MATCHALL "-l[^ ]*" MYSQL_LIB_LIST "${MY_TMP}")
foreach(LIB ${MYSQL_LIB_LIST})
string(REGEX REPLACE "[ ]*-l([^ ]*)" "\\1" LIB "${LIB}")
list(APPEND MYSQL_ADD_LIBRARIES "${LIB}")
#message("[DEBUG] MYSQL ADD_LIBRARIES : ${MYSQL_ADD_LIBRARIES}")
endforeach(LIB ${MYSQL_LIB_LIST})
set(MYSQL_ADD_LIBRARIES_PATH "")
string(REGEX MATCHALL "-L[^ ]*" MYSQL_LIBDIR_LIST "${MY_TMP}")
foreach(LIB ${MYSQL_LIBDIR_LIST})
string(REGEX REPLACE "[ ]*-L([^ ]*)" "\\1" LIB "${LIB}")
list(APPEND MYSQL_ADD_LIBRARIES_PATH "${LIB}")
#message("[DEBUG] MYSQL ADD_LIBRARIES_PATH : ${MYSQL_ADD_LIBRARIES_PATH}")
endforeach(LIB ${MYSQL_LIBS})
else( MYSQL_CONFIG )
set(MYSQL_ADD_LIBRARIES "")
list(APPEND MYSQL_ADD_LIBRARIES "mysqlclient_r")
endif( MYSQL_CONFIG )
endif( UNIX )
if( WIN32 )
# read environment variables and change \ to /
SET(PROGRAM_FILES_32 $ENV{ProgramFiles})
if (${PROGRAM_FILES_32})
STRING(REPLACE "\\\\" "/" PROGRAM_FILES_32 ${PROGRAM_FILES_32})
endif(${PROGRAM_FILES_32})
SET(PROGRAM_FILES_64 $ENV{ProgramW6432})
if (${PROGRAM_FILES_64})
STRING(REPLACE "\\\\" "/" PROGRAM_FILES_64 ${PROGRAM_FILES_64})
endif(${PROGRAM_FILES_64})
endif ( WIN32 )
find_path(MYSQL_INCLUDE_DIR
NAMES
mysql.h
PATHS
${MYSQL_ADD_INCLUDE_PATH}
/usr/include
/usr/include/mysql
/usr/local/include
/usr/local/include/mysql
/usr/local/mysql/include
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.7/include"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.6/include"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.5/include"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.1/include"
"${PROGRAM_FILES_32}/MySQL/include"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.7/include"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.6/include"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.5/include"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.1/include"
"${PROGRAM_FILES_64}/MySQL/include"
"C:/MySQL/include"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/include"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.6;Location]/include"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.5;Location]/include"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.1;Location]/include"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.7;Location]/include"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.6;Location]/include"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.5;Location]/include"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.1;Location]/include"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.7/include"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.6/include"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.5/include"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.1/include"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.7/include"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.6/include"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.5/include"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.1/include"
"c:/msys/local/include"
"$ENV{MYSQL_ROOT}/include"
DOC
"Specify the directory containing mysql.h."
)
if( UNIX )
foreach(LIB ${MYSQL_ADD_LIBRARIES})
find_library( MYSQL_LIBRARY
NAMES
mysql libmysql ${LIB}
PATHS
${MYSQL_ADD_LIBRARIES_PATH}
/usr/lib
/usr/lib/mysql
/usr/local/lib
/usr/local/lib/mysql
/usr/local/mysql/lib
DOC "Specify the location of the mysql library here."
)
endforeach(LIB ${MYSQL_ADD_LIBRARY})
endif( UNIX )
if( WIN32 )
find_library( MYSQL_LIBRARY
NAMES
libmysql
PATHS
${MYSQL_ADD_LIBRARIES_PATH}
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.7/lib"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.6/lib"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.5/lib"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.1/lib"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.7/lib/opt"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.6/lib/opt"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.5/lib/opt"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.1/lib/opt"
"${PROGRAM_FILES_32}/MySQL/lib"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.7/lib"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.6/lib"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.5/lib"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.1/lib"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.7/lib/opt"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.6/lib/opt"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.5/lib/opt"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.1/lib/opt"
"${PROGRAM_FILES_64}/MySQL/lib"
"C:/MySQL/lib/debug"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/lib"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.6;Location]/lib"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.5;Location]/lib"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.1;Location]/lib"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/lib/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.6;Location]/lib/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.5;Location]/lib/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.1;Location]/lib/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.7;Location]/lib"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.6;Location]/lib"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.5;Location]/lib"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.1;Location]/lib"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.7;Location]/lib/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.6;Location]/lib/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.5;Location]/lib/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.1;Location]/lib/opt"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.7/lib/opt"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.6/lib/opt"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.5/lib/opt"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.1/lib/opt"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.7/lib/opt"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.6/lib/opt"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.5/lib/opt"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.1/lib/opt"
"c:/msys/local/include"
"$ENV{MYSQL_ROOT}/lib"
DOC "Specify the location of the mysql library here."
)
endif( WIN32 )
# On Windows you typically don't need to include any extra libraries
# to build MYSQL stuff.
if( NOT WIN32 )
find_library( MYSQL_EXTRA_LIBRARIES
NAMES
z zlib
PATHS
/usr/lib
/usr/local/lib
DOC
"if more libraries are necessary to link in a MySQL client (typically zlib), specify them here."
)
else( NOT WIN32 )
set( MYSQL_EXTRA_LIBRARIES "" )
endif( NOT WIN32 )
if( UNIX )
find_program(MYSQL_EXECUTABLE mysql
PATHS
${MYSQL_CONFIG_PREFER_PATH}
/usr/local/mysql/bin/
/usr/local/bin/
/usr/bin/
DOC
"path to your mysql binary."
)
endif( UNIX )
if( WIN32 )
find_program(MYSQL_EXECUTABLE mysql
PATHS
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.7/bin"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.6/bin"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.5/bin"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.1/bin"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.7/bin/opt"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.6/bin/opt"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.5/bin/opt"
"${PROGRAM_FILES_32}/MySQL/MySQL Server 5.1/bin/opt"
"${PROGRAM_FILES_32}/MySQL/bin"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.7/bin"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.6/bin"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.5/bin"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.1/bin"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.7/bin/opt"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.6/bin/opt"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.5/bin/opt"
"${PROGRAM_FILES_64}/MySQL/MySQL Server 5.1/bin/opt"
"${PROGRAM_FILES_64}/MySQL/bin"
"C:/MySQL/bin/debug"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/bin"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.6;Location]/bin"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.5;Location]/bin"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.1;Location]/bin"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.7;Location]/bin/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.6;Location]/bin/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.5;Location]/bin/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.1;Location]/bin/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.7;Location]/bin"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.6;Location]/bin"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.5;Location]/bin"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.1;Location]/bin"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.7;Location]/bin/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.6;Location]/bin/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.5;Location]/bin/opt"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\MySQL AB\\MySQL Server 5.1;Location]/bin/opt"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.7/bin/opt"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.6/bin/opt"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.5/bin/opt"
"$ENV{ProgramFiles}/MySQL/MySQL Server 5.1/bin/opt"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.7/bin/opt"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.6/bin/opt"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.5/bin/opt"
"$ENV{SystemDrive}/MySQL/MySQL Server 5.1/bin/opt"
"c:/msys/local/include"
"$ENV{MYSQL_ROOT}/bin"
DOC
"path to your mysql binary."
)
endif( WIN32 )
if( MYSQL_LIBRARY )
if( MYSQL_INCLUDE_DIR )
set( MYSQL_FOUND 1 )
message(STATUS "Found MySQL library: ${MYSQL_LIBRARY}")
message(STATUS "Found MySQL headers: ${MYSQL_INCLUDE_DIR}")
else( MYSQL_INCLUDE_DIR )
message(FATAL_ERROR "Could not find MySQL headers! Please install the development libraries and headers")
endif( MYSQL_INCLUDE_DIR )
if( MYSQL_EXECUTABLE )
message(STATUS "Found MySQL executable: ${MYSQL_EXECUTABLE}")
endif( MYSQL_EXECUTABLE )
mark_as_advanced( MYSQL_FOUND MYSQL_LIBRARY MYSQL_EXTRA_LIBRARIES MYSQL_INCLUDE_DIR MYSQL_EXECUTABLE)
else( MYSQL_LIBRARY )
message(FATAL_ERROR "Could not find the MySQL libraries! Please install the development libraries and headers")
endif( MYSQL_LIBRARY )

View file

@ -1,39 +0,0 @@
if(UNIX)
find_package(Boost ${SAPPHIRE_BOOST_VER} COMPONENTS system)
if(Boost_FOUND)
set(BOOST_LIBRARY_DIR ${Boost_LIBRARY_DIR})
else()
if (EXISTS /opt/build_libs/${SAPPHIRE_BOOST_FOLDER_NAME})
set(Boost_INCLUDE_DIR /opt/build_libs/${SAPPHIRE_BOOST_FOLDER_NAME})
set(BOOST_LIBRARYDIR /opt/build_libs/${SAPPHIRE_BOOST_FOLDER_NAME}/stage/lib)
else()
message(FATAL_ERROR "Unable to find boost ${SAPPHIRE_BOOST_VER} package!")
endif()
endif()
else()
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/libraries/external/${SAPPHIRE_BOOST_FOLDER_NAME})
message(STATUS "Using boost in /libraries/external")
set(Boost_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/libraries/external/${SAPPHIRE_BOOST_FOLDER_NAME})
set(BOOST_LIBRARYDIR ${CMAKE_CURRENT_SOURCE_DIR}/src/libraries/external/${SAPPHIRE_BOOST_FOLDER_NAME}/lib32-msvc-14.0)
else()
find_package(Boost ${SAPPHIRE_BOOST_VER} COMPONENTS system)
if(Boost_FOUND)
set(BOOST_LIBRARY_DIR ${Boost_LIBRARY_DIR})
elseif ((EXISTS $ENV{BOOST_ROOT_DIR}) AND (EXISTS $ENV{BOOST_LIB_DIR}))
set(Boost_INCLUDE_DIR $ENV{BOOST_ROOT_DIR})
set(BOOST_LIBRARYDIR $ENV{BOOST_LIB_DIR})
else()
message(FATAL_ERROR "SapphireError: Unable to find boost ${SAPPHIRE_BOOST_VER} package and environment variables BOOST_ROOT_DIR and BOOST_LIB_DIR not set!")
endif()
endif()
endif()
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost ${SAPPHIRE_BOOST_VER} COMPONENTS log log_setup thread date_time filesystem system)
include_directories(${Boost_INCLUDE_DIR})
link_directories(${BOOST_LIBRARYDIR})

View file

@ -1,10 +1,11 @@
if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
else()
add_definitions(-D_WIN32_WINNT=0x601)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-DNOMINMAX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHc")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
@ -16,7 +17,7 @@ else()
# edit and continue
message(STATUS "Enabling Edit and Continue..")
add_definitions(/ZI)
add_definitions(/Zi)
# incremental linking
message(STATUS "Enabling Incremental Linking..")
@ -28,4 +29,5 @@ else()
endif()
endif()
# force standalone asio
add_definitions( -DASIO_STANDALONE )

22
deps/MySQL/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,22 @@
# Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
if (NOT MYSQL_FOUND)
message(FATAL_ERROR "MySQL wasn't found on your system but it's required to build the servers!")
endif()
add_library(mysql STATIC IMPORTED GLOBAL)
set_target_properties(mysql
PROPERTIES
IMPORTED_LOCATION
"${MYSQL_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES
"${MYSQL_INCLUDE_DIR}")

1
deps/asio vendored Submodule

@ -0,0 +1 @@
Subproject commit 28d9b8d6df708024af5227c551673fdb2519f5bf

26
deps/datReader/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.0.2)
project(Sapphire)
include_directories( "../" )
file( GLOB UTILS_PUBLIC_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*" )
file( GLOB UTILS_SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*" )
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
add_library( xivdat ${UTILS_PUBLIC_INCLUDE_FILES} ${UTILS_SOURCE_FILES} )
set_target_properties( xivdat PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS ON
)
if (UNIX)
target_link_libraries( xivdat PUBLIC dl )
target_link_libraries( xivdat PUBLIC z )
else()
target_link_libraries( xivdat PUBLIC zlib )
endif()
target_include_directories( xivdat PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} )
#cotire( xivdat )

311
deps/datReader/Dat.cpp vendored Normal file
View file

@ -0,0 +1,311 @@
#include "Dat.h"
#include "zlib.h"
#include "File.h"
namespace
{
const uint32_t model_section_count = 0xB;
}
namespace xiv
{
namespace dat
{
struct DatFileHeader
{
uint32_t size;
FileType entry_type;
uint32_t total_uncompressed_size;
uint32_t unknown[0x2];
};
struct DatBlockRecord
{
uint32_t offset;
uint32_t size;
uint32_t unknown[0x4];
SqPackBlockHash block_hash;
};
struct DatBlockHeader
{
uint32_t size;
uint32_t unknown1;
uint32_t compressed_size;
uint32_t uncompressed_size;
};
struct DatStdFileBlockInfos
{
uint32_t offset;
uint16_t size;
uint16_t uncompressed_size;
};
struct DatMdlFileBlockInfos
{
uint32_t unknown1;
uint32_t uncompressed_sizes[::model_section_count];
uint32_t compressed_sizes[::model_section_count];
uint32_t offsets[::model_section_count];
uint16_t block_ids[::model_section_count];
uint16_t block_counts[::model_section_count];
uint32_t unknown2[0x2];
};
struct DatTexFileBlockInfos
{
uint32_t offset;
uint32_t size;
uint32_t uncompressed_size;
uint32_t block_id;
uint32_t block_count;
};
}
}
namespace xiv
{
namespace utils
{
namespace bparse
{
template <>
inline void reorder<xiv::dat::DatFileHeader>(xiv::dat::DatFileHeader& i_struct)
{
xiv::utils::bparse::reorder(i_struct.size);
xiv::utils::bparse::reorder(i_struct.entry_type);
xiv::utils::bparse::reorder(i_struct.total_uncompressed_size);
for (int32_t i = 0; i < 0x2; ++i) { xiv::utils::bparse::reorder(i_struct.unknown[i]); }
}
template <>
inline void reorder<xiv::dat::DatBlockRecord>(xiv::dat::DatBlockRecord& i_struct)
{
xiv::utils::bparse::reorder(i_struct.offset);
xiv::utils::bparse::reorder(i_struct.size);
for (int32_t i = 0; i < 0x4; ++i) { xiv::utils::bparse::reorder(i_struct.unknown[i]); }
xiv::utils::bparse::reorder(i_struct.block_hash);
}
template <>
inline void reorder<xiv::dat::DatBlockHeader>(xiv::dat::DatBlockHeader& i_struct)
{
xiv::utils::bparse::reorder(i_struct.size);
xiv::utils::bparse::reorder(i_struct.unknown1);
xiv::utils::bparse::reorder(i_struct.compressed_size);
xiv::utils::bparse::reorder(i_struct.uncompressed_size);
}
template <>
inline void reorder<xiv::dat::DatStdFileBlockInfos>(xiv::dat::DatStdFileBlockInfos& i_struct)
{
xiv::utils::bparse::reorder(i_struct.offset);
xiv::utils::bparse::reorder(i_struct.size);
xiv::utils::bparse::reorder(i_struct.uncompressed_size);
}
template <>
inline void reorder<xiv::dat::DatMdlFileBlockInfos>(xiv::dat::DatMdlFileBlockInfos& i_struct)
{
xiv::utils::bparse::reorder(i_struct.unknown1);
for (auto i = 0; i < ::model_section_count; ++i) { xiv::utils::bparse::reorder(i_struct.uncompressed_sizes[i]); }
for (auto i = 0; i < ::model_section_count; ++i) { xiv::utils::bparse::reorder(i_struct.compressed_sizes[i]); }
for (auto i = 0; i < ::model_section_count; ++i) { xiv::utils::bparse::reorder(i_struct.offsets[i]); }
for (auto i = 0; i < ::model_section_count; ++i) { xiv::utils::bparse::reorder(i_struct.block_ids[i]); }
for (auto i = 0; i < ::model_section_count; ++i) { xiv::utils::bparse::reorder(i_struct.block_counts[i]); }
for (auto i = 0; i < 0x2; ++i) { xiv::utils::bparse::reorder(i_struct.unknown2[i]); }
}
template <>
inline void reorder<xiv::dat::DatTexFileBlockInfos>(xiv::dat::DatTexFileBlockInfos& i_struct)
{
xiv::utils::bparse::reorder(i_struct.offset);
xiv::utils::bparse::reorder(i_struct.size);
xiv::utils::bparse::reorder(i_struct.uncompressed_size);
xiv::utils::bparse::reorder(i_struct.block_id);
xiv::utils::bparse::reorder(i_struct.block_count);
}
}
}
};
using xiv::utils::bparse::extract;
namespace xiv
{
namespace dat
{
Dat::Dat( const std::experimental::filesystem::path& i_path, uint32_t i_nb ) :
SqPack( i_path ),
m_num( i_nb )
{
auto block_record = extract<DatBlockRecord>(m_handle);
block_record.offset *= 0x80;
isBlockValid(block_record.offset, block_record.size, block_record.block_hash);
}
Dat::~Dat()
{
}
std::unique_ptr<File> Dat::getFile( uint32_t i_offset )
{
std::unique_ptr<File> outputFile(new File());
{
// Lock in this scope
std::lock_guard<std::mutex> lock(m_fileMutex);
// Seek to the start of the header of the file record and extract it
m_handle.seekg(i_offset);
auto file_header = extract<DatFileHeader>(m_handle);
switch (file_header.entry_type)
{
case FileType::empty:
throw std::runtime_error("File is empty");
case FileType::standard:
{
outputFile->_type = FileType::standard;
uint32_t number_of_blocks = extract<uint32_t>(m_handle, "number_of_blocks");
// Just extract offset infos for the blocks to extract
std::vector<DatStdFileBlockInfos> std_file_block_infos;
extract<DatStdFileBlockInfos>( m_handle, number_of_blocks, std_file_block_infos );
// Pre allocate data vector for the whole file
outputFile->_data_sections.resize(1);
auto& data_section = outputFile->_data_sections.front();
data_section.reserve(file_header.total_uncompressed_size);
// Extract each block
for (auto& file_block_info : std_file_block_infos)
{
extractBlock(i_offset + file_header.size + file_block_info.offset, data_section);
}
}
break;
case FileType::model:
{
outputFile->_type = FileType::model;
DatMdlFileBlockInfos mdlBlockInfo = extract<DatMdlFileBlockInfos>(m_handle);
// Getting the block number and read their sizes
const uint32_t block_count = mdlBlockInfo.block_ids[::model_section_count - 1] +
mdlBlockInfo.block_counts[::model_section_count - 1];
std::vector<uint16_t> block_sizes;
extract<uint16_t>(m_handle, "block_size", block_count, block_sizes);
// Preallocate sufficient space
outputFile->_data_sections.resize(::model_section_count);
for (uint32_t i = 0; i < ::model_section_count; ++i)
{
// Preallocating for section
auto& data_section = outputFile->_data_sections[i];
data_section.reserve(mdlBlockInfo.uncompressed_sizes[i]);
uint32_t current_offset = i_offset + file_header.size + mdlBlockInfo.offsets[i];
for (uint32_t j = 0; j < mdlBlockInfo.block_counts[i]; ++j)
{
extractBlock(current_offset, data_section);
current_offset += block_sizes[mdlBlockInfo.block_ids[i] + j];
}
}
}
break;
case FileType::texture:
{
outputFile->_type = FileType::texture;
// Extracts mipmap entries and the block sizes
uint32_t sectionCount = extract<uint32_t>(m_handle, "sections_count");
std::vector<DatTexFileBlockInfos> texBlockInfo;
extract<DatTexFileBlockInfos>(m_handle, sectionCount, texBlockInfo);
// Extracting block sizes
uint32_t block_count = texBlockInfo.back().block_id + texBlockInfo.back().block_count;
std::vector<uint16_t> block_sizes;
extract<uint16_t>(m_handle, "block_size", block_count, block_sizes);
outputFile->_data_sections.resize(sectionCount + 1);
// Extracting header in section 0
const uint32_t header_size = texBlockInfo.front().offset;
auto& header_section = outputFile->_data_sections[0];
header_section.resize(header_size);
m_handle.seekg(i_offset + file_header.size);
m_handle.read(header_section.data(), header_size);
// Extracting other sections
for (uint32_t i = 0; i < sectionCount; ++i)
{
auto& data_section = outputFile->_data_sections[i + 1];
auto& section_infos = texBlockInfo[i];
data_section.reserve(section_infos.uncompressed_size);
uint32_t current_offset = i_offset + file_header.size + section_infos.offset;
for (uint32_t j = 0; j < section_infos.block_count; ++j)
{
extractBlock(current_offset, data_section);
current_offset += block_sizes[section_infos.block_id + j];
}
}
}
break;
default:
throw std::runtime_error("Invalid entry_type: " + std::to_string(static_cast<uint32_t>(file_header.entry_type)));
}
}
return outputFile;
}
void Dat::extractBlock( uint32_t i_offset, std::vector<char>& o_data )
{
m_handle.seekg(i_offset);
DatBlockHeader block_header = extract<DatBlockHeader>(m_handle);
// Resizing the vector to write directly into it
const uint32_t data_size = o_data.size();
o_data.resize(data_size + block_header.uncompressed_size);
// 32000 in compressed_size means it is not compressed so take uncompressed_size
if (block_header.compressed_size == 32000)
{
m_handle.read(o_data.data() + data_size, block_header.uncompressed_size);
}
else
{
// If it is compressed use zlib
// Read the data to be decompressed
std::vector<char> temp_buffer(block_header.compressed_size);
m_handle.read(temp_buffer.data(), block_header.compressed_size);
utils::zlib::no_header_decompress(reinterpret_cast<uint8_t*>(temp_buffer.data()),
temp_buffer.size(),
reinterpret_cast<uint8_t*>(o_data.data() + data_size),
block_header.uncompressed_size);
}
}
uint32_t Dat::getNum() const
{
return m_num;
}
}
}

45
deps/datReader/Dat.h vendored Normal file
View file

@ -0,0 +1,45 @@
#ifndef XIV_DAT_DAT_H
#define XIV_DAT_DAT_H
#include "SqPack.h"
#include <mutex>
#include <experimental/filesystem>
namespace xiv
{
namespace dat
{
class File;
class Dat : public SqPack
{
public:
// Full path to the dat file
Dat( const std::experimental::filesystem::path& i_path, uint32_t i_nb );
virtual ~Dat();
// Retrieves a file given the offset in the dat file
std::unique_ptr<File> getFile( uint32_t i_offset );
// Appends to the vector the data of this block, it is assumed to be preallocated
// Is it also assumed that the m_fileMutex is currently locked by this thread before the call
void extractBlock( uint32_t i_offset, std::vector<char>& o_data );
// Returns the dat number
uint32_t getNum() const;
protected:
// File reading mutex to have only one thread reading the file at a time
std::mutex m_fileMutex;
// Dat nb
uint32_t m_num;
};
}
}
#endif // XIV_DAT_DAT_H

86
deps/datReader/DatCat.cpp vendored Normal file
View file

@ -0,0 +1,86 @@
#include "DatCat.h"
#include "Index.h"
#include "Dat.h"
#include "File.h"
#include "GameData.h"
namespace xiv
{
namespace dat
{
Cat::Cat( const std::experimental::filesystem::path& basePath, uint32_t catNum, const std::string& name ) :
m_name( name ),
m_catNum( catNum ),
m_chunk( -1 )
{
// From the category number, compute back the real filename for.index .datXs
std::stringstream ss;
ss << std::setw( 2 ) << std::setfill( '0' ) << std::hex << catNum;
std::string prefix = ss.str() + "0000.win32";
// Creates the index: XX0000.win32.index
m_index = std::unique_ptr<Index>( new Index( basePath / "//ffxiv" / ( prefix + ".index" ) ) );
// For all dat files linked to this index, create it: XX0000.win32.datX
for( uint32_t i = 0; i < getIndex().getDatCount(); ++i )
{
m_dats.emplace_back( std::unique_ptr<Dat>( new Dat( basePath / "//ffxiv" / ( prefix + ".dat" + std::to_string( i ) ), i ) ) );
}
}
Cat::Cat( const std::experimental::filesystem::path& basePath, uint32_t catNum, const std::string& name, uint32_t exNum, uint32_t chunk ) :
m_name( name ),
m_catNum( catNum ),
m_chunk( chunk )
{
// Creates the index: XX0000.win32.index
m_index = std::unique_ptr<Index>( new Index( basePath / GameData::buildDatStr( "ex" + std::to_string( exNum ), catNum, exNum, chunk, "win32", "index" ) ) );
// For all dat files linked to this index, create it: XX0000.win32.datX
for( uint32_t i = 0; i < getIndex().getDatCount(); ++i )
{
m_dats.emplace_back( std::unique_ptr<Dat>( new Dat( basePath / GameData::buildDatStr( "ex" + std::to_string( exNum ), catNum, exNum, chunk, "win32", "dat" + std::to_string( i ) ), i ) ) );
}
}
Cat::~Cat()
{
}
const Index& Cat::getIndex() const
{
return *m_index;
}
std::unique_ptr<File> Cat::getFile(uint32_t dir_hash, uint32_t filename_hash) const
{
// Fetch the correct hash_table_entry for these hashes, from that request the file from the right dat file
auto& hash_table_entry = getIndex().getHashTableEntry(dir_hash, filename_hash);
return m_dats[hash_table_entry.datNum]->getFile(hash_table_entry.datOffset);
}
bool Cat::doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const
{
return getIndex().doesFileExist( dir_hash, filename_hash );
}
bool Cat::doesDirExist( uint32_t dir_hash ) const
{
return getIndex().doesDirExist( dir_hash );
}
const std::string& Cat::getName() const
{
return m_name;
}
uint32_t Cat::getCatNum() const
{
return m_catNum;
}
}
}

64
deps/datReader/DatCat.h vendored Normal file
View file

@ -0,0 +1,64 @@
#ifndef XIV_DAT_CAT_H
#define XIV_DAT_CAT_H
#include <memory>
#include <vector>
#include <experimental/filesystem>
namespace xiv {
namespace dat {
class Index;
class Dat;
class File;
// A category represents an .index and its associated .datX
class Cat
{
public:
// basePath: Path to the folder containingthe datfiles
// catNum: The number of the category
// name: The name of the category, empty if not known
Cat( const std::experimental::filesystem::path& basePath, uint32_t catNum, const std::string& name );
// basePath: Path to the folder containingthe datfiles
// catNum: The number of the category
// name: The name of the category, empty if not known
// exNum: The number of the expansion to load from
// chunk: The chunk to load from
Cat( const std::experimental::filesystem::path& basePath, uint32_t catNum, const std::string& name, uint32_t exNum, uint32_t chunk );
~Cat();
// Returns .index of the category
const Index& getIndex() const;
// Retrieve a file from the category given its hashes
std::unique_ptr<File> getFile( uint32_t dir_hash, uint32_t filename_hash ) const;
bool doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const;
bool doesDirExist( uint32_t dir_hash ) const;
// Returns thename of the category
const std::string& getName() const;
// Returns the number of the category
uint32_t getCatNum() const;
protected:
const std::string m_name;
const uint32_t m_catNum;
const uint32_t m_chunk;
// The .index
std::unique_ptr<Index> m_index;
// The .datXs such as dat nb X => m_dats[X]
std::vector<std::unique_ptr<Dat>> m_dats;
};
}
}
#endif // XIV_DAT_CAT_H

278
deps/datReader/Exd.cpp vendored Normal file
View file

@ -0,0 +1,278 @@
#include "Exd.h"
#include "bparse.h"
#include "stream.h"
#include "Exh.h"
using xiv::utils::bparse::extract;
namespace xiv
{
namespace exd
{
struct ExdHeader
{
char magic[0x4];
uint16_t unknown;
uint16_t unknown2;
uint32_t index_size;
};
struct ExdRecordIndex
{
uint32_t id;
uint32_t offset;
};
}
}
namespace xiv
{
namespace utils
{
namespace bparse
{
template <> inline void reorder<xiv::exd::ExdHeader>( xiv::exd::ExdHeader& i_struct ) { for( int32_t i = 0; i < 0x4; ++i ) { xiv::utils::bparse::reorder( i_struct.magic[i] ); } i_struct.unknown = xiv::utils::bparse::byteswap( i_struct.unknown ); xiv::utils::bparse::reorder( i_struct.unknown ); i_struct.unknown2 = xiv::utils::bparse::byteswap( i_struct.unknown2 ); xiv::utils::bparse::reorder( i_struct.unknown2 ); i_struct.index_size = xiv::utils::bparse::byteswap( i_struct.index_size ); xiv::utils::bparse::reorder( i_struct.index_size ); }
template <> inline void reorder<xiv::exd::ExdRecordIndex>( xiv::exd::ExdRecordIndex& i_struct ) { i_struct.id = xiv::utils::bparse::byteswap( i_struct.id ); xiv::utils::bparse::reorder( i_struct.id ); i_struct.offset = xiv::utils::bparse::byteswap( i_struct.offset ); xiv::utils::bparse::reorder( i_struct.offset ); }
}
}
};
namespace xiv
{
namespace exd
{
Exd::Exd( std::shared_ptr<Exh> i_exh, const std::vector<std::shared_ptr<dat::File>>& i_files )
{
_exh = i_exh;
_files = i_files;
// Iterates over all the files
const uint32_t member_count = _exh->get_members().size();
for ( auto &file_ptr : _files )
{
// Get a stream
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
// Extract the header and skip to the record indices
auto exd_header = extract< ExdHeader >( iss );
iss.seekg( 0x20 );
// Preallocate and extract the record_indices
const uint32_t record_count = exd_header.index_size / sizeof( ExdRecordIndex );
std::vector< ExdRecordIndex > record_indices;
record_indices.reserve( record_count );
for ( uint32_t i = 0; i < record_count; ++i )
{
auto recordIndex = extract< ExdRecordIndex >( iss );
_idCache[recordIndex.id] = ExdCacheEntry{file_ptr, recordIndex.offset};
}
}
}
Exd::~Exd()
{
}
const std::vector<Field> Exd::get_row( uint32_t id )
{
auto cacheEntryIt = _idCache.find( id );
if( cacheEntryIt == _idCache.end() )
throw std::runtime_error( "Id not found: " + std::to_string( id ) );
// Iterates over all the files
const uint32_t member_count = _exh->get_members().size();
auto& file_ptr = cacheEntryIt->second.file;
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
// Get the vector fields for the given record and preallocate it
auto fields = _data[id];
fields.reserve( member_count );
for( auto& member_entry : _exh->get_exh_members() )
{
// Seek to the position of the member to extract.
// 6 is because we have uint32_t/uint16_t at the start of each record
iss.seekg( cacheEntryIt->second.offset + 6 + member_entry.offset );
// Switch depending on the type to extract
switch( member_entry.type )
{
case DataType::string:
// Extract the offset to the actual string
// Seek to it then extract the actual string
{
auto string_offset = extract<uint32_t>( iss, "string_offset", false );
iss.seekg( cacheEntryIt->second.offset + 6 + _exh->get_header().data_offset + string_offset );
fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
}
break;
case DataType::boolean:
fields.emplace_back( extract<bool>( iss, "bool" ) );
break;
case DataType::int8:
fields.emplace_back( extract<int8_t>( iss, "int8_t" ) );
break;
case DataType::uint8:
fields.emplace_back( extract<uint8_t>( iss, "uint8_t" ) );
break;
case DataType::int16:
fields.emplace_back( extract<int16_t>( iss, "int16_t", false ) );
break;
case DataType::uint16:
fields.emplace_back( extract<uint16_t>( iss, "uint16_t", false ) );
break;
case DataType::int32:
fields.emplace_back( extract<int32_t>( iss, "int32_t", false ) );
break;
case DataType::uint32:
fields.emplace_back( extract<uint32_t>( iss, "uint32_t", false ) );
break;
case DataType::float32:
fields.emplace_back( extract<float>( iss, "float", false ) );
break;
case DataType::uint64:
fields.emplace_back( extract<uint64_t>( iss, "uint64_t", false ) );
break;
default:
auto type = static_cast< uint16_t >( member_entry.type );
if( type < 0x19 || type > 0x20 )
throw std::runtime_error("Unknown DataType: " + std::to_string( type ));
uint64_t val = extract< uint64_t >( iss, "bool" );
int32_t shift = type - 0x19;
int32_t i = 1 << shift;
val &= i;
fields.emplace_back( ( val & i ) == i );
break;
}
}
return fields;
}
// Get all rows
const std::map<uint32_t, std::vector<Field>>& Exd::get_rows()
{
// Iterates over all the files
const uint32_t member_count = _exh->get_members().size();
for( auto& file_ptr : _files )
{
// Get a stream
std::vector< char > dataCpy = file_ptr->get_data_sections().front();
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
// Extract the header and skip to the record indices
auto exd_header = extract<ExdHeader>( iss );
iss.seekg( 0x20 );
// Preallocate and extract the record_indices
const uint32_t record_count = exd_header.index_size / sizeof( ExdRecordIndex );
std::vector<ExdRecordIndex> record_indices;
record_indices.reserve( record_count );
for( uint32_t i = 0; i < record_count; ++i )
{
record_indices.emplace_back( extract<ExdRecordIndex>( iss ) );
}
for( auto& record_index : record_indices )
{
// Get the vector fields for the given record and preallocate it
auto& fields = _data[record_index.id];
fields.reserve( member_count );
for( auto& member_entry : _exh->get_exh_members() )
//for( auto& member_entry : _exh->get_members() )
{
// Seek to the position of the member to extract.
// 6 is because we have uint32_t/uint16_t at the start of each record
iss.seekg( record_index.offset + 6 + member_entry.offset );
// Switch depending on the type to extract
switch( member_entry.type )
{
case DataType::string:
// Extract the offset to the actual string
// Seek to it then extract the actual string
{
auto string_offset = extract<uint32_t>( iss, "string_offset", false );
iss.seekg( record_index.offset + 6 + _exh->get_header().data_offset + string_offset );
fields.emplace_back( utils::bparse::extract_cstring( iss, "string" ) );
}
break;
case DataType::boolean:
fields.emplace_back( extract<bool>( iss, "bool" ) );
break;
case DataType::int8:
fields.emplace_back( extract<int8_t>( iss, "int8_t" ) );
break;
case DataType::uint8:
fields.emplace_back( extract<uint8_t>( iss, "uint8_t" ) );
break;
case DataType::int16:
fields.emplace_back( extract<int16_t>( iss, "int16_t", false ) );
break;
case DataType::uint16:
fields.emplace_back( extract<uint16_t>( iss, "uint16_t", false ) );
break;
case DataType::int32:
fields.emplace_back( extract<int32_t>( iss, "int32_t", false ) );
break;
case DataType::uint32:
fields.emplace_back( extract<uint32_t>( iss, "uint32_t", false ) );
break;
case DataType::float32:
fields.emplace_back( extract<float>( iss, "float", false ) );
break;
case DataType::uint64:
fields.emplace_back( extract<uint64_t>( iss, "uint64_t", false ) );
break;
default:
auto type = static_cast< uint16_t >( member_entry.type );
if( type < 0x19 || type > 0x20 )
throw std::runtime_error("Unknown DataType: " + std::to_string( type ));
uint64_t val = extract< uint64_t >( iss, "bool" );
int32_t shift = type - 0x19;
int32_t i = 1 << shift;
val &= i;
fields.emplace_back( ( val & i ) == i );
break;
}
}
}
}
return _data;
}
}
}

64
deps/datReader/Exd.h vendored Normal file
View file

@ -0,0 +1,64 @@
#ifndef XIV_EXD_EXD_H
#define XIV_EXD_EXD_H
#include <memory>
#include <map>
#include <variant>
#include "File.h"
namespace xiv
{
namespace exd
{
class Exh;
// Field type containing all the possible types in the data files
using Field = std::variant<
std::string,
bool,
int8_t,
uint8_t,
int16_t,
uint16_t,
int32_t,
uint32_t,
float,
uint64_t >;
struct ExdCacheEntry
{
std::shared_ptr<dat::File> file;
uint32_t offset;
};
// Data for a given language
class Exd
{
public:
// i_exh: the header
// i_files: the multiple exd files
Exd() {}
Exd(std::shared_ptr<Exh> i_exh, const std::vector<std::shared_ptr<dat::File>>& i_files);
~Exd();
// Get a row by its id
const std::vector<Field> get_row(uint32_t id);
// Get all rows
const std::map<uint32_t, std::vector<Field>>& get_rows();
protected:
// Data indexed by the ID of the row, the vector is field with the same order as exh.members
std::map<uint32_t, std::vector<Field>> _data;
std::vector<std::shared_ptr<dat::File>> _files;
std::shared_ptr<Exh> _exh;
std::map< uint32_t, ExdCacheEntry > _idCache;
};
}
}
#endif // XIV_EXD_EXD_H

82
deps/datReader/ExdCat.cpp vendored Normal file
View file

@ -0,0 +1,82 @@
#include "ExdCat.h"
#include <fstream>
#include "GameData.h"
#include "Exh.h"
#include "Exd.h"
namespace
{
// Suffix of the filenames given a language
std::map<xiv::exd::Language, std::string> language_map =
{{xiv::exd::Language::none, ""},
{xiv::exd::Language::ja, "_ja"},
{xiv::exd::Language::en, "_en"},
{xiv::exd::Language::de, "_de"},
{xiv::exd::Language::fr, "_fr"},
{xiv::exd::Language::chs, "_chs"}};
}
namespace xiv
{
namespace exd
{
Cat::Cat(dat::GameData& i_game_data, const std::string& i_name) :
_name(i_name)
{
//XIV_INFO(xiv_exd_logger, "Initializing Cat with name: " << i_name);
// creates the header .exh
{
auto header_file = i_game_data.getFile("exd/" + i_name + ".exh");
_header = std::shared_ptr< Exh >( new Exh( *header_file ) );
}
for(auto language: _header->get_languages())
{
// chs not yet in data files
if (language == Language::en || language == Language::none)
{
// Get all the files for a given category/language, in case of multiple range of IDs in separate files (like Quest)
std::vector<std::shared_ptr<dat::File>> files;
for(auto& exd_def: _header->get_exd_defs())
{
files.emplace_back( i_game_data.getFile("exd/" + i_name + "_" + std::to_string(exd_def.start_id) + language_map.at(language) + ".exd") );
}
// Instantiate the data for this language
_data[language] = std::unique_ptr<Exd>(new Exd(_header, files));
}
}
}
Cat::~Cat()
{
}
const std::string& Cat::get_name() const
{
return _name;
}
const Exh& Cat::get_header() const
{
return *_header;
}
const Exd& Cat::get_data_ln(Language i_language) const
{
auto ln_it = _data.find(i_language);
if (ln_it == _data.end())
{
throw std::runtime_error("No data for language: " + std::to_string(uint16_t(i_language)));
}
return *(ln_it->second);
}
}
}

66
deps/datReader/ExdCat.h vendored Normal file
View file

@ -0,0 +1,66 @@
#ifndef XIV_EXD_CAT_H
#define XIV_EXD_CAT_H
#include <memory>
#include <map>
#include <experimental/filesystem>
#include "bparse.h"
#include "Exd.h"
namespace xiv
{
namespace dat
{
class GameData;
}
namespace exd
{
// Language in the exd files - note: chs/chinese is present in the languages array but not in the data files
enum Language : uint16_t
{
none = 0,
ja = 1,
en = 2,
de = 3,
fr = 4,
chs = 5,
};
class Exh;
class Exd;
// A category repesent a several data sheets in the dats all under the same category
class Cat
{
public:
// i_name: name of the category
// i_game_data: used to fetch the files needed
Cat( dat::GameData& i_game_data, const std::string& i_name );
~Cat();
// Returns the name of the category
const std::string& get_name() const;
// Returns the header
const Exh& get_header() const;
// Returns data for a specific language
const Exd& get_data_ln( Language i_language = Language::none ) const;
protected:
const std::string _name;
// The header file of the category *.exh
std::shared_ptr<Exh> _header;
// The data files of the category, indexed by language *.exd
// Note that if we have multiple files for different range of IDs, they are merged here
std::map<Language, std::unique_ptr<Exd>> _data;
};
}
}
#endif // XIV_EXD_CAT_H

100
deps/datReader/ExdData.cpp vendored Normal file
View file

@ -0,0 +1,100 @@
#include "ExdData.h"
#include "stream.h"
#include "GameData.h"
#include "File.h"
#include "ExdCat.h"
namespace xiv
{
namespace exd
{
ExdData::ExdData(dat::GameData& i_game_data) try :
_game_data(i_game_data)
{
//XIV_INFO(xiv_exd_logger, "Initializing ExdData");
// Fetch the root.exl and get a stream from it
auto root_exl = i_game_data.getFile("exd/root.exl");
std::vector< char > dataCpy = root_exl->get_data_sections().front();
xiv::utils::stream::vectorwrapbuf<char> databuf(dataCpy);
std::istream stream(&databuf);
// Iterates over the lines while skipping the first one
std::string line;
std::getline(stream, line); // extract first line EXLT,2
std::getline(stream, line);
// Until the EOF
while (!line.empty())
{
// Format is cat_name,XX
// XX being an internal identifier
// Get only the cat_name
auto sep = line.find(',');
auto category = line.substr(0, sep);
// Add to the list of category name
// creates the empty category in the cats map
// instantiate the creation mutex for this category
_cat_names.push_back(category);
_cats[category] = std::unique_ptr<Cat>();
_cat_creation_mutexes[category] = std::unique_ptr<std::mutex>(new std::mutex());
std::getline(stream, line);
}
}
catch(std::exception& e)
{
// In case of failure here, client is supposed to catch the exception because it is not recoverable on our side
throw std::runtime_error( "ExdData initialization failed: " + std::string( e.what() ) );
}
ExdData::~ExdData()
{
}
const std::vector<std::string>& ExdData::get_cat_names() const
{
return _cat_names;
}
const Cat& ExdData::get_category(const std::string& i_cat_name)
{
// Get the category from its name
auto cat_it = _cats.find(i_cat_name);
if (cat_it == _cats.end())
{
throw std::runtime_error("Category not found: " + i_cat_name);
}
if (cat_it->second)
{
// If valid return it
return *(cat_it->second);
}
else
{
// If not, create it and return it
create_category(i_cat_name);
return *(_cats[i_cat_name]);
}
}
void ExdData::create_category(const std::string& i_cat_name)
{
// Lock mutex in this scope
std::lock_guard<std::mutex> lock(*(_cat_creation_mutexes[i_cat_name]));
// Maybe after unlocking it has already been created, so check (most likely if it blocked)
if (!_cats[i_cat_name])
{
_cats[i_cat_name] = std::unique_ptr<Cat>(new Cat(_game_data, i_cat_name));
}
}
}
}

57
deps/datReader/ExdData.h vendored Normal file
View file

@ -0,0 +1,57 @@
#ifndef XIV_EXD_EXDDATA_H
#define XIV_EXD_EXDDATA_H
#include <unordered_map>
#include <memory>
#include <mutex>
#include <experimental/filesystem>
namespace xiv
{
namespace dat
{
class GameData;
}
namespace exd
{
class Cat;
// Interface for retrieval of exd data - Main entry point
// the game_data object should outlive the exd_data object
class ExdData
{
public:
// Need an initialized dat::GameData to retrieve the files from the dat
ExdData(dat::GameData& i_game_data);
~ExdData();
// Get the list of thenames of the categories
const std::vector<std::string>& get_cat_names() const;
// Get a category by its name
const Cat& get_category(const std::string& i_cat_name);
// Export in csv in base flder i_ouput_path
void export_as_csvs(const std::experimental::filesystem::path& i_output_path);
protected:
// Lazy instantiation of category
void create_category(const std::string& i_cat_name);
// Reference to the game_data object
dat::GameData& _game_data;
// Categories, indexed by their name
std::unordered_map<std::string, std::unique_ptr<Cat>> _cats;
// List of category names = m_cats.keys()
std::vector<std::string> _cat_names;
// Mutexes used to avoid race condition when lazy instantiating a category
std::unordered_map<std::string, std::unique_ptr<std::mutex>> _cat_creation_mutexes;
};
}
}
#endif // XIV_EXD_EXDDATA_H

77
deps/datReader/Exh.cpp vendored Normal file
View file

@ -0,0 +1,77 @@
#include "Exh.h"
#include "stream.h"
#include "File.h"
#include <sstream>
using xiv::utils::bparse::extract;
namespace xiv
{
namespace exd
{
Exh::Exh(const dat::File& i_file)
{
// Get a stream from the file
std::vector< char > dataCpy = i_file.get_data_sections().front();
std::istringstream iss( std::string( dataCpy.begin(), dataCpy.end() ) );
// Extract header and skip to member definitions
_header = extract<ExhHeader>(iss);
iss.seekg(0x20);
// Extract all the members and feed the _members map
for (auto i = 0; i < _header.field_count; ++i)
{
auto member = extract<ExhMember>(iss);
_members[member.offset] = member;
_exh_defs.push_back( member );
}
// Extract all the exd_defs
_exd_defs.reserve(_header.exd_count);
for (auto i = 0; i < _header.exd_count; ++i)
{
_exd_defs.emplace_back(extract<ExhExdDef>(iss));
}
// Extract all the languages
_languages.reserve(_header.language_count);
for (auto i = 0; i < _header.language_count; ++i)
{
_languages.emplace_back(Language(extract<uint16_t>(iss, "language")));
}
}
Exh::~Exh()
{
}
const ExhHeader& Exh::get_header() const
{
return _header;
}
const std::vector<ExhExdDef>& Exh::get_exd_defs() const
{
return _exd_defs;
}
const std::vector<Language>& Exh::get_languages() const
{
return _languages;
}
const std::map<uint32_t, ExhMember>& Exh::get_members() const
{
return _members;
}
const std::vector<ExhMember>& Exh::get_exh_members() const
{
return _exh_defs;
}
}
}

100
deps/datReader/Exh.h vendored Normal file
View file

@ -0,0 +1,100 @@
#ifndef XIV_EXD_EXH_H
#define XIV_EXD_EXH_H
#include <map>
#include "bparse.h"
namespace xiv
{
namespace exd
{
enum class DataType : uint16_t
{
string = 0,
boolean = 1,
int8 = 2,
uint8 = 3,
int16 = 4,
uint16 = 5,
int32 = 6,
uint32 = 7,
float32 = 9,
uint64 = 11,
};
struct ExhHeader
{
char magic[0x4];
uint16_t unknown;
uint16_t data_offset;
uint16_t field_count;
uint16_t exd_count;
uint16_t language_count;
};
struct ExhMember
{
DataType type;
uint16_t offset;
};
struct ExhExdDef
{
uint32_t start_id;
uint32_t count_id;
};
}
};
namespace xiv
{
namespace utils
{
namespace bparse
{
template <> inline void reorder<xiv::exd::ExhHeader>( xiv::exd::ExhHeader& i_struct ) { for( int32_t i = 0; i < 0x4; ++i ) { xiv::utils::bparse::reorder( i_struct.magic[i] ); } i_struct.unknown = xiv::utils::bparse::byteswap( i_struct.unknown ); xiv::utils::bparse::reorder( i_struct.unknown ); i_struct.data_offset = xiv::utils::bparse::byteswap( i_struct.data_offset ); xiv::utils::bparse::reorder( i_struct.data_offset ); i_struct.field_count = xiv::utils::bparse::byteswap( i_struct.field_count ); xiv::utils::bparse::reorder( i_struct.field_count ); i_struct.exd_count = xiv::utils::bparse::byteswap( i_struct.exd_count ); xiv::utils::bparse::reorder( i_struct.exd_count ); i_struct.language_count = xiv::utils::bparse::byteswap( i_struct.language_count ); xiv::utils::bparse::reorder( i_struct.language_count ); }
template <> inline void reorder<xiv::exd::ExhMember>( xiv::exd::ExhMember& i_struct ) { i_struct.type = xiv::utils::bparse::byteswap( i_struct.type ); xiv::utils::bparse::reorder( i_struct.type ); i_struct.offset = xiv::utils::bparse::byteswap( i_struct.offset ); xiv::utils::bparse::reorder( i_struct.offset ); }
template <> inline void reorder<xiv::exd::ExhExdDef>( xiv::exd::ExhExdDef& i_struct ) { i_struct.start_id = xiv::utils::bparse::byteswap( i_struct.start_id ); xiv::utils::bparse::reorder( i_struct.start_id ); i_struct.count_id = xiv::utils::bparse::byteswap( i_struct.count_id ); xiv::utils::bparse::reorder( i_struct.count_id ); }
}
}
};
namespace xiv
{
namespace dat
{
class File;
}
namespace exd
{
enum Language : uint16_t;
// Header file for exd data
class Exh
{
public:
// The header file
Exh( const dat::File& i_file );
~Exh();
const ExhHeader& get_header() const;
const std::vector<ExhExdDef>& get_exd_defs() const;
const std::vector<Language>& get_languages() const;
const std::map<uint32_t, ExhMember>& get_members() const;
const std::vector<ExhMember>& get_exh_members() const;
protected:
ExhHeader _header;
// Members of the datastruct ordered(indexed) by offset
std::map<uint32_t, ExhMember> _members;
std::vector<ExhMember> _exh_defs;
std::vector<ExhExdDef> _exd_defs;
std::vector<Language> _languages;
};
}
}
#endif // XIV_EXD_EXH_H

45
deps/datReader/File.cpp vendored Normal file
View file

@ -0,0 +1,45 @@
#include "File.h"
#include <fstream>
namespace xiv
{
namespace dat
{
File::File() :
_type(FileType::empty)
{
}
File::~File()
{
}
FileType File::get_type() const
{
return _type;
}
const std::vector<std::vector<char>>& File::get_data_sections() const
{
return _data_sections;
}
std::vector<std::vector<char>>& File::access_data_sections()
{
return _data_sections;
}
void File::exportToFile(const std::experimental::filesystem::path& i_path) const
{
std::ofstream ofs( i_path.string(), std::ios_base::binary | std::ios_base::out );
for( auto& data_section : _data_sections )
{
ofs.write( data_section.data(), data_section.size() );
}
ofs.close();
}
}
}

56
deps/datReader/File.h vendored Normal file
View file

@ -0,0 +1,56 @@
#ifndef XIV_DAT_FILE_H
#define XIV_DAT_FILE_H
#include <vector>
#include <experimental/filesystem>
#include <stdint.h>
#include "bparse.h"
namespace xiv
{
namespace dat
{
enum class FileType : uint32_t
{
empty = 1,
standard = 2,
model = 3,
texture = 4,
};
}
};
namespace xiv
{
namespace dat
{
class Dat;
// Basic file from the dats
class File
{
friend class Dat;
public:
File();
~File();
FileType get_type() const;
// Getters functions for the data in the file
const std::vector<std::vector<char>>& get_data_sections() const;
std::vector<std::vector<char>>& access_data_sections();
void exportToFile( const std::experimental::filesystem::path& i_path ) const;
protected:
FileType _type;
std::vector<std::vector<char>> _data_sections;
};
}
}
#endif // XIV_DAT_FILE_H

315
deps/datReader/GameData.cpp vendored Normal file
View file

@ -0,0 +1,315 @@
#include "GameData.h"
#include <string>
#include <sstream>
#include <algorithm>
#include <map>
#include <zlib/zlib.h>
#include "bparse.h"
#include "DatCat.h"
#include "File.h"
namespace
{
// Relation between category number and category name
// These names are taken straight from the exe, it helps resolve dispatching when getting files by path
std::unordered_map< std::string, uint32_t > categoryNameToIdMap =
{{"common", 0x00},
{"bgcommon", 0x01},
{"bg", 0x02},
{"cut", 0x03},
{"chara", 0x04},
{"shader", 0x05},
{"ui", 0x06},
{"sound", 0x07},
{"vfx", 0x08},
{"ui_script", 0x09},
{"exd", 0x0A},
{"game_script", 0x0B},
{"music", 0x0C}
};
std::unordered_map< uint32_t, std::string > categoryIdToNameMap =
{{0x00, "common"},
{0x01, "bgcommon"},
{0x02, "bg"},
{0x03, "cut"},
{0x04, "chara"},
{0x05, "shader"},
{0x06, "ui"},
{0x07, "sound"},
{0x08, "vfx"},
{0x09, "ui_script"},
{0x0A, "exd"},
{0x0B, "game_script"},
{0x0C, "music"}};
}
namespace xiv
{
namespace dat
{
GameData::GameData(const std::experimental::filesystem::path& path) try :
m_path(path)
{
int maxExLevel = 0;
// Determine which expansions are available
while( std::experimental::filesystem::exists( std::experimental::filesystem::path( m_path.string() + "\\ex" + std::to_string( maxExLevel + 1) + "\\ex" + std::to_string( maxExLevel + 1) + ".ver" ) ) )
{
maxExLevel++;
}
// Iterate over the files in path
for( auto it = std::experimental::filesystem::directory_iterator( m_path.string() + "//ffxiv" ); it != std::experimental::filesystem::directory_iterator(); ++it )
{
// Get the filename of the current element
auto filename = it->path().filename().string();
// If it contains ".win32.index" this is most likely a hit for a category
if( filename.find( ".win32.index" ) != std::string::npos && filename.find( ".win32.index2" ) == std::string::npos )
{
// Format of indexes is XX0000.win32.index, so fetch the hex number for category number
std::istringstream iss( filename.substr( 0, 2 ) );
uint32_t cat_nb;
iss >> std::hex >> cat_nb;
// Add to the list of category number
// creates the empty category in the cats map
// instantiate the creation mutex for this category
m_catNums.push_back( cat_nb );
m_cats[cat_nb] = std::unique_ptr<Cat>();
m_catCreationMutexes[cat_nb] = std::unique_ptr<std::mutex>( new std::mutex() );
// Check for expansion
for( int exNum = 1; exNum <= maxExLevel; exNum++ )
{
const std::string path = m_path.string() + "\\" + buildDatStr( "ex" + std::to_string( exNum ), cat_nb, exNum, 0, "win32", "index" );
if( std::experimental::filesystem::exists( std::experimental::filesystem::path( path ) ) )
{
int chunkCount = 0;
for(int chunkTest = 0; chunkTest < 256; chunkTest++ )
{
if( std::experimental::filesystem::exists( m_path.string() + "\\" + buildDatStr( "ex" + std::to_string( exNum ), cat_nb, exNum, chunkTest, "win32", "index" ) ) )
{
m_exCats[cat_nb].exNumToChunkMap[exNum].chunkToCatMap[chunkTest] = std::unique_ptr<Cat>();
chunkCount++;
}
}
}
}
}
}
}
catch( std::exception& e )
{
// In case of failure here, client is supposed to catch the exception because it is not recoverable on our side
throw std::runtime_error( "GameData initialization failed: " + std::string( e.what() ) );
}
GameData::~GameData()
{
}
const std::string GameData::buildDatStr( const std::string folder, const int cat, const int exNum, const int chunk, const std::string platform, const std::string type )
{
char dat[1024];
sprintf( dat, "%s/%02x%02x%02x.%s.%s", folder.c_str(), cat, exNum, chunk, platform.c_str(), type.c_str() );
return std::string( dat );
}
const std::vector<uint32_t>& GameData::getCatNumbers() const
{
return m_catNums;
}
std::unique_ptr<File> GameData::getFile(const std::string& path)
{
// Get the hashes, the category from the path then call the getFile of the category
uint32_t dirHash;
uint32_t filenameHash;
getHashes( path, dirHash, filenameHash );
return getCategoryFromPath( path ).getFile( dirHash, filenameHash );
}
bool GameData::doesFileExist(const std::string& path)
{
uint32_t dirHash;
uint32_t filenameHash;
getHashes( path, dirHash, filenameHash );
return getCategoryFromPath( path ).doesFileExist( dirHash, filenameHash );
}
bool GameData::doesDirExist(const std::string& i_path)
{
uint32_t dirHash;
uint32_t filenameHash;
getHashes( i_path, dirHash, filenameHash );
return getCategoryFromPath( i_path ).doesDirExist( dirHash );
}
const Cat& GameData::getCategory(uint32_t catNum)
{
// Check that the category number exists
auto catIt = m_cats.find( catNum );
if( catIt == m_cats.end() )
{
throw std::runtime_error( "Category not found: " + std::to_string( catNum ) );
}
// If it exists and already instantiated return it
if( catIt->second )
{
return *( catIt->second );
}
else
{
// Else create it and return it
createCategory( catNum );
return *( m_cats[catNum] );
}
}
const Cat& GameData::getCategory(const std::string& catName)
{
// Find the category number from the name
auto categoryNameToIdMapIt = ::categoryNameToIdMap.find( catName );
if( categoryNameToIdMapIt == ::categoryNameToIdMap.end() )
{
throw std::runtime_error( "Category not found: " + catName );
}
// From the category number return the category
return getCategory( categoryNameToIdMapIt->second );
}
const Cat& GameData::getExCategory( const std::string& catName, uint32_t exNum, const std::string& path )
{
// Find the category number from the name
auto categoryMapIt = ::categoryNameToIdMap.find( catName );
if( categoryMapIt == ::categoryNameToIdMap.end() )
{
throw std::runtime_error( "Category not found: " + catName );
}
uint32_t dirHash;
uint32_t filenameHash;
getHashes( path, dirHash, filenameHash );
for( auto const& chunk : m_exCats[categoryMapIt->second].exNumToChunkMap[exNum].chunkToCatMap )
{
if( !chunk.second )
createExCategory( categoryMapIt->second );
if( chunk.second->doesFileExist( dirHash, filenameHash ) )
{
return *( chunk.second );
}
}
throw std::runtime_error( "Chunk not found for path: " + path );
}
const Cat& GameData::getCategoryFromPath(const std::string& path)
{
// Find the first / in the string, paths are in the format CAT_NAME/..../.../../....
auto firstSlashPos = path.find( '/' );
if( firstSlashPos == std::string::npos )
{
throw std::runtime_error( "Path does not have a / char: " + path );
}
if( path.substr( firstSlashPos + 1, 2) == "ex" )
{
return getExCategory( path.substr( 0, firstSlashPos ), std::stoi( path.substr( firstSlashPos + 3, 1 ) ), path );
}
else
{
// From the sub string found beforethe first / get the category
return getCategory( path.substr( 0, firstSlashPos ) );
}
}
void GameData::getHashes(const std::string& path, uint32_t& dirHash, uint32_t& filenameHash) const
{
// Convert the path to lowercase before getting the hashes
std::string pathLower;
pathLower.resize( path.size() );
std::transform( path.begin(), path.end(), pathLower.begin(), ::tolower );
// Find last / to separate dir from filename
auto lastSlashPos = pathLower.rfind( '/' );
if( lastSlashPos == std::string::npos )
{
throw std::runtime_error( "Path does not have a / char: " + path );
}
std::string dirPart = pathLower.substr( 0, lastSlashPos );
std::string filenamePart = pathLower.substr( lastSlashPos + 1 );
// Get the crc32 values from zlib, to compensate the final XOR 0xFFFFFFFF that isnot done in the exe we just reXOR
dirHash = crc32( 0, reinterpret_cast<const uint8_t*>( dirPart.data() ), dirPart.size() ) ^ 0xFFFFFFFF;
filenameHash = crc32( 0, reinterpret_cast<const uint8_t*>( filenamePart.data() ), filenamePart.size() ) ^ 0xFFFFFFFF;
}
void GameData::createCategory(uint32_t catNum)
{
// Lock mutex in this scope
std::lock_guard<std::mutex> lock( *( m_catCreationMutexes[catNum] ) );
// Maybe after unlocking it has already been created, so check (most likely if it blocked)
if( !m_cats[catNum] )
{
// Get the category name if we have it
std::string catName;
auto categoryMapIt = ::categoryIdToNameMap.find( catNum );
if( categoryMapIt != ::categoryIdToNameMap.end() )
{
catName = categoryMapIt->second;
}
// Actually creates the category
m_cats[catNum] = std::unique_ptr<Cat>( new Cat( m_path, catNum, catName ) );
}
}
void GameData::createExCategory( uint32_t catNum )
{
// Maybe after unlocking it has already been created, so check (most likely if it blocked)
if( !m_exCats[catNum].exNumToChunkMap[1].chunkToCatMap[0] )
{
// Get the category name if we have it
std::string catName;
auto categoryMapIt = ::categoryIdToNameMap.find( catNum );
if( categoryMapIt != ::categoryIdToNameMap.end() )
{
catName = categoryMapIt->second;
}
for( auto const& ex : m_exCats[catNum].exNumToChunkMap )
{
for( auto const& chunk : m_exCats[catNum].exNumToChunkMap[ex.first].chunkToCatMap )
{
// Actually creates the category
m_exCats[catNum].exNumToChunkMap[ex.first].chunkToCatMap[chunk.first] = std::unique_ptr<Cat>( new Cat( m_path, catNum, catName, ex.first, chunk.first ) );
}
}
}
}
}
}

84
deps/datReader/GameData.h vendored Normal file
View file

@ -0,0 +1,84 @@
#ifndef XIV_DAT_GAMEDATA_H
#define XIV_DAT_GAMEDATA_H
#include <memory>
#include <unordered_map>
#include <mutex>
#include <experimental/filesystem>
namespace xiv
{
namespace dat
{
class Cat;
class File;
// Interface to all the datfiles - Main entry point
// All the paths to files/dirs inside the dats are case-insensitive
class GameData
{
public:
// This should be the path in which the .index/.datX files are located
GameData( const std::experimental::filesystem::path& path );
~GameData();
static const std::string buildDatStr( const std::string folder, const int cat, const int exNum, const int chunk, const std::string platform, const std::string type );
// Returns all the scanned category number available in the path
const std::vector<uint32_t>& getCatNumbers() const;
// Return a specific category by its number (see getCatNumbers() for loops)
const Cat& getCategory( uint32_t catNum );
// Return a specific category by it's name (e.g.: "exd"/"game_script"/ etc...)
const Cat& getCategory( const std::string& catName );
const Cat& getExCategory( const std::string& catName, uint32_t exNum, const std::string& path );
// Retrieve a file from the dats given its filename
std::unique_ptr<File> getFile( const std::string& path );
// Checks that a file exists
bool doesFileExist( const std::string& path );
// Checks that a dir exists, there must be a trailing / in the path
// Note that it won't work for dirs that don't contain any file
// e.g.: - "ui/icon/" will return False
// - "ui/icon/000000/" will return True
bool doesDirExist( const std::string& path );
protected:
// Return a specific category given a path (calls const Cat& getCategory(const std::string& catName))
const Cat& getCategoryFromPath( const std::string& path );
// From a full path, returns the dirHash and the filenameHash
void getHashes( const std::string& path, uint32_t& dirHash, uint32_t& filenameHash ) const;
// Lazy instantiation of category
void createCategory( uint32_t catNum );
void createExCategory( uint32_t catNum );
// Path given to constructor, pointing to the folder with the .index/.datX files
const std::experimental::filesystem::path m_path;
// Stored categories, indexed by their number, categories are instantiated and parsed individually when they are needed
std::unordered_map<uint32_t, std::unique_ptr<Cat>> m_cats;
// List of all the categories numbers, is equal to m_cats.keys()
std::vector<uint32_t> m_catNums;
// Map of all EX categories and their chunks, "CatNum - (ExNum - (ChunkNum - Cat))"
// Map of all EX categories and their chunks, "CatNum - (ExNum - (ChunkNum - Cat))"
using ChunkToCatMap = struct { std::unordered_map< uint32_t, std::unique_ptr< Cat > > chunkToCatMap; };
using ExNumToChunkMap = struct { std::unordered_map< uint32_t, ChunkToCatMap > exNumToChunkMap; };
using CatNumToExNumMap = std::unordered_map< uint32_t, ExNumToChunkMap >;
CatNumToExNumMap m_exCats;
std::unordered_map<uint32_t, std::unique_ptr<std::mutex>> m_catCreationMutexes;
};
}
}
#endif // XIV_DAT_GAMEDATA_H

167
deps/datReader/Index.cpp vendored Normal file
View file

@ -0,0 +1,167 @@
#include "Index.h"
#include "bparse.h"
namespace xiv
{
namespace dat
{
struct IndexBlockRecord
{
uint32_t offset;
uint32_t size;
SqPackBlockHash blockHash;
};
struct IndexHashTableEntry
{
uint32_t filenameHash;
uint32_t dirHash;
uint32_t datOffset;
uint32_t padding;
};
}
}
namespace xiv
{
namespace utils
{
namespace bparse
{
template <>
inline void reorder<xiv::dat::IndexBlockRecord>(xiv::dat::IndexBlockRecord& i_struct)
{
xiv::utils::bparse::reorder(i_struct.offset);
xiv::utils::bparse::reorder(i_struct.size);
xiv::utils::bparse::reorder(i_struct.blockHash);
}
template <>
inline void reorder<xiv::dat::IndexHashTableEntry>(xiv::dat::IndexHashTableEntry& i_struct)
{
xiv::utils::bparse::reorder(i_struct.filenameHash);
xiv::utils::bparse::reorder(i_struct.dirHash);
xiv::utils::bparse::reorder(i_struct.datOffset);
xiv::utils::bparse::reorder(i_struct.padding);
}
}
}
};
using xiv::utils::bparse::extract;
namespace xiv
{
namespace dat
{
Index::Index(const std::experimental::filesystem::path& path) :
SqPack( path )
{
if( !m_handle )
throw new std::runtime_error( "Failed to load Index at " + path.string() );
// Hash Table record
auto hashTableBlockRecord = extract<IndexBlockRecord>( m_handle );
isIndexBlockValid( hashTableBlockRecord );
// Save the posin the stream to go back to it later on
auto pos = m_handle.tellg();
// Seek to the pos of the hash table in the file
m_handle.seekg( hashTableBlockRecord.offset );
// Preallocate and extract the index_hash_table_entries
std::vector<IndexHashTableEntry> indexHashTableEntries;
extract<IndexHashTableEntry>( m_handle, hashTableBlockRecord.size / sizeof( IndexHashTableEntry ),
indexHashTableEntries );
// Feed the correct entry in the HashTable for each index_hash_table_entry
for( auto& indexHashTableEntry : indexHashTableEntries )
{
auto& hashTableEntry = m_hashTable[indexHashTableEntry.dirHash][indexHashTableEntry.filenameHash];
// The dat number is found in the offset, last four bits
hashTableEntry.datNum = ( indexHashTableEntry.datOffset & 0xF ) / 0x2;
// The offset in the dat file, needs to strip the dat number indicator
hashTableEntry.datOffset = ( indexHashTableEntry.datOffset & 0xFFFFFFF0 ) * 0x08;
hashTableEntry.dirHash = indexHashTableEntry.dirHash;
hashTableEntry.filenameHash = indexHashTableEntry.filenameHash;
}
// Come back to where we were before reading the HashTable
m_handle.seekg( pos );
// Dat Count
m_datCount = extract<uint32_t>( m_handle, "dat_count" );
// Free List
isIndexBlockValid( extract<IndexBlockRecord>( m_handle ) );
// Dir Hash Table
isIndexBlockValid( extract<IndexBlockRecord>( m_handle ) );
}
Index::~Index()
{
}
uint32_t Index::getDatCount() const
{
return m_datCount;
}
const Index::HashTable& Index::getHashTable() const
{
return m_hashTable;
}
bool Index::doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const
{
auto dir_it = getHashTable().find( dir_hash );
if( dir_it != getHashTable().end() )
{
return ( dir_it->second.find( filename_hash ) != dir_it->second.end() );
}
return false;
}
bool Index::doesDirExist( uint32_t dir_hash ) const
{
return ( getHashTable().find( dir_hash ) != getHashTable().end() );
}
const Index::DirHashTable& Index::getDirHashTable( uint32_t dir_hash ) const
{
auto dir_it = getHashTable().find( dir_hash );
if( dir_it == getHashTable().end() )
{
throw std::runtime_error( "dirHash not found" );
}
else
{
return dir_it->second;
}
}
const Index::HashTableEntry& Index::getHashTableEntry( uint32_t dir_hash, uint32_t filename_hash ) const
{
auto& dirHashTable = getDirHashTable( dir_hash );
auto file_it = dirHashTable.find( filename_hash );
if( file_it == dirHashTable.end() )
{
throw std::runtime_error( "filenameHash not found" );
}
else
{
return file_it->second;
}
}
void Index::isIndexBlockValid( const IndexBlockRecord& i_index_block_record )
{
isBlockValid( i_index_block_record.offset, i_index_block_record.size, i_index_block_record.blockHash );
}
}
}

59
deps/datReader/Index.h vendored Normal file
View file

@ -0,0 +1,59 @@
#ifndef XIV_DAT_INDEX_H
#define XIV_DAT_INDEX_H
#include "SqPack.h"
#include <unordered_map>
#include <experimental/filesystem>
namespace xiv {
namespace dat {
struct IndexBlockRecord;
class Index : public SqPack
{
public:
// Full path to the index file
Index( const std::experimental::filesystem::path& i_path );
virtual ~Index();
// An entry in the hash table, representing a file in a given dat
struct HashTableEntry
{
uint32_t datNum;
uint32_t dirHash;
uint32_t filenameHash;
uint32_t datOffset;
};
// HashTable has dir hashes -> filename hashes -> HashTableEntry
using DirHashTable = std::unordered_map< uint32_t, HashTableEntry >;
using HashTable = std::unordered_map< uint32_t, DirHashTable >;
// Get the number of dat files the index is linked to
uint32_t getDatCount() const;
bool doesFileExist( uint32_t dir_hash, uint32_t filename_hash ) const;
bool doesDirExist( uint32_t dir_hash ) const;
// Returns the whole HashTable
const HashTable& getHashTable() const;
// Returns the hash table for a specific dir
const DirHashTable& getDirHashTable( uint32_t dir_hash ) const;
// Returns the HashTableEntry for a given file given its hashes
const HashTableEntry& getHashTableEntry( uint32_t dir_hash, uint32_t filename_hash ) const;
protected:
// Checks that the block is valid with regards to its hash
void isIndexBlockValid( const IndexBlockRecord& i_index_block_record );
uint32_t m_datCount;
HashTable m_hashTable;
};
}
}
#endif // XIV_DAT_INDEX_H

76
deps/datReader/SqPack.cpp vendored Normal file
View file

@ -0,0 +1,76 @@
#include "SqPack.h"
namespace xiv {
namespace dat {
struct SqPackHeader
{
char magic[0x8];
uint32_t zero;
uint32_t size;
uint32_t version;
uint32_t type;
};
struct SqPackIndexHeader
{
uint32_t size;
uint32_t type;
};
}
}
namespace xiv {
namespace utils {
namespace bparse {
template <>
inline void reorder<xiv::dat::SqPackHeader>(xiv::dat::SqPackHeader& i_struct)
{
for (int32_t i = 0; i < 0x8; ++i)
{
xiv::utils::bparse::reorder(i_struct.magic[i]);
}
xiv::utils::bparse::reorder(i_struct.zero);
xiv::utils::bparse::reorder(i_struct.size);
xiv::utils::bparse::reorder(i_struct.version);
xiv::utils::bparse::reorder(i_struct.type);
}
template <>
inline void reorder<xiv::dat::SqPackIndexHeader>(xiv::dat::SqPackIndexHeader& i_struct)
{
xiv::utils::bparse::reorder(i_struct.size);
xiv::utils::bparse::reorder(i_struct.type);
}
}
}
};
using xiv::utils::bparse::extract;
namespace xiv
{
namespace dat
{
SqPack::SqPack( const std::experimental::filesystem::path& path ) :
// Open the file
m_handle( path.string(), std::ios_base::in | std::ios_base::binary )
{
// Extract the header
extract<SqPackHeader>( m_handle );
// Skip until the IndexHeader the extract it
m_handle.seekg( 0x400 );
extract<SqPackIndexHeader>( m_handle );
}
SqPack::~SqPack()
{
}
void SqPack::isBlockValid( uint32_t i_offset, uint32_t i_size, const SqPackBlockHash& i_block_hash )
{
// TODO
}
}
}

66
deps/datReader/SqPack.h vendored Normal file
View file

@ -0,0 +1,66 @@
#ifndef XIV_DAT_SQPACK_H
#define XIV_DAT_SQPACK_H
#include <fstream>
#include <experimental/filesystem>
#include "bparse.h"
namespace xiv
{
namespace dat
{
struct SqPackBlockHash
{
uint8_t hash[0x14];
uint32_t padding[0xB];
};
}
}
namespace xiv {
namespace utils {
namespace bparse {
template <> inline void reorder<xiv::dat::SqPackBlockHash>( xiv::dat::SqPackBlockHash& i_struct )
{
for( auto i = 0; i < 0x14; ++i )
{
xiv::utils::bparse::reorder( i_struct.hash[i] );
}
for( auto i = 0; i < 0xB; ++i )
{
xiv::utils::bparse::reorder( i_struct.padding[i] );
}
}
}
}
};
namespace xiv
{
namespace dat
{
class SqPack
{
public:
// Full path to the sqpack file
SqPack( const std::experimental::filesystem::path& i_path );
virtual ~SqPack();
protected:
// Checks that a given block is valid iven its hash
void isBlockValid( uint32_t i_offset, uint32_t i_size, const SqPackBlockHash& i_block_hash );
// File handle
std::ifstream m_handle;
};
}
}
#endif // XIV_DAT_SQPACK_H

8
deps/datReader/bparse.cpp vendored Normal file
View file

@ -0,0 +1,8 @@
#include "bparse.h"
std::string xiv::utils::bparse::extract_cstring( std::istream& i_stream, const std::string& i_name )
{
std::string temp_str;
std::getline( i_stream, temp_str, '\0' );
return temp_str;
}

103
deps/datReader/bparse.h vendored Normal file
View file

@ -0,0 +1,103 @@
#ifndef XIV_UTILS_BPARSE_H
#define XIV_UTILS_BPARSE_H
#include <type_traits>
#include <iomanip>
#include <sstream>
#include <vector>
namespace xiv
{
namespace utils
{
namespace bparse
{
// Internal macro for byteswapping
template <int N>
void byteswap_impl(char (&bytes)[N])
{
for( auto p = std::begin( bytes ), end = std::end( bytes ) - 1; p < end; ++p, --end )
{
std::swap( *p, *end );
}
}
// byteswapping any type (no pointers to array)
template <typename T>
T byteswap(T value)
{
byteswap_impl(*reinterpret_cast<char (*)[sizeof(T)]>(&value));
return value;
}
// Read a struct from a stream
template <typename StructType>
void read(std::istream& i_stream, StructType& i_struct)
{
static_assert( std::is_pod<StructType>::value, "StructType must be a POD to be able to use read." );
i_stream.read( reinterpret_cast<char*>( &i_struct ), sizeof( StructType ) );
}
// By default a type does not need reordering
template <typename StructType> void reorder(StructType& i_struct) {}
// "Overload" for passed struct as arg
template <typename StructType>
void extract(std::istream& i_stream, StructType& o_struct)
{
read( i_stream, o_struct );
reorder( o_struct );
}
// This should not copy because of RVO
// Extract a struct from a stream and log it
template <typename StructType>
StructType extract( std::istream& i_stream )
{
StructType temp_struct;
extract<StructType>( i_stream, temp_struct );
return temp_struct;
}
template <typename StructType>
void extract(std::istream& i_stream, uint32_t i_size, std::vector<StructType>& o_structs )
{
o_structs.reserve( i_size );
for( uint32_t i = 0; i < i_size; ++i )
{
o_structs.emplace_back( extract<StructType>( i_stream ) );
}
}
// For simple (integral) types just provide name and endianness directly
template <typename StructType>
StructType extract(std::istream& i_stream, const std::string& i_name, bool i_is_le = true)
{
StructType temp_struct;
read( i_stream, temp_struct );
if( !i_is_le )
{
temp_struct = byteswap( temp_struct );
}
return temp_struct;
}
template <typename StructType>
void extract(std::istream& i_stream, const std::string& i_name, uint32_t i_size, std::vector<StructType>& o_structs, bool i_is_le = true)
{
o_structs.reserve( i_size );
for( uint32_t i = 0; i < i_size; ++i )
{
o_structs.emplace_back( extract<StructType>( i_stream, i_name ) );
}
}
// For cstrings
std::string extract_cstring( std::istream& i_stream, const std::string& i_name );
}
}
}
#endif // XIV_UTILS_BPARSE_H

35
deps/datReader/conv.cpp vendored Normal file
View file

@ -0,0 +1,35 @@
#include "conv.h"
namespace xiv {
namespace utils {
namespace conv {
float half2float( const uint16_t i_value )
{
uint32_t t1;
uint32_t t2;
uint32_t t3;
t1 = i_value & 0x7fff; // Non-sign bits
t2 = i_value & 0x8000; // Sign bit
t3 = i_value & 0x7c00; // Exponent
t1 <<= 13; // Align mantissa on MSB
t2 <<= 16; // Shift sign bit into position
t1 += 0x38000000; // Adjust bias
t1 = ( t3 == 0 ? 0 : t1 ); // Denormals-as-zero
t1 |= t2; // Re-insert sign bit
return *reinterpret_cast< float* >( &t1 );
}
float ubyte2float( const uint8_t i_value )
{
return i_value / 255.0f;
}
}
}
}

17
deps/datReader/conv.h vendored Normal file
View file

@ -0,0 +1,17 @@
#ifndef XIV_UTILS_CONV_H
#define XIV_UTILS_CONV_H
#include <cstdint>
#include <vector>
#include <ostream>
namespace xiv {
namespace utils {
namespace conv {
float half2float( const uint16_t i_value );
float ubyte2float( const uint8_t i_value );
}
}
}
#endif // XIV_UTILS_CONV_H

180
deps/datReader/crc32.cpp vendored Normal file
View file

@ -0,0 +1,180 @@
#include "crc32.h"
#include <mutex>
#include <vector>
#include <zlib/zlib.h>
namespace internal
{
// Mutex to prevent two threads from concurrently trying to build the crc tables atthe same time
std::mutex crc_creation_mutex;
typedef std::vector<uint32_t> CrcTable;
// Our crc/rev_crc tables
CrcTable crc_table;
CrcTable rev_crc_table;
bool crc_tables_created = false;
void build_crc_tables()
{
std::lock_guard<std::mutex> lock(crc_creation_mutex);
if (!crc_tables_created)
{
crc_table.resize(0x100);
rev_crc_table.resize(0x100);
for (auto i = 0; i < 0x100; ++i)
{
uint32_t crc = i;
for (auto j = 0; j < 8; ++j)
{
if (crc & 1)
{
crc = 0xEDB88320 ^ (crc >> 1);
}
else
{
crc = crc >> 1;
}
}
crc_table[i] = crc;
rev_crc_table[crc >> 24] = i + ((crc & 0xFFFFFF) << 8);
}
}
crc_tables_created = true;
}
const CrcTable& get_crc_table()
{
if (!crc_tables_created)
{
build_crc_tables();
}
return crc_table;
}
const CrcTable& get_rev_crc_table()
{
if (!crc_tables_created)
{
build_crc_tables();
}
return rev_crc_table;
}
}
namespace xiv
{
namespace utils
{
namespace crc32
{
uint32_t compute(const std::string& i_input, uint32_t init_crc)
{
// Classical crc stuff
auto& crc_table = internal::get_crc_table();
auto crc = init_crc;
for(std::size_t i = 0; i < i_input.size(); ++i)
{
crc = crc_table[(crc ^ i_input[i]) & 0xFF] ^ (crc >> 8);
}
return crc;
}
uint32_t rev_compute(const std::string& i_input, uint32_t init_crc)
{
auto& rev_crc_table = internal::get_rev_crc_table();
auto crc = init_crc;
const auto input_size = i_input.size();
// Reverse crc
for(auto i = input_size; i > 0; --i)
{
crc = rev_crc_table[crc >> 24] ^ ((crc << 8) & 0xFFFFFF00) ^ i_input[input_size - i - 1];
}
// Compute the 4 bytes needed for this init_crc
for (auto i = 0; i < 4; ++i)
{
crc = rev_crc_table[crc >> 24] ^ ((crc << 8) & 0xFFFFFF00);
}
return crc;
}
void generate_hashes_1(std::string& i_format, const uint32_t i_first_index, std::vector<uint32_t>& o_hashes)
{
char* str = const_cast<char*>(i_format.data());
const uint32_t str_size = i_format.size();
o_hashes.resize(10000);
uint32_t i = 0;
for (char a = '0'; a <= '9'; ++a)
{
str[i_first_index] = a;
for (char b = '0'; b <= '9'; ++b)
{
str[i_first_index + 1] = b;
for (char c = '0'; c <= '9'; ++c)
{
str[i_first_index + 2] = c;
for (char d = '0'; d <= '9'; ++d)
{
str[i_first_index + 3] = d;
o_hashes[i] = ::crc32(0, reinterpret_cast<uint8_t*>(&(str[0])), str_size) ^ 0xFFFFFFFF;
++i;
}
}
}
}
}
void generate_hashes_2(std::string& i_format, const uint32_t i_first_index, const uint32_t i_second_index, std::vector<uint32_t>& o_hashes)
{
char* str = const_cast<char*>(i_format.data());
const uint32_t str_size = i_format.size();
o_hashes.resize(100000000);
uint32_t i = 0;
for (char a = '0'; a <= '9'; ++a)
{
str[i_first_index] = a;
for (char b = '0'; b <= '9'; ++b)
{
str[i_first_index + 1] = b;
for (char c = '0'; c <= '9'; ++c)
{
str[i_first_index + 2] = c;
for (char d = '0'; d <= '9'; ++d)
{
str[i_first_index + 3] = d;
for (char e = '0'; e <= '9'; ++e)
{
str[i_second_index] = e;
for (char f = '0'; f <= '9'; ++f)
{
str[i_second_index + 1] = f;
for (char g = '0'; g <= '9'; ++g)
{
str[i_second_index + 2] = g;
for (char h = '0'; h <= '9'; ++h)
{
str[i_second_index + 3] = h;
o_hashes[i] = ::crc32(0, reinterpret_cast<uint8_t*>(&(str[0])), str_size) ^ 0xFFFFFFFF;
++i;
}
}
}
}
}
}
}
}
}
}
}
}

26
deps/datReader/crc32.h vendored Normal file
View file

@ -0,0 +1,26 @@
#ifndef XIV_UTILS_CRC32_H
#define XIV_UTILS_CRC32_H
#include <cstdint>
#include <vector>
#include <string>
namespace xiv {
namespace utils {
namespace crc32 {
// Normal crc32 computation from a given intial crc value, use zlib.crc32 instead, the final XOR 0xFFFFFFFF is not done
uint32_t compute( const std::string& i_input, uint32_t init_crc = 0xFFFFFFFF );
// Computes the 4 missing bytes XXXX such as init_crc = crc32(prefix_string)
// and string_to_find = prefix_string + XXXX + i_input
uint32_t rev_compute( const std::string& i_input, uint32_t init_crc = 0 );
void generate_hashes_1( std::string& i_format, const uint32_t i_first_index, std::vector< uint32_t >& o_hashes );
void generate_hashes_2( std::string& i_format, const uint32_t i_first_index, const uint32_t i_second_index, std::vector< uint32_t >& o_hashes );
}
}
}
#endif // XIV_UTILS_CRC32_H

16
deps/datReader/stream.cpp vendored Normal file
View file

@ -0,0 +1,16 @@
#include "stream.h"
#include <iostream>
#include <sstream>
#include <streambuf>
namespace xiv
{
namespace utils
{
namespace stream
{
}
}
}

27
deps/datReader/stream.h vendored Normal file
View file

@ -0,0 +1,27 @@
#ifndef XIV_UTILS_STREAM_H
#define XIV_UTILS_STREAM_H
#include <memory>
#include <iostream>
#include <vector>
namespace xiv
{
namespace utils
{
namespace stream
{
template<typename CharT, typename TraitsT = std::char_traits<CharT> >
class vectorwrapbuf : public std::basic_streambuf<CharT, TraitsT>
{
public:
vectorwrapbuf(std::vector<CharT> &vec)
{
this->setg(vec.data(), vec.data(), vec.data() + vec.size());
}
};
}
}
}
#endif // XIV_UTILS_STREAM_H

65
deps/datReader/zlib.cpp vendored Normal file
View file

@ -0,0 +1,65 @@
#include "zlib.h"
#include <string>
#include <stdexcept>
#include <zlib/zlib.h>
#include <vector>
namespace xiv
{
namespace utils
{
namespace zlib
{
void compress(const std::vector<char>& in, std::vector<char>& out)
{
// Fetching upper bound for out size
auto out_size = compressBound(in.size());
out.resize(out_size);
auto ret = compress2(reinterpret_cast<uint8_t*>(out.data()), &out_size,
reinterpret_cast<const uint8_t*>(in.data()), in.size(), Z_BEST_COMPRESSION);
if (ret != Z_OK)
{
throw std::runtime_error("Error at zlib uncompress: " + std::to_string(ret));
}
out.resize(out_size);
}
void no_header_decompress(uint8_t* in, uint32_t in_size, uint8_t* out, uint32_t out_size)
{
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = in_size;
strm.next_in = Z_NULL;
// Init with -15 because we do not have header in this compressed data
auto ret = inflateInit2(&strm, -15);
if (ret != Z_OK)
{
throw std::runtime_error("Error at zlib init: " + std::to_string(ret));
}
// Set pointers to the right addresses
strm.next_in = in;
strm.avail_out = out_size;
strm.next_out = out;
// Effectively decompress data
ret = inflate(&strm, Z_NO_FLUSH);
if (ret != Z_STREAM_END)
{
throw std::runtime_error("Error at zlib inflate: " + std::to_string(ret));
}
// Clean up
inflateEnd(&strm);
}
}
}
}

21
deps/datReader/zlib.h vendored Normal file
View file

@ -0,0 +1,21 @@
#ifndef XIV_UTILS_ZLIB_H
#define XIV_UTILS_ZLIB_H
#include <cstdint>
#include <vector>
namespace xiv
{
namespace utils
{
namespace zlib
{
void compress(const std::vector<char>& in, std::vector<char>& out);
void no_header_decompress(uint8_t* in, uint32_t in_size, uint8_t* out, uint32_t out_size);
}
}
}
#endif // XIV_UTILS_ZLIB_H

441
deps/inih/INIReader.h vendored Normal file
View file

@ -0,0 +1,441 @@
// Read an INI file into easy-to-access name/value pairs.
// inih and INIReader are released under the New BSD license (see LICENSE.txt).
// Go to the project home page for more info:
//
// https://github.com/benhoyt/inih
/* inih -- simple .INI file parser
inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:
https://github.com/benhoyt/inih
*/
#ifndef __INI_H__
#define __INI_H__
/* Make this header file easier to include in C++ code */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
/* Typedef for prototype of handler function. */
typedef int (*ini_handler)(void* user, const char* section,
const char* name, const char* value);
/* Typedef for prototype of fgets-style reader function. */
typedef char* (*ini_reader)(char* str, int num, void* stream);
/* Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section
is "" if name=value pair parsed before any section heading. name:value
pairs are also supported as a concession to Python's configparser.
For each name=value pair parsed, call handler function with given user
pointer as well as section, name, and value (data only valid for duration
of handler call). Handler should return nonzero on success, zero on error.
Returns 0 on success, line number of first error on parse error (doesn't
stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero).
*/
int ini_parse(const char* filename, ini_handler handler, void* user);
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
close the file when it's finished -- the caller must do that. */
int ini_parse_file(FILE* file, ini_handler handler, void* user);
/* Same as ini_parse(), but takes an ini_reader function pointer instead of
filename. Used for implementing custom or string-based I/O. */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
void* user);
/* Nonzero to allow multi-line value parsing, in the style of Python's
configparser. If allowed, ini_parse() will call the handler with the same
name for each subsequent line parsed. */
#ifndef INI_ALLOW_MULTILINE
#define INI_ALLOW_MULTILINE 1
#endif
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
the file. See http://code.google.com/p/inih/issues/detail?id=21 */
#ifndef INI_ALLOW_BOM
#define INI_ALLOW_BOM 1
#endif
/* Nonzero to allow inline comments (with valid inline comment characters
specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match
Python 3.2+ configparser behaviour. */
#ifndef INI_ALLOW_INLINE_COMMENTS
#define INI_ALLOW_INLINE_COMMENTS 1
#endif
#ifndef INI_INLINE_COMMENT_PREFIXES
#define INI_INLINE_COMMENT_PREFIXES ";"
#endif
/* Nonzero to use stack, zero to use heap (malloc/free). */
#ifndef INI_USE_STACK
#define INI_USE_STACK 1
#endif
/* Stop parsing on first error (default is to keep parsing). */
#ifndef INI_STOP_ON_FIRST_ERROR
#define INI_STOP_ON_FIRST_ERROR 0
#endif
/* Maximum line length for any line in INI file. */
#ifndef INI_MAX_LINE
#define INI_MAX_LINE 200
#endif
#ifdef __cplusplus
}
#endif
/* inih -- simple .INI file parser
inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:
https://github.com/benhoyt/inih
*/
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#if !INI_USE_STACK
#include <stdlib.h>
#endif
#define MAX_SECTION 50
#define MAX_NAME 50
/* Strip whitespace chars off end of given string, in place. Return s. */
inline static char* rstrip(char* s)
{
char* p = s + strlen(s);
while (p > s && isspace((unsigned char)(*--p)))
*p = '\0';
return s;
}
/* Return pointer to first non-whitespace char in given string. */
inline static char* lskip(const char* s)
{
while (*s && isspace((unsigned char)(*s)))
s++;
return (char*)s;
}
/* Return pointer to first char (of chars) or inline comment in given string,
or pointer to null at end of string if neither found. Inline comment must
be prefixed by a whitespace character to register as a comment. */
inline static char* find_chars_or_comment(const char* s, const char* chars)
{
#if INI_ALLOW_INLINE_COMMENTS
int was_space = 0;
while (*s && (!chars || !strchr(chars, *s)) &&
!(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
was_space = isspace((unsigned char)(*s));
s++;
}
#else
while (*s && (!chars || !strchr(chars, *s))) {
s++;
}
#endif
return (char*)s;
}
/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
inline static char* strncpy0(char* dest, const char* src, size_t size)
{
strncpy(dest, src, size);
dest[size - 1] = '\0';
return dest;
}
/* See documentation in header file. */
inline int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
void* user)
{
/* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
char line[INI_MAX_LINE];
#else
char* line;
#endif
char section[MAX_SECTION] = "";
char prev_name[MAX_NAME] = "";
char* start;
char* end;
char* name;
char* value;
int lineno = 0;
int error = 0;
#if !INI_USE_STACK
line = (char*)malloc(INI_MAX_LINE);
if (!line) {
return -2;
}
#endif
/* Scan through stream line by line */
while (reader(line, INI_MAX_LINE, stream) != NULL) {
lineno++;
start = line;
#if INI_ALLOW_BOM
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
(unsigned char)start[1] == 0xBB &&
(unsigned char)start[2] == 0xBF) {
start += 3;
}
#endif
start = lskip(rstrip(start));
if (*start == ';' || *start == '#') {
/* Per Python configparser, allow both ; and # comments at the
start of a line */
}
#if INI_ALLOW_MULTILINE
else if (*prev_name && *start && start > line) {
#if INI_ALLOW_INLINE_COMMENTS
end = find_chars_or_comment(start, NULL);
if (*end)
*end = '\0';
rstrip(start);
#endif
/* Non-blank line with leading whitespace, treat as continuation
of previous name's value (as per Python configparser). */
if (!handler(user, section, prev_name, start) && !error)
error = lineno;
}
#endif
else if (*start == '[') {
/* A "[section]" line */
end = find_chars_or_comment(start + 1, "]");
if (*end == ']') {
*end = '\0';
strncpy0(section, start + 1, sizeof(section));
*prev_name = '\0';
}
else if (!error) {
/* No ']' found on section line */
error = lineno;
}
}
else if (*start) {
/* Not a comment, must be a name[=:]value pair */
end = find_chars_or_comment(start, "=:");
if (*end == '=' || *end == ':') {
*end = '\0';
name = rstrip(start);
value = lskip(end + 1);
#if INI_ALLOW_INLINE_COMMENTS
end = find_chars_or_comment(value, NULL);
if (*end)
*end = '\0';
#endif
rstrip(value);
/* Valid name[=:]value pair found, call handler */
strncpy0(prev_name, name, sizeof(prev_name));
if (!handler(user, section, name, value) && !error)
error = lineno;
}
else if (!error) {
/* No '=' or ':' found on name[=:]value line */
error = lineno;
}
}
#if INI_STOP_ON_FIRST_ERROR
if (error)
break;
#endif
}
#if !INI_USE_STACK
free(line);
#endif
return error;
}
/* See documentation in header file. */
inline int ini_parse_file(FILE* file, ini_handler handler, void* user)
{
return ini_parse_stream((ini_reader)fgets, file, handler, user);
}
/* See documentation in header file. */
inline int ini_parse(const char* filename, ini_handler handler, void* user)
{
FILE* file;
int error;
file = fopen(filename, "r");
if (!file)
return -1;
error = ini_parse_file(file, handler, user);
fclose(file);
return error;
}
#endif /* __INI_H__ */
#ifndef __INIREADER_H__
#define __INIREADER_H__
#include <map>
#include <set>
#include <string>
// Read an INI file into easy-to-access name/value pairs. (Note that I've gone
// for simplicity here rather than speed, but it should be pretty decent.)
class INIReader
{
public:
// Empty Constructor
INIReader() {};
// Construct INIReader and parse given filename. See ini.h for more info
// about the parsing.
INIReader(std::string filename);
// Return the result of ini_parse(), i.e., 0 on success, line number of
// first error on parse error, or -1 on file open error.
int ParseError() const;
// Return the list of sections found in ini file
const std::set<std::string>& Sections() const;
// Get a string value from INI file, returning default_value if not found.
std::string Get(std::string section, std::string name,
std::string default_value) const;
// Get an integer (long) value from INI file, returning default_value if
// not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2").
long GetInteger(std::string section, std::string name, long default_value) const;
// Get a real (floating point double) value from INI file, returning
// default_value if not found or not a valid floating point value
// according to strtod().
double GetReal(std::string section, std::string name, double default_value) const;
// Get a boolean value from INI file, returning default_value if not found or if
// not a valid true/false value. Valid true values are "true", "yes", "on", "1",
// and valid false values are "false", "no", "off", "0" (not case sensitive).
bool GetBoolean(std::string section, std::string name, bool default_value) const;
protected:
int _error;
std::map<std::string, std::string> _values;
std::set<std::string> _sections;
static std::string MakeKey(std::string section, std::string name);
static int ValueHandler(void* user, const char* section, const char* name,
const char* value);
};
#endif // __INIREADER_H__
#ifndef __INIREADER__
#define __INIREADER__
#include <algorithm>
#include <cctype>
#include <cstdlib>
using std::string;
inline INIReader::INIReader(string filename)
{
_error = ini_parse(filename.c_str(), ValueHandler, this);
}
inline int INIReader::ParseError() const
{
return _error;
}
inline const std::set<string>& INIReader::Sections() const
{
return _sections;
}
inline string INIReader::Get(string section, string name, string default_value) const
{
string key = MakeKey(section, name);
return _values.count(key) ? _values.at(key) : default_value;
}
inline long INIReader::GetInteger(string section, string name, long default_value) const
{
string valstr = Get(section, name, "");
const char* value = valstr.c_str();
char* end;
// This parses "1234" (decimal) and also "0x4D2" (hex)
long n = strtol(value, &end, 0);
return end > value ? n : default_value;
}
inline double INIReader::GetReal(string section, string name, double default_value) const
{
string valstr = Get(section, name, "");
const char* value = valstr.c_str();
char* end;
double n = strtod(value, &end);
return end > value ? n : default_value;
}
inline bool INIReader::GetBoolean(string section, string name, bool default_value) const
{
string valstr = Get(section, name, "");
// Convert to lower case to make string comparisons case-insensitive
std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower);
if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1")
return true;
else if (valstr == "false" || valstr == "no" || valstr == "off" || valstr == "0")
return false;
else
return default_value;
}
inline string INIReader::MakeKey(string section, string name)
{
string key = section + "=" + name;
// Convert to lower case to make section/name lookups case-insensitive
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
return key;
}
inline int INIReader::ValueHandler(void* user, const char* section, const char* name,
const char* value)
{
INIReader* reader = (INIReader*)user;
string key = MakeKey(section, name);
if (reader->_values[key].size() > 0)
reader->_values[key] += "\n";
reader->_values[key] += value;
reader->_sections.insert(section);
return 1;
}
#endif // __INIREADER__

27
deps/inih/LICENSE.txt vendored Normal file
View file

@ -0,0 +1,27 @@
The "inih" library is distributed under the New BSD license:
Copyright (c) 2009, Ben Hoyt
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Ben Hoyt nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY BEN HOYT ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL BEN HOYT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

41
deps/inih/README.md vendored Normal file
View file

@ -0,0 +1,41 @@
# inih
[![Build Status](https://travis-ci.org/jtilly/inih.svg?branch=master)](https://travis-ci.org/jtilly/inih)
This is a header only C++ version of [inih](https://github.com/benhoyt/inih).
**inih (INI Not Invented Here)** is a simple [.INI file](http://en.wikipedia.org/wiki/INI_file) parser written in C. It's only a couple of pages of code, and it was designed to be _small and simple_, so it's good for embedded systems. It's also more or less compatible with Python's [ConfigParser](http://docs.python.org/library/configparser.html) style of .INI files, including RFC 822-style multi-line syntax and `name: value` entries.
## Usage
All you need to do is to include `INIReader.h`. Consider the following example (`INIReaderTest.cpp`):
```cpp
#include <iostream>
#include "INIReader.h"
int main() {
INIReader reader("test.ini");
if (reader.ParseError() < 0) {
std::cout << "Can't load 'test.ini'\n";
return 1;
}
std::cout << "Config loaded from 'test.ini': version="
<< reader.GetInteger("protocol", "version", -1) << ", name="
<< reader.Get("user", "name", "UNKNOWN") << ", email="
<< reader.Get("user", "email", "UNKNOWN") << ", pi="
<< reader.GetReal("user", "pi", -1) << ", active="
<< reader.GetBoolean("user", "active", true) << "\n";
return 0;
}
```
To compile and run:
```sh
g++ INIReaderTest.cpp -o INIReaderTest.out
./INIReaderTest.out
# Config loaded from 'test.ini': version=6, name=Bob Smith, email=bob@smith.com, pi=3.14159, active=1
```

12
deps/inih/test.ini vendored Normal file
View file

@ -0,0 +1,12 @@
; Test config file for ini_example.c and INIReaderTest.cpp
[protocol] ; Protocol configuration
version=6 ; IPv6
[user]
name = Bob Smith ; Spaces around '=' are stripped
email = bob@smith.com ; And comments (like this) ignored
active = true ; Test a boolean
pi = 3.14159 ; Test a floating point number
multi = this is a ; test
multi-line value ; test

26
deps/mysqlConnector/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.2.0)
project(Sapphire)
file( GLOB UTILS_PUBLIC_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*" )
file( GLOB UTILS_SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*" )
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
add_library( mysqlConnector ${UTILS_PUBLIC_INCLUDE_FILES} ${UTILS_SOURCE_FILES} )
set_target_properties( mysqlConnector PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS ON
)
target_include_directories( mysqlConnector PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} )
if(UNIX)
target_include_directories( mysqlConnector PUBLIC "/usr/include/mysql/" )
else()
target_include_directories( mysqlConnector PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../MySQL/" )
endif()
target_link_libraries( mysqlConnector PUBLIC mysql )
#cotire(mysqlConnector)

254
deps/mysqlConnector/Connection.cpp vendored Normal file
View file

@ -0,0 +1,254 @@
#include "Connection.h"
#include "MySqlBase.h"
#include "Statement.h"
#include "PreparedStatement.h"
#include <mysql.h>
#include <vector>
Mysql::Connection::Connection( std::shared_ptr< MySqlBase > pBase,
const std::string& hostName,
const std::string& userName,
const std::string& password,
uint16_t port ) :
m_pBase( pBase ),
m_bConnected( false )
{
m_pRawCon = mysql_init( nullptr );
if( mysql_real_connect( m_pRawCon, hostName.c_str(), userName.c_str(), password.c_str(),
nullptr, port, nullptr, 0) == nullptr )
throw std::runtime_error( mysql_error( m_pRawCon ) );
m_bConnected = true;
}
Mysql::Connection::Connection( std::shared_ptr< MySqlBase > pBase,
const std::string& hostName,
const std::string& userName,
const std::string& password,
const optionMap& options,
uint16_t port ) :
m_pBase( pBase )
{
m_pRawCon = mysql_init( nullptr );
// Different mysql versions support different options, for now whatever was unsupporter here was commented out
// but left there.
for( auto entry : options )
{
switch( entry.first )
{
// integer based options
case MYSQL_OPT_CONNECT_TIMEOUT:
case MYSQL_OPT_PROTOCOL:
case MYSQL_OPT_READ_TIMEOUT:
// case MYSQL_OPT_SSL_MODE:
// case MYSQL_OPT_RETRY_COUNT:
case MYSQL_OPT_WRITE_TIMEOUT:
// case MYSQL_OPT_MAX_ALLOWED_PACKET:
// case MYSQL_OPT_NET_BUFFER_LENGTH:
{
uint32_t optVal = std::stoi( entry.second, nullptr, 10 );
setOption( entry.first, optVal );
}
break;
// bool based options
// case MYSQL_ENABLE_CLEARTEXT_PLUGIN:
// case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
case MYSQL_OPT_COMPRESS:
case MYSQL_OPT_GUESS_CONNECTION:
case MYSQL_OPT_LOCAL_INFILE:
case MYSQL_OPT_RECONNECT:
// case MYSQL_OPT_SSL_ENFORCE:
// case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
case MYSQL_OPT_USE_REMOTE_CONNECTION:
case MYSQL_REPORT_DATA_TRUNCATION:
case MYSQL_SECURE_AUTH:
{
my_bool optVal = entry.second == "0" ? 0 : 1;
setOption( entry.first, &optVal );
}
break;
// string based options
// case MYSQL_DEFAULT_AUTH:
// case MYSQL_OPT_BIND:
// case MYSQL_OPT_SSL_CA:
// case MYSQL_OPT_SSL_CAPATH:
// case MYSQL_OPT_SSL_CERT:
// case MYSQL_OPT_SSL_CIPHER:
// case MYSQL_OPT_SSL_CRL:
// case MYSQL_OPT_SSL_CRLPATH:
// case MYSQL_OPT_SSL_KEY:
// case MYSQL_OPT_TLS_VERSION:
// case MYSQL_PLUGIN_DIR:
case MYSQL_READ_DEFAULT_FILE:
case MYSQL_READ_DEFAULT_GROUP:
// case MYSQL_SERVER_PUBLIC_KEY:
case MYSQL_SET_CHARSET_DIR:
case MYSQL_SET_CHARSET_NAME:
case MYSQL_SET_CLIENT_IP:
case MYSQL_SHARED_MEMORY_BASE_NAME:
{
setOption( entry.first, entry.second.c_str() );
}
break;
default:
throw std::runtime_error( "Unknown option: " + std::to_string( entry.first ) );
}
}
if( mysql_real_connect( m_pRawCon, hostName.c_str(), userName.c_str(), password.c_str(),
nullptr, port, nullptr, 0) == nullptr )
throw std::runtime_error( mysql_error( m_pRawCon ) );
}
Mysql::Connection::~Connection()
{
}
void Mysql::Connection::setOption( enum mysqlOption option, const void *arg )
{
if( mysql_options( m_pRawCon, static_cast< mysql_option>( option ), arg ) != 0 )
throw std::runtime_error( "Connection::setOption failed!" );
}
void Mysql::Connection::setOption( enum mysqlOption option, uint32_t arg )
{
if( mysql_options( m_pRawCon, static_cast< mysql_option>( option ), &arg ) != 0 )
throw std::runtime_error( "Connection::setOption failed!" );
}
void Mysql::Connection::setOption( enum mysqlOption option, const std::string& arg )
{
if( mysql_options( m_pRawCon, static_cast< mysql_option>( option ), arg.c_str() ) != 0 )
throw std::runtime_error( "Connection::setOption failed!" );
}
void Mysql::Connection::close()
{
mysql_close( m_pRawCon );
m_bConnected = false;
}
bool Mysql::Connection::isClosed() const
{
return !m_bConnected;
}
std::shared_ptr< Mysql::MySqlBase > Mysql::Connection::getMySqlBase() const
{
return m_pBase;
}
void Mysql::Connection::setAutoCommit( bool autoCommit )
{
auto b = static_cast< my_bool >( autoCommit == true ? 1 : 0 );
if( mysql_autocommit( m_pRawCon, b ) != 0 )
throw std::runtime_error( "Connection::setAutoCommit failed!" );
}
bool Mysql::Connection::getAutoCommit()
{
// TODO: should be replaced with wrapped sql query function once available
std::string query("SELECT @@autocommit");
auto res = mysql_real_query( m_pRawCon, query.c_str(), query.length() );
if( res != 0 )
throw std::runtime_error( "Query failed!" );
auto pRes = mysql_store_result( m_pRawCon );
auto row = mysql_fetch_row( pRes );
uint32_t ac = atoi( row[0] );
return ac != 0;
}
void Mysql::Connection::beginTransaction()
{
auto stmt = createStatement();
stmt->execute( "START TRANSACTION;" );
}
void Mysql::Connection::commitTransaction()
{
auto stmt = createStatement();
stmt->execute( "COMMIT" );
}
void Mysql::Connection::rollbackTransaction()
{
auto stmt = createStatement();
stmt->execute( "ROLLBACK" );
}
std::string Mysql::Connection::escapeString( const std::string &inData )
{
std::unique_ptr< char[] > buffer( new char[inData.length() * 2 + 1] );
if( !buffer.get() )
return "";
unsigned long return_len = mysql_real_escape_string( m_pRawCon, buffer.get(),
inData.c_str(), static_cast< unsigned long > ( inData.length() ) );
return std::string( buffer.get(), return_len );
}
void Mysql::Connection::setSchema( const std::string &schema )
{
if( mysql_select_db( m_pRawCon, schema.c_str() ) != 0 )
throw std::runtime_error( "Current database could not be changed to " + schema );
}
std::shared_ptr< Mysql::Statement > Mysql::Connection::createStatement()
{
return std::make_shared< Mysql::Statement >( shared_from_this() );
}
MYSQL* Mysql::Connection::getRawCon()
{
return m_pRawCon;
}
std::string Mysql::Connection::getError()
{
auto mysqlError = mysql_error( m_pRawCon );
if( mysqlError )
return std::string( mysqlError );
return "";
}
std::shared_ptr< Mysql::PreparedStatement > Mysql::Connection::prepareStatement( const std::string &sql )
{
MYSQL_STMT* stmt = mysql_stmt_init( getRawCon() );
if( !stmt )
throw std::runtime_error( "Could not init prepared statement: " + getError() );
if( mysql_stmt_prepare( stmt, sql.c_str(), sql.size() ) )
throw std::runtime_error( "Could not prepare statement: " + getError() );
return std::make_shared< PreparedStatement >( stmt, shared_from_this() );
}
uint32_t Mysql::Connection::getErrorNo()
{
return mysql_errno( m_pRawCon );
}
bool Mysql::Connection::ping()
{
return mysql_ping( m_pRawCon ) != 0;
}

89
deps/mysqlConnector/Connection.h vendored Normal file
View file

@ -0,0 +1,89 @@
#ifndef SAPPHIRE_CONNECTION_H
#define SAPPHIRE_CONNECTION_H
#include <memory>
#include <map>
#include "MysqlCommon.h"
typedef struct st_mysql MYSQL;
namespace Mysql
{
using optionMap = std::map< enum mysqlOption, std::string >;
class MySqlBase;
class Statement;
class PreparedStatement;
class Connection : public std::enable_shared_from_this< Connection >
{
public:
Connection( std::shared_ptr< MySqlBase > pBase,
const std::string& hostName,
const std::string& userName,
const std::string& password,
uint16_t port = 3306);
Connection( std::shared_ptr< MySqlBase > pBase,
const std::string& hostName,
const std::string& userName,
const std::string& password,
const optionMap& options,
uint16_t port = 3306 );
virtual ~Connection();
void close();
bool isClosed() const;
bool ping();
void setOption( enum mysqlOption option, const void* arg );
void setOption( enum mysqlOption option, uint32_t arg );
void setOption( enum mysqlOption option, const std::string& arg );
std::shared_ptr< MySqlBase > getMySqlBase() const;
void setAutoCommit( bool autoCommit );
bool getAutoCommit();
std::string escapeString( const std::string& inData );
void setSchema( const std::string& catalog );
std::shared_ptr< Statement > createStatement();
void beginTransaction();
void commitTransaction();
void rollbackTransaction();
std::string getSchema();
std::string getError();
uint32_t getErrorNo();
bool isReadOnly();
void setReadOnly( bool readOnly );
bool isValid();
bool reconnect();
std::shared_ptr< Mysql::PreparedStatement > prepareStatement( const std::string& sql );
std::string getLastStatementInfo();
MYSQL* getRawCon();
private:
std::shared_ptr< MySqlBase > m_pBase;
MYSQL* m_pRawCon;
bool m_bConnected;
Connection( const Connection& );
void operator=( Connection& );
};
}
#endif //SAPPHIRE_CONNECTION_H

41
deps/mysqlConnector/DataType.h vendored Normal file
View file

@ -0,0 +1,41 @@
#ifndef SAPPHIRE_DATATYPE_H
#define SAPPHIRE_DATATYPE_H
namespace Mysql
{
class DataType
{
DataType();
public:
enum
{
UNKNOWN = 0,
BIT,
TINYINT,
SMALLINT,
MEDIUMINT,
INTEGER,
BIGINT,
REAL,
DOUBLE,
DECIMAL,
NUMERIC,
CHAR,
BINARY,
VARCHAR,
VARBINARY,
LONGVARCHAR,
LONGVARBINARY,
TIMESTAMP,
DATE,
TIME,
YEAR,
GEOMETRY,
ENUM,
SET,
SQLNULL,
JSON
};
};
}
#endif //SAPPHIRE_DATATYPE_H

31
deps/mysqlConnector/MySqlBase.cpp vendored Normal file
View file

@ -0,0 +1,31 @@
#include "MySqlBase.h"
#include "Connection.h"
#include <memory>
#include <mysql.h>
Mysql::MySqlBase::MySqlBase()
{
}
Mysql::MySqlBase::~MySqlBase()
{
}
std::string Mysql::MySqlBase::getVersionInfo()
{
return std::string( mysql_get_client_info() );
}
std::shared_ptr< Mysql::Connection > Mysql::MySqlBase::connect( const std::string& hostName, const std::string& userName,
const std::string& password, uint16_t port = 3306 )
{
return std::make_shared< Mysql::Connection >( shared_from_this(), hostName, userName, password, port );
}
std::shared_ptr< Mysql::Connection > Mysql::MySqlBase::connect( const std::string& hostName, const std::string& userName,
const std::string& password, const optionMap& options,
uint16_t port = 3306 )
{
return std::shared_ptr< Mysql::Connection >( new Mysql::Connection( shared_from_this(), hostName, userName, password, options, port ) );
}

38
deps/mysqlConnector/MySqlBase.h vendored Normal file
View file

@ -0,0 +1,38 @@
#ifndef SAPPHIRE_MYSQLBASE_H
#define SAPPHIRE_MYSQLBASE_H
#include <memory>
#include <string>
#include <map>
#include "MysqlCommon.h"
namespace Mysql
{
using optionMap = std::map< enum mysqlOption, std::string >;
class Connection;
class MySqlBase : public std::enable_shared_from_this< MySqlBase >
{
public:
MySqlBase();
~MySqlBase();
std::shared_ptr< Connection > connect( const std::string& hostName, const std::string& userName,
const std::string& password, uint16_t port );
std::shared_ptr< Connection > connect( const std::string& hostName, const std::string& userName,
const std::string& password, const optionMap& map, uint16_t port );
std::string getVersionInfo();
private:
MySqlBase( const MySqlBase& );
void operator=( MySqlBase& );
};
}
#endif //SAPPHIRE_MYSQLBASE_H

12
deps/mysqlConnector/MySqlConnector.h vendored Normal file
View file

@ -0,0 +1,12 @@
#include "MySqlBase.h"
#include "Connection.h"
#include "Statement.h"
#include "PreparedStatement.h"
#include "ResultSet.h"
#include "PreparedResultSet.h"
#include <memory>
namespace Mysql
{
using PreparedResultSetScopedPtr = std::unique_ptr< Mysql::PreparedResultSet >;
}

33
deps/mysqlConnector/MysqlCommon.h vendored Normal file
View file

@ -0,0 +1,33 @@
#ifndef MYSQL_COMMON_H
#define MYSQL_COMMON_H
namespace Mysql {
enum mysqlOption
{
MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE,
MYSQL_INIT_COMMAND, MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,
MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, MYSQL_OPT_LOCAL_INFILE,
MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT,
MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT,
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH,
MYSQL_OPT_BIND,
MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CERT,
MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CAPATH, MYSQL_OPT_SSL_CIPHER,
MYSQL_OPT_SSL_CRL, MYSQL_OPT_SSL_CRLPATH,
MYSQL_OPT_CONNECT_ATTR_RESET, MYSQL_OPT_CONNECT_ATTR_ADD,
MYSQL_OPT_CONNECT_ATTR_DELETE,
MYSQL_SERVER_PUBLIC_KEY,
MYSQL_ENABLE_CLEARTEXT_PLUGIN,
MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
MYSQL_OPT_SSL_ENFORCE,
MYSQL_OPT_MAX_ALLOWED_PACKET, MYSQL_OPT_NET_BUFFER_LENGTH,
MYSQL_OPT_TLS_VERSION,
MYSQL_OPT_SSL_MODE
};
}
#endif

View file

@ -0,0 +1,706 @@
#include "PreparedResultSet.h"
#include "ResultBind.h"
#include "DataType.h"
#include <string>
#include <cctype>
#include <clocale>
#include <string.h>
#include <mysql.h>
#include <algorithm>
namespace
{
static inline char * my_l_to_a(char * buf, size_t buf_size, int64_t a)
{
snprintf(buf, buf_size, "%lld", (long long) a);
return buf;
}
static inline char * my_ul_to_a(char * buf, size_t buf_size, uint64_t a)
{
snprintf(buf, buf_size, "%llu", (unsigned long long) a);
return buf;
}
static inline char * my_f_to_a(char * buf, size_t buf_size, double a)
{
snprintf(buf, buf_size, "%f", a);
return buf;
}
}
uint32_t Mysql::PreparedResultSet::findColumn( const std::string &columnLabel ) const
{
std::string searchColumn = columnLabel;
std::transform( searchColumn.begin(), searchColumn.end(), searchColumn.begin(),
[](unsigned char c){ return std::toupper( c ); } );
auto iter = m_fieldNameToIndex.find( searchColumn );
if( iter == m_fieldNameToIndex.end() )
return 0;
return iter->second + 1;
}
Mysql::PreparedResultSet::PreparedResultSet( std::shared_ptr< ResultBind >& pBind,
std::shared_ptr< Mysql::PreparedStatement > par ) :
ResultSet( nullptr, par ),
m_pResultBind( pBind ),
m_pStmt( par )
{
pBind->bindResult();
m_numRows = mysql_stmt_num_rows( par->getRawStmt() );
m_numFields = mysql_stmt_field_count( par->getRawStmt() );
auto resMeta = mysql_stmt_result_metadata( m_pStmt->getRawStmt() );
for( uint32_t i = 0; i < m_numFields; ++i )
{
auto field = resMeta->fields[i];
std::string fieldName( field.name );
std::transform( fieldName.begin(), fieldName.end(), fieldName.begin(),
[]( unsigned char c ){ return std::toupper(c); } );
m_fieldNameToIndex[fieldName] = i;
}
}
bool Mysql::PreparedResultSet::isBeforeFirstOrAfterLast() const
{
return ( m_rowPosition == 0 );
}
Mysql::PreparedResultSet::~PreparedResultSet()
{
free();
}
uint32_t Mysql::PreparedResultSet::getUInt( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getUInt: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getUInt: invalid value of 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if (*m_pResultBind->m_pBind[columnIndex - 1].is_null) {
return 0;
}
return static_cast< uint32_t >( getUInt64_intern( columnIndex, true ) );
}
uint16_t Mysql::PreparedResultSet::getUInt16( const uint32_t columnIndex ) const
{
return static_cast< uint16_t >( getUInt( columnIndex) );
}
uint16_t Mysql::PreparedResultSet::getUInt16( const std::string& columnLabel ) const
{
return static_cast< uint16_t >( getUInt( columnLabel) );
}
uint8_t Mysql::PreparedResultSet::getUInt8( const uint32_t columnIndex ) const
{
return static_cast< uint8_t >( getUInt( columnIndex) );
}
uint8_t Mysql::PreparedResultSet::getUInt8( const std::string& columnLabel ) const
{
return static_cast< uint8_t >( getUInt( columnLabel) );
}
int16_t Mysql::PreparedResultSet::getInt16( const uint32_t columnIndex ) const
{
return static_cast< int16_t >( getInt( columnIndex) );
}
int16_t Mysql::PreparedResultSet::getInt16( const std::string& columnLabel ) const
{
return static_cast< int16_t >( getInt( columnLabel) );
}
int8_t Mysql::PreparedResultSet::getInt8( const uint32_t columnIndex ) const
{
return static_cast< int8_t >( getInt( columnIndex) );
}
int8_t Mysql::PreparedResultSet::getInt8( const std::string& columnLabel ) const
{
return static_cast< int8_t >( getInt( columnLabel) );
}
uint32_t Mysql::PreparedResultSet::getUInt( const std::string& columnLabel ) const
{
return getUInt( findColumn( columnLabel ) );
}
int64_t Mysql::PreparedResultSet::getInt64( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getInt64: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getInt64: invalid value of 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( *m_pResultBind->m_pBind[columnIndex - 1].is_null )
return 0;
return getInt64_intern( columnIndex, true );
}
int64_t Mysql::PreparedResultSet::getInt64( const std::string& columnLabel ) const
{
return getInt64( findColumn( columnLabel ) );
}
uint64_t Mysql::PreparedResultSet::getUInt64_intern( const uint32_t columnIndex, bool ) const
{
MYSQL_RES* res = mysql_stmt_result_metadata( m_pStmt->getRawStmt() );
MYSQL_FIELD* field = mysql_fetch_field_direct( res, columnIndex - 1 );
switch( Mysql::Util::mysql_type_to_datatype( field ) )
{
case DataType::REAL:
case DataType::DOUBLE:
return static_cast< uint64_t >( getDouble( columnIndex ) );
case DataType::NUMERIC:
case DataType::DECIMAL:
case DataType::TIMESTAMP:
case DataType::DATE:
case DataType::TIME:
case DataType::CHAR:
case DataType::BINARY:
case DataType::VARCHAR:
case DataType::VARBINARY:
case DataType::LONGVARCHAR:
case DataType::LONGVARBINARY:
case DataType::SET:
case DataType::ENUM:
case DataType::JSON:
return Mysql::Util::strtoull( getString( columnIndex ).c_str(), nullptr );
case DataType::BIT:
{
uint64_t uval = 0;
/* This length is in bytes, on the contrary to what can be seen in mysql_resultset.cpp where the Meta is used */
switch( *m_pResultBind->m_pBind[columnIndex - 1].length )
{
case 8:uval = (uint64_t) bit_uint8korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 7:uval = (uint64_t) bit_uint7korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 6:uval = (uint64_t) bit_uint6korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 5:uval = (uint64_t) bit_uint5korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 4:uval = (uint64_t) bit_uint4korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 3:uval = (uint64_t) bit_uint3korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 2:uval = (uint64_t) bit_uint2korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 1:uval = (uint64_t) bit_uint1korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
}
return uval;
}
case DataType::YEAR:
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::MEDIUMINT:
case DataType::INTEGER:
case DataType::BIGINT:
{
uint64_t ret;
bool is_it_null = *m_pResultBind->m_pBind[columnIndex - 1].is_null != 0;
bool is_it_unsigned = m_pResultBind->m_pBind[columnIndex - 1].is_unsigned != 0;
switch( m_pResultBind->m_pBind[columnIndex - 1].buffer_length )
{
case 1:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint8_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int8_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
case 2:
if(is_it_unsigned)
ret = !is_it_null ? *reinterpret_cast< uint16_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int16_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
case 4:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint32_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int32_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
case 8:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint64_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int64_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
default:
throw std::runtime_error( "PreparedResultSet::getInt64_intern: invalid type" );
}
return ret;
}
default:
break;
}
throw std::runtime_error( "PreparedResultSet::getUInt64_intern: unhandled type. Please, report" );
return 0;
}
int64_t Mysql::PreparedResultSet::getInt64_intern( const uint32_t columnIndex, bool ) const
{
MYSQL_RES* res = mysql_stmt_result_metadata( m_pStmt->getRawStmt() );
MYSQL_FIELD* field = mysql_fetch_field_direct( res, columnIndex - 1 );
switch( Mysql::Util::mysql_type_to_datatype( field ) )
{
case DataType::REAL:
case DataType::DOUBLE:
return static_cast< int64_t >( getDouble( columnIndex ) );
case DataType::NUMERIC:
case DataType::DECIMAL:
case DataType::TIMESTAMP:
case DataType::DATE:
case DataType::TIME:
case DataType::CHAR:
case DataType::BINARY:
case DataType::VARCHAR:
case DataType::VARBINARY:
case DataType::LONGVARCHAR:
case DataType::LONGVARBINARY:
case DataType::SET:
case DataType::ENUM:
case DataType::JSON:
return Mysql::Util::strtoll( getString( columnIndex ).c_str(), nullptr );
case DataType::BIT:
{
int64_t uval = 0;
switch( *m_pResultBind->m_pBind[columnIndex - 1].length )
{
case 8:uval = ( int64_t ) bit_uint8korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 7:uval = ( int64_t ) bit_uint7korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 6:uval = ( int64_t ) bit_uint6korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 5:uval = ( int64_t ) bit_uint5korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 4:uval = ( int64_t ) bit_uint4korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 3:uval = ( int64_t ) bit_uint3korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 2:uval = ( int64_t ) bit_uint2korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
case 1:uval = ( int64_t ) bit_uint1korr( m_pResultBind->m_pBind[columnIndex - 1].buffer );break;
}
return uval;
}
case DataType::YEAR:
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::MEDIUMINT:
case DataType::INTEGER:
case DataType::BIGINT:
{
int64_t ret;
bool is_it_null = *m_pResultBind->m_pBind[columnIndex - 1].is_null != 0;
bool is_it_unsigned = m_pResultBind->m_pBind[columnIndex - 1].is_unsigned != 0;
switch( m_pResultBind->m_pBind[columnIndex - 1].buffer_length )
{
case 1:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint8_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int8_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
case 2:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint16_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int16_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
case 4:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint32_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int32_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer) : 0;
break;
case 8:
if( is_it_unsigned )
ret = !is_it_null ? *reinterpret_cast< uint64_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
else
ret = !is_it_null ? *reinterpret_cast< int64_t* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0;
break;
default:
throw std::runtime_error( "PreparedResultSet::getInt64_intern: invalid type" );
}
return ret;
}
default:
break;
}
throw std::runtime_error( "PreparedResultSet::getInt64_intern: unhandled type. Please, report" );
return 0;
}
uint64_t Mysql::PreparedResultSet::getUInt64( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getUInt64: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getUInt64: invalid value of 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( *m_pResultBind->m_pBind[columnIndex - 1].is_null )
return 0;
return getUInt64_intern( columnIndex, true );
}
uint64_t Mysql::PreparedResultSet::getUInt64( const std::string& columnLabel ) const
{
return getUInt64( findColumn( columnLabel ) );
}
std::string Mysql::PreparedResultSet::getString( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getString: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getString: invalid 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( *m_pResultBind->m_pBind[columnIndex - 1].is_null )
return std::string("");
MYSQL_RES* res = mysql_stmt_result_metadata( m_pStmt->getRawStmt() );
MYSQL_FIELD* field = mysql_fetch_field_direct( res, columnIndex - 1 );
switch( Mysql::Util::mysql_type_to_datatype( field ) )
{
case DataType::TIMESTAMP:
{
char buf[28];
MYSQL_TIME * t = static_cast< MYSQL_TIME* >( m_pResultBind->m_pBind[columnIndex - 1].buffer );
if( t->second_part )
snprintf( buf, sizeof(buf) - 1, "%04d-%02d-%02d %02d:%02d:%02d.%06lu",
t->year, t->month, t->day, t->hour, t->minute, t->second, t->second_part );
else
snprintf( buf, sizeof(buf) - 1, "%04d-%02d-%02d %02d:%02d:%02d",
t->year, t->month, t->day, t->hour, t->minute, t->second );
return std::string( buf );
}
case DataType::DATE:
{
char buf[12];
MYSQL_TIME* t = static_cast< MYSQL_TIME* >( m_pResultBind->m_pBind[columnIndex - 1].buffer );
snprintf( buf, sizeof( buf ) - 1, "%02d-%02d-%02d", t->year, t->month, t->day );
return std::string( buf );
}
case DataType::TIME:
{
char buf[18];
MYSQL_TIME* t = static_cast< MYSQL_TIME* >( m_pResultBind->m_pBind[columnIndex - 1].buffer );
if( t->second_part )
snprintf( buf, sizeof( buf ), "%s%02d:%02d:%02d.%06lu", t->neg ? "-" : "", t->hour, t->minute, t->second, t->second_part );
else
snprintf( buf, sizeof( buf ), "%s%02d:%02d:%02d", t->neg ? "-" : "", t->hour, t->minute, t->second );
return std::string( buf );
}
case DataType::BIT:
case DataType::YEAR: // fetched as a SMALLINT
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::MEDIUMINT:
case DataType::INTEGER:
case DataType::BIGINT:
{
char buf[30];
if( m_pResultBind->m_pBind[columnIndex - 1].is_unsigned )
my_ul_to_a( buf, sizeof( buf ) - 1, getUInt64_intern( columnIndex, false ) );
else
my_l_to_a( buf, sizeof( buf ) - 1, getInt64_intern( columnIndex, false ) );
return std::string( buf );
}
case DataType::REAL:
case DataType::DOUBLE:
{
char buf[50];
my_f_to_a( buf, sizeof( buf ) - 1, getDouble( columnIndex ) );
return std::string( buf );
}
case DataType::NUMERIC:
case DataType::DECIMAL:
case DataType::CHAR:
case DataType::BINARY:
case DataType::VARCHAR:
case DataType::VARBINARY:
case DataType::LONGVARCHAR:
case DataType::LONGVARBINARY:
case DataType::SET:
case DataType::ENUM:
case DataType::JSON:
return std::string( static_cast< char* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ),
*m_pResultBind->m_pBind[columnIndex - 1].length );
default:
break;
}
throw std::runtime_error( " PreparedResultSet::getString: unhandled type. Please, report" );
return 0;
}
std::string Mysql::PreparedResultSet::getString( const std::string& columnLabel) const
{
return getString( findColumn( columnLabel ) );
}
int32_t Mysql::PreparedResultSet::getInt( uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getInt: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getInt: invalid value of 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( *m_pResultBind->m_pBind[columnIndex - 1].is_null )
return 0;
return static_cast< int32_t >( getInt64_intern( columnIndex, true ) );
}
int32_t Mysql::PreparedResultSet::getInt( const std::string& columnLabel ) const
{
return getInt( findColumn( columnLabel ) );
}
long double Mysql::PreparedResultSet::getDouble(const uint32_t columnIndex) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getDouble: can't fetch because not on result set" );
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getDouble: invalid 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( *m_pResultBind->m_pBind[columnIndex - 1].is_null)
return 0.0;
MYSQL_RES* res = mysql_stmt_result_metadata( m_pStmt->getRawStmt() );
MYSQL_FIELD* field = mysql_fetch_field_direct( res, columnIndex - 1);
switch( Mysql::Util::mysql_type_to_datatype( field ) )
{
case DataType::BIT:
case DataType::YEAR:
case DataType::TINYINT:
case DataType::SMALLINT:
case DataType::MEDIUMINT:
case DataType::INTEGER:
case DataType::BIGINT:
{
long double ret;
bool is_it_unsigned = m_pResultBind->m_pBind[columnIndex - 1].is_unsigned != 0;
if( is_it_unsigned )
{
uint64_t ival = getUInt64_intern( columnIndex, false );
ret = static_cast< long double >( ival );
}
else
{
int64_t ival = getInt64_intern( columnIndex, false );
ret = static_cast< long double >( ival );
}
return ret;
}
case DataType::NUMERIC:
case DataType::DECIMAL:
case DataType::TIMESTAMP:
case DataType::DATE:
case DataType::TIME:
case DataType::CHAR:
case DataType::BINARY:
case DataType::VARCHAR:
case DataType::VARBINARY:
case DataType::LONGVARCHAR:
case DataType::LONGVARBINARY:
case DataType::SET:
case DataType::ENUM:
case DataType::JSON:
{
long double ret = Mysql::Util::strtonum( getString( columnIndex ).c_str() );
return ret;
}
case DataType::REAL:
{
long double ret = !*m_pResultBind->m_pBind[columnIndex - 1].is_null ?
*reinterpret_cast< float* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0.;
return ret;
}
case DataType::DOUBLE:
{
long double ret = !*m_pResultBind->m_pBind[columnIndex - 1].is_null ?
*reinterpret_cast< double* >( m_pResultBind->m_pBind[columnIndex - 1].buffer ) : 0.;
return ret;
}
}
throw std::runtime_error( "PreparedResultSet::getDouble: unhandled type. Please, report" );
return .0;
}
long double Mysql::PreparedResultSet::getDouble( const std::string& columnLabel ) const
{
return getDouble( findColumn( columnLabel ) );
}
float Mysql::PreparedResultSet::getFloat( const uint32_t columnIndex ) const
{
return static_cast< float >( getDouble( columnIndex ) );
}
float Mysql::PreparedResultSet::getFloat( const std::string& columnLabel ) const
{
return static_cast< float >( getDouble( findColumn( columnLabel ) ) );
}
size_t Mysql::PreparedResultSet::getRow() const
{
return static_cast< size_t >( m_rowPosition );
}
size_t Mysql::PreparedResultSet::rowsCount() const
{
return static_cast< uint32_t >( m_numRows );
}
const std::shared_ptr< Mysql::Statement > Mysql::PreparedResultSet::getStatement() const
{
return m_pStmt;
}
std::istream* Mysql::PreparedResultSet::getBlob( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getBlob: can't fetch because not on result set" );
return new std::istringstream( getString( columnIndex ) );
}
std::istream* Mysql::PreparedResultSet::getBlob( const std::string& columnLabel ) const
{
return new std::istringstream( getString( columnLabel ) );
}
std::vector< char > Mysql::PreparedResultSet::getBlobVector( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::getBlobVector: invalid value of 'columnIndex'" );
std::unique_ptr< std::istream > inStr( getBlob( columnIndex ) );
char buff[4196];
std::vector< char > data;
inStr->read( buff, sizeof( buff ) );
if( inStr->gcount() )
{
data.resize( static_cast< uint32_t >( inStr->gcount() ) );
memcpy( data.data(), buff, static_cast< size_t >( inStr->gcount() ) );
}
return data;
}
std::vector< char > Mysql::PreparedResultSet::getBlobVector( const std::string& columnLabel ) const
{
return getBlobVector( findColumn( columnLabel ) );
}
bool Mysql::PreparedResultSet::getBoolean( const uint32_t columnIndex ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::getBoolean: can't fetch because not on result set" );
return getInt(columnIndex ) != 0;
}
bool Mysql::PreparedResultSet::getBoolean( const std::string& columnLabel ) const
{
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error("PreparedResultSet::getBoolean: can't fetch because not on result set");
return getInt(columnLabel ) != 0;
}
bool Mysql::PreparedResultSet::isLast() const
{
return ( m_rowPosition == m_numRows );
}
bool Mysql::PreparedResultSet::isFirst() const
{
return ( m_rowPosition == 1 );
}
bool Mysql::PreparedResultSet::isNull( const uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "PreparedResultSet::isNull: invalid value of 'columnIndex'" );
if( isBeforeFirstOrAfterLast() )
throw std::runtime_error( "PreparedResultSet::isNull: can't fetch because not on result set" );
return *m_pResultBind->m_pBind[columnIndex - 1].is_null != 0;
}
bool Mysql::PreparedResultSet::isNull( const std::string& columnLabel ) const
{
uint32_t index = findColumn( columnLabel );
if( index == 0 )
throw std::runtime_error( "PreparedResultSet::isNull: invalid value of 'columnLabel'" );
return isNull( index );
}
bool Mysql::PreparedResultSet::next()
{
bool ret = false;
// reset last_queried_column
// m_lastQueriedColumn = std::numeric_limits< uint32_t >::max();
int result = mysql_stmt_fetch( m_pStmt->getRawStmt() );
if( !result || result == MYSQL_DATA_TRUNCATED )
ret = true;
if( result == MYSQL_NO_DATA )
ret = false;
if( result == 1 )
throw std::runtime_error( "PreparedResultSet:next: error getting next result" );
++m_rowPosition;
return ret;
}
void Mysql::PreparedResultSet::clearWarnings()
{
}
void Mysql::PreparedResultSet::free()
{
if( m_pStmt->getRawStmt() )
mysql_stmt_free_result( m_pStmt->getRawStmt() );
}

120
deps/mysqlConnector/PreparedResultSet.h vendored Normal file
View file

@ -0,0 +1,120 @@
#ifndef SAPPHIRE_PREPAREDRESULTSET_H
#define SAPPHIRE_PREPAREDRESULTSET_H
#include <memory>
#include "ResultSet.h"
namespace Mysql
{
class PreparedStatement;
class ResultBind;
class PreparedResultSet : public ResultSet
{
private:
mutable uint32_t m_lastQueriedColumn; // this is updated by calls to getInt(int), getString(int), etc...
uint32_t m_numFields;
uint64_t m_numRows;
uint64_t m_rowPosition;
typedef std::map< std::string, uint32_t > FieldNameIndexMap;
FieldNameIndexMap m_fieldNameToIndex;
std::shared_ptr< PreparedStatement > m_pStmt;
bool is_valid;
std::shared_ptr< ResultBind > m_pResultBind;
protected:
void checkValid() const;
void closeIntern();
bool isBeforeFirstOrAfterLast() const;
void seek();
int64_t getInt64_intern( const uint32_t columnIndex, bool cutTooBig ) const;
uint64_t getUInt64_intern( const uint32_t columnIndex, bool cutTooBig ) const;
public:
PreparedResultSet( std::shared_ptr< ResultBind >& pBind, std::shared_ptr< PreparedStatement > par );
~PreparedResultSet() override;
void free();
void clearWarnings();
void close();
uint32_t findColumn( const std::string& columnLabel ) const override;
std::istream * getBlob( uint32_t columnIndex ) const override;
std::istream * getBlob( const std::string& columnLabel ) const override;
std::vector< char > getBlobVector( uint32_t columnIndex ) const override;
std::vector< char > getBlobVector( const std::string& columnLabel ) const override;
bool getBoolean( uint32_t columnIndex ) const override;
bool getBoolean( const std::string& columnLabel ) const override;
long double getDouble( uint32_t columnIndex ) const override;
long double getDouble( const std::string& columnLabel ) const override;
float getFloat( uint32_t columnIndex ) const override;
float getFloat( const std::string& columnLabel ) const override;
int32_t getInt( uint32_t columnIndex ) const override;
int32_t getInt( const std::string& columnLabel ) const override;
int16_t getInt16( uint32_t columnIndex ) const override;
int16_t getInt16( const std::string& columnLabel ) const override;
int8_t getInt8( uint32_t columnIndex ) const;
int8_t getInt8( const std::string& columnLabel ) const;
uint32_t getUInt( uint32_t columnIndex ) const override;
uint32_t getUInt( const std::string& columnLabel ) const override;
uint8_t getUInt8( uint32_t columnIndex ) const;
uint8_t getUInt8( const std::string& columnLabel ) const;
uint16_t getUInt16( uint32_t columnIndex ) const override;
uint16_t getUInt16( const std::string& columnLabel ) const override;
int64_t getInt64( uint32_t columnIndex ) const override;
int64_t getInt64( const std::string& columnLabel ) const override;
uint64_t getUInt64( uint32_t columnIndex ) const override;
uint64_t getUInt64( const std::string& columnLabel ) const override;
size_t getRow() const override;
const std::shared_ptr< Statement > getStatement() const override;
std::string getString( uint32_t columnIndex ) const override;
std::string getString( const std::string& columnLabel ) const override;
void getWarnings();
bool isClosed() const;
void insertRow();
bool isFirst() const override;
bool isLast() const override;
bool isNull( uint32_t columnIndex ) const override;
bool isNull( const std::string& columnLabel ) const override;
bool next() override;
size_t rowsCount() const;
};
}
#endif //SAPPHIRE_PREPAREDRESULTSET_H

View file

@ -0,0 +1,692 @@
#include "PreparedStatement.h"
#include "PreparedResultSet.h"
#include "Connection.h"
#include "ResultBind.h"
#include <variant>
#include <errmsg.h>
#include <string.h>
#include <mysql.h>
static const unsigned int MAX_SEND_LONGDATA_BUFFER = 1 << 18; //1<<18=256k (for istream)
static const unsigned int MAX_SEND_LONGDATA_CHUNK = 1 << 18; //1<<19=512k (for string)
namespace Mysql
{
// Visitor class to send long data contained in blob_bind
struct LongDataSender
{
unsigned position;
MYSQL_STMT* m_pStmt;
LongDataSender()
{}
LongDataSender( MYSQL_STMT* pStmt, unsigned int i ) :
position( i ),
m_pStmt( pStmt )
{
}
bool operator()( std::istream* my_blob ) const
{
if( my_blob == nullptr )
return false;
//char buf[MAX_SEND_LONGDATA_BUFFER];
std::unique_ptr< char[] > buf( new char[MAX_SEND_LONGDATA_BUFFER] );
do
{
if( my_blob->eof() )
break;
my_blob->read( buf.get(), MAX_SEND_LONGDATA_BUFFER );
if( my_blob->bad() )
throw std::runtime_error( "Error while reading from blob (bad)" );
else if( my_blob->fail() )
{
if( !my_blob->eof() )
throw std::runtime_error( "Error while reading from blob (fail)" );
}
if( mysql_stmt_send_long_data( m_pStmt, position, buf.get(), static_cast< unsigned long >( my_blob->gcount() ) ) )
{
switch( mysql_stmt_errno( m_pStmt ) )
{
case CR_OUT_OF_MEMORY:
throw std::bad_alloc();
case CR_INVALID_BUFFER_USE:
throw std::runtime_error( "PreparedStatement::setBlob: can't set blob value on that column" );
case CR_SERVER_GONE_ERROR:
case CR_COMMANDS_OUT_OF_SYNC:
default:
throw std::runtime_error( "PreparedStatement:: Default error" );
}
}
} while( true );
return true;
}
bool operator()( std::string* str ) const
{
if ( str == nullptr )
return false;
uint32_t sent = 0, chunkSize;
while( sent < str->length() )
{
chunkSize = ( sent + MAX_SEND_LONGDATA_CHUNK > str->length()
? str->length() - sent
: MAX_SEND_LONGDATA_CHUNK );
if( mysql_stmt_send_long_data( m_pStmt, position, str->c_str() + sent, chunkSize ) )
{
switch( mysql_stmt_errno( m_pStmt ) )
{
case CR_OUT_OF_MEMORY:
throw std::bad_alloc();
case CR_INVALID_BUFFER_USE:
throw std::runtime_error( "PreparedStatement::setBlob: can't set blob value on that column" );
case CR_SERVER_GONE_ERROR:
case CR_COMMANDS_OUT_OF_SYNC:
default:
throw std::runtime_error( "PreparedStatement:: Default error" );
}
}
sent+= chunkSize;
}
return true;
}
};
struct BlobBindDeleter
{
void operator()( std::string*& str ) const
{
if( str != nullptr )
{
delete str;
str= nullptr;
}
}
void operator()( std::istream*& my_blob ) const
{
if( my_blob!= nullptr )
{
delete my_blob;
my_blob= nullptr;
}
}
};
struct BlobIsNull
{
bool operator()( std::string*& str ) const
{
return str == nullptr;
}
bool operator()( std::istream*& my_blob ) const
{
return my_blob == nullptr;
}
};
void resetBlobBind( MYSQL_BIND& param )
{
delete [] static_cast<char *>( param.buffer );
param.buffer_type = MYSQL_TYPE_LONG_BLOB;
param.buffer = nullptr;
param.buffer_length = 0;
param.is_null_value = 0;
delete param.length;
param.length = new unsigned long( 0 );
}
class ParamBind
{
public:
typedef std::variant< std::istream*, std::string* > Blob_t;
private:
unsigned int m_paramCount;
std::unique_ptr< MYSQL_BIND[] > bind;
std::unique_ptr< bool[] > value_set;
std::unique_ptr< bool[] > delete_blob_after_execute;
typedef std::map< uint32_t, Blob_t > Blobs;
Blobs blob_bind;
public:
ParamBind( uint32_t paramCount )
: m_paramCount( paramCount ),
bind( nullptr ),
value_set( nullptr ),
delete_blob_after_execute( nullptr )
{
if( m_paramCount )
{
bind.reset( new MYSQL_BIND[paramCount] );
memset( bind.get(), 0, sizeof( MYSQL_BIND ) * paramCount );
value_set.reset( new bool[paramCount] );
delete_blob_after_execute.reset( new bool[paramCount] );
for( uint32_t i = 0; i < paramCount; ++i )
{
bind[i].is_null_value = 1;
value_set[i] = false;
delete_blob_after_execute[i] = false;
}
}
}
virtual ~ParamBind()
{
clearParameters();
for( Blobs::iterator it = blob_bind.begin(); it != blob_bind.end(); ++it )
{
if( delete_blob_after_execute[it->first] )
{
delete_blob_after_execute[it->first] = false;
std::visit( BlobBindDeleter(), it->second );
}
}
}
void set( uint32_t position )
{
value_set[position] = true;
}
void unset( uint32_t position )
{
value_set[position] = false;
if( delete_blob_after_execute[position] )
{
delete_blob_after_execute[position] = false;
std::visit( BlobBindDeleter(), blob_bind[position] );
blob_bind.erase( position );
}
}
void setBlob( uint32_t position, Blob_t & blob, bool delete_after_execute )
{
set( position );
resetBlobBind( bind[position] );
Blobs::iterator it = blob_bind.find( position );
if( it != blob_bind.end() && delete_blob_after_execute[position] )
std::visit( BlobBindDeleter(), it->second );
if( std::visit( BlobIsNull(), blob ) )
{
if( it != blob_bind.end() )
blob_bind.erase( it );
delete_blob_after_execute[position] = false;
}
else
{
blob_bind[position] = blob;
delete_blob_after_execute[position] = delete_after_execute;
}
}
bool isAllSet()
{
for( uint32_t i = 0; i < m_paramCount; ++i )
{
if( !value_set[i] )
return false;
}
return true;
}
void clearParameters()
{
for( uint32_t i = 0; i < m_paramCount; ++i )
{
delete ( char* ) bind[i].length;
bind[i].length = nullptr;
delete[] ( char* ) bind[i].buffer;
bind[i].buffer = nullptr;
if (value_set[i])
{
Blobs::iterator it = blob_bind.find( i );
if( it != blob_bind.end() && delete_blob_after_execute[i] )
{
std::visit( BlobBindDeleter(), it->second );
blob_bind.erase( it );
}
blob_bind[i] = Blob_t();
value_set[i] = false;
}
}
}
MYSQL_BIND* getBindObject()
{
return bind.get();
}
std::variant< std::istream*, std::string* > getBlobObject( uint32_t position )
{
Blobs::iterator it = blob_bind.find( position );
if( it != blob_bind.end() )
return it->second;
return Blob_t();
}
};
}
Mysql::PreparedStatement::PreparedStatement( MYSQL_STMT* pStmt, std::shared_ptr< Mysql::Connection > pConn )
: Statement( pConn )
{
m_pStmt = pStmt;
m_pConnection = pConn;
m_paramCount = mysql_stmt_param_count( m_pStmt );
m_pParamBind.reset( new ParamBind( m_paramCount ) );
m_pResultBind.reset( new ResultBind( pStmt ) );
}
uint32_t Mysql::PreparedStatement::errNo()
{
return mysql_stmt_errno( m_pStmt );
}
std::shared_ptr< Mysql::Connection > Mysql::PreparedStatement::getConnection()
{
return m_pConnection;
}
Mysql::PreparedStatement::~PreparedStatement()
{
if( m_pStmt )
closeIntern();
}
uint32_t Mysql::PreparedStatement::getWarningCount()
{
return mysql_warning_count( m_pConnection->getRawCon() );
}
uint64_t Mysql::PreparedStatement::getUpdateCount()
{
throw std::runtime_error( "PreparedStatement::getUpdateCount() Not implemented" );
return 0;
}
bool Mysql::PreparedStatement::sendLongDataBeforeParamBind()
{
MYSQL_BIND* bind = m_pParamBind->getBindObject();
for( unsigned int i = 0; i < m_paramCount; ++i )
{
if( bind[i].buffer_type == MYSQL_TYPE_LONG_BLOB )
{
LongDataSender lv( m_pStmt, i );
ParamBind::Blob_t dummy( m_pParamBind->getBlobObject( i ) );
std::visit( lv, dummy );
}
}
return true;
}
void Mysql::PreparedStatement::doQuery()
{
if( m_paramCount && !m_pParamBind->isAllSet() )
throw std::runtime_error( "Value not set for all parameters" );
if( mysql_stmt_bind_param( m_pStmt, m_pParamBind->getBindObject() ) )
throw std::runtime_error("Couldn't bind : " + std::to_string( errNo() ) );
if( !sendLongDataBeforeParamBind() || mysql_stmt_execute( m_pStmt ) )
throw std::runtime_error( "Couldn't execute : " + std::to_string( errNo() ) + ": " + std::string( mysql_stmt_error( m_pStmt ) ) );
warningsCount = getWarningCount();
}
void Mysql::PreparedStatement::closeIntern()
{
if( m_pStmt )
mysql_stmt_close( m_pStmt );
clearParameters();
}
void Mysql::PreparedStatement::clearParameters()
{
m_pParamBind->clearParameters();
}
bool Mysql::PreparedStatement::execute()
{
doQuery();
return mysql_stmt_field_count( m_pStmt ) > 0;
}
bool Mysql::PreparedStatement::execute( const std::string &sql )
{
throw std::runtime_error("PreparedStatement::execute( const std::string &sql ) Not implemented");
return false;
}
std::shared_ptr< Mysql::ResultSet > Mysql::PreparedStatement::executeQuery( const std::string &sql )
{
// not to be implemented for prepared statements
return nullptr;
}
std::shared_ptr< Mysql::ResultSet > Mysql::PreparedStatement::executeQuery()
{
doQuery();
my_bool bool_tmp = 1;
mysql_stmt_attr_set( m_pStmt, STMT_ATTR_UPDATE_MAX_LENGTH, &bool_tmp );
std::shared_ptr< ResultSet > tmp( new PreparedResultSet( m_pResultBind, std::static_pointer_cast< PreparedStatement >( shared_from_this() ) ) );
return tmp;
}
std::shared_ptr< Mysql::ResultSet > Mysql::PreparedStatement::getResultSet()
{
my_bool bool_tmp = 1;
mysql_stmt_attr_set( m_pStmt, STMT_ATTR_UPDATE_MAX_LENGTH, &bool_tmp );
std::shared_ptr< ResultSet > tmp( new PreparedResultSet( m_pResultBind, std::static_pointer_cast< PreparedStatement >( shared_from_this() ) ) );
return tmp;
}
MYSQL_STMT* Mysql::PreparedStatement::getRawStmt()
{
return m_pStmt;
}
typedef std::pair< char*, size_t > BufferSizePair;
static BufferSizePair allocate_buffer_for_type( enum_field_types t )
{
switch( t )
{
case MYSQL_TYPE_LONG:
return BufferSizePair( new char[4], 4 );
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_LONGLONG:
return BufferSizePair( new char[8], 8 );
case MYSQL_TYPE_STRING:
return BufferSizePair( NULLCSTR, 0 );
case MYSQL_TYPE_NULL:
return BufferSizePair( NULLCSTR, 0 );
default:
throw std::runtime_error( "allocate_buffer_for_type: invalid result_bind data type" );
}
}
void Mysql::PreparedStatement::setInt( uint32_t parameterIndex, int32_t value )
{
if( parameterIndex == 0 || parameterIndex > m_paramCount )
throw std::runtime_error( "PreparedStatement::setInt: invalid 'parameterIndex'" );
--parameterIndex;
{
ParamBind::Blob_t dummy;
m_pParamBind->setBlob( parameterIndex, dummy, false );
m_pParamBind->unset( parameterIndex );
}
enum_field_types t = MYSQL_TYPE_LONG;
BufferSizePair p = allocate_buffer_for_type(t);
m_pParamBind->set(parameterIndex);
MYSQL_BIND* param = &m_pParamBind->getBindObject()[parameterIndex];
param->buffer_type = t;
delete [] static_cast< char* >( param->buffer );
param->buffer = p.first;
param->buffer_length = 0;
param->is_null_value = 0;
delete param->length;
param->length = nullptr;
memcpy( param->buffer, &value, p.second );
}
void Mysql::PreparedStatement::setUInt( uint32_t parameterIndex, uint32_t value )
{
if( parameterIndex == 0 || parameterIndex > m_paramCount )
throw std::runtime_error( "PreparedStatement::setInt: invalid 'parameterIndex'" );
--parameterIndex;
{
ParamBind::Blob_t dummy;
m_pParamBind->setBlob( parameterIndex, dummy, false );
m_pParamBind->unset( parameterIndex );
}
enum_field_types t = MYSQL_TYPE_LONG;
BufferSizePair p = allocate_buffer_for_type(t);
m_pParamBind->set( parameterIndex );
MYSQL_BIND* param = &m_pParamBind->getBindObject()[parameterIndex];
param->buffer_type = t;
delete [] static_cast< char* >( param->buffer );
param->buffer = p.first;
param->buffer_length = 0;
param->is_null_value = 0;
param->is_unsigned = 1;
delete param->length;
param->length = nullptr;
memcpy( param->buffer, &value, p.second );
}
void Mysql::PreparedStatement::setInt64( uint32_t parameterIndex, int64_t value )
{
if( parameterIndex == 0 || parameterIndex > m_paramCount )
throw std::runtime_error( "PreparedStatement::setInt64: invalid 'parameterIndex'" );
--parameterIndex;
{
ParamBind::Blob_t dummy;
m_pParamBind->setBlob( parameterIndex, dummy, false );
m_pParamBind->unset( parameterIndex );
}
enum_field_types t = MYSQL_TYPE_LONGLONG;
BufferSizePair p = allocate_buffer_for_type(t);
m_pParamBind->set( parameterIndex );
MYSQL_BIND* param = &m_pParamBind->getBindObject()[parameterIndex];
param->buffer_type = t;
delete [] static_cast< char* >( param->buffer );
param->buffer = p.first;
param->buffer_length = 0;
param->is_null_value = 0;
delete param->length;
param->length = nullptr;
memcpy( param->buffer, &value, p.second );
}
void Mysql::PreparedStatement::setUInt64( uint32_t parameterIndex, uint64_t value )
{
if( parameterIndex == 0 || parameterIndex > m_paramCount )
throw std::runtime_error( "PreparedStatement::setInt64: invalid 'parameterIndex'" );
--parameterIndex;
{
ParamBind::Blob_t dummy;
m_pParamBind->setBlob( parameterIndex, dummy, false );
m_pParamBind->unset( parameterIndex );
}
enum_field_types t = MYSQL_TYPE_LONGLONG;
BufferSizePair p = allocate_buffer_for_type(t);
m_pParamBind->set( parameterIndex );
MYSQL_BIND* param = &m_pParamBind->getBindObject()[parameterIndex];
param->buffer_type = t;
delete [] static_cast< char* >( param->buffer );
param->buffer = p.first;
param->buffer_length = 0;
param->is_null_value = 0;
param->is_unsigned = 1;
delete param->length;
param->length = nullptr;
memcpy( param->buffer, &value, p.second );
}
void Mysql::PreparedStatement::setNull( uint32_t parameterIndex, int )
{
if( parameterIndex == 0 || parameterIndex > m_paramCount )
throw std::runtime_error( "PreparedStatement::setNull: invalid 'parameterIndex'" );
--parameterIndex;
{
ParamBind::Blob_t dummy;
m_pParamBind->setBlob( parameterIndex, dummy, false );
m_pParamBind->unset( parameterIndex );
}
enum_field_types t = MYSQL_TYPE_NULL;
m_pParamBind->set( parameterIndex );
MYSQL_BIND* param = &m_pParamBind->getBindObject()[parameterIndex];
param->buffer_type = t;
delete [] static_cast< char* >( param->buffer );
param->buffer = nullptr;
delete param->length;
param->length = nullptr;
}
void Mysql::PreparedStatement::setString( uint32_t parameterIndex, const std::string& value )
{
if( parameterIndex == 0 || parameterIndex > m_paramCount )
{
throw std::runtime_error( "PreparedStatement::setString: invalid 'parameterIndex'" );
}
if( value.length() > 256*1024 )
{
std::string* pvalue = new std::string( value );
ParamBind::Blob_t dummy( pvalue );
return m_pParamBind->setBlob( --parameterIndex, dummy, true );
}
--parameterIndex;
{
ParamBind::Blob_t dummy;
m_pParamBind->setBlob( parameterIndex, dummy, false );
m_pParamBind->unset( parameterIndex );
}
enum_field_types t = MYSQL_TYPE_STRING;
m_pParamBind->set( parameterIndex );
MYSQL_BIND* param = &m_pParamBind->getBindObject()[parameterIndex];
delete [] static_cast< char* >( param->buffer );
param->buffer_type = t;
param->buffer = memcpy( new char[value.length() + 1], value.c_str(), value.length() + 1 );
param->buffer_length = static_cast< unsigned long >( value.length() ) + 1;
param->is_null_value = 0;
delete param->length;
param->length = new unsigned long( static_cast< unsigned long >( value.length() ) );
}
void Mysql::PreparedStatement::setDouble( uint32_t parameterIndex, double value )
{
if( parameterIndex == 0 || parameterIndex > m_paramCount )
{
throw std::runtime_error( "PreparedStatement::setDouble: invalid 'parameterIndex'" );
}
--parameterIndex;
{
ParamBind::Blob_t dummy;
m_pParamBind->setBlob( parameterIndex, dummy, false );
m_pParamBind->unset( parameterIndex );
}
enum_field_types t = MYSQL_TYPE_DOUBLE;
BufferSizePair p = allocate_buffer_for_type(t);
m_pParamBind->set( parameterIndex );
MYSQL_BIND* param = &m_pParamBind->getBindObject()[parameterIndex];
param->buffer_type = t;
delete [] static_cast< char* >( param->buffer );
param->buffer = p.first;
param->buffer_length = 0;
param->is_null_value = 0;
delete param->length;
param->length = nullptr;
memcpy( param->buffer, &value, p.second );
}
void Mysql::PreparedStatement::setDateTime( uint32_t parameterIndex, const std::string& value )
{
setString( parameterIndex, value );
}
void Mysql::PreparedStatement::setBoolean( uint32_t parameterIndex, bool value )
{
setInt( parameterIndex, value );
}
void Mysql::PreparedStatement::setBigInt( uint32_t parameterIndex, const std::string& value )
{
setString( parameterIndex, value );
}
void Mysql::PreparedStatement::setBlob( uint32_t parameterIndex, std::istream* blob )
{
if( parameterIndex == 0 || parameterIndex > m_paramCount )
throw std::runtime_error( "PreparedStatement::setBlob: invalid 'parameterIndex'" );
ParamBind::Blob_t dummy(blob);
m_pParamBind->setBlob( --parameterIndex, dummy, false );
}

88
deps/mysqlConnector/PreparedStatement.h vendored Normal file
View file

@ -0,0 +1,88 @@
#ifndef SAPPHIRE_DB_PREPAREDSTATEMENT_H
#define SAPPHIRE_DB_PREPAREDSTATEMENT_H
#include <memory>
#include "Statement.h"
typedef struct st_mysql_stmt MYSQL_STMT;
namespace Mysql
{
class ParamBind;
class ResultBind;
class PreparedStatement : public Statement
{
protected:
MYSQL_STMT * m_pStmt;
std::shared_ptr< Connection > m_pConnection;
std::unique_ptr< ParamBind > m_pParamBind;
uint32_t m_paramCount;
int32_t resultSetConcurrency;
int32_t resultSetType;
std::shared_ptr< ResultBind > m_pResultBind;
unsigned int warningsCount;
virtual void doQuery();
virtual void closeIntern();
bool sendLongDataBeforeParamBind();
public:
PreparedStatement( MYSQL_STMT* pStmt, std::shared_ptr< Connection > pConn );
virtual ~PreparedStatement();
std::shared_ptr< Connection > getConnection() override;
MYSQL_STMT* getRawStmt();
uint32_t errNo() override;
uint32_t getWarningCount() override;
uint64_t getUpdateCount() override;
void clearParameters();
bool execute();
bool execute( const std::string& sql ) override;
std::shared_ptr< ResultSet > executeQuery();
std::shared_ptr< ResultSet > executeQuery( const std::string& sql ) override;
bool getMoreResults();
std::shared_ptr< ResultSet > getResultSet() override;
void setBlob( uint32_t parameterIndex, std::istream * blob );
void setBoolean( uint32_t parameterIndex, bool value );
void setBigInt( uint32_t parameterIndex, const std::string& value );
void setDateTime( uint32_t parameterIndex, const std::string& value );
void setDouble( uint32_t parameterIndex, double value );
void setInt( uint32_t parameterIndex, int32_t value );
void setUInt( uint32_t parameterIndex, uint32_t value );
void setInt64( uint32_t parameterIndex, int64_t value );
void setUInt64( uint32_t parameterIndex, uint64_t value );
void setNull( uint32_t parameterIndex, int sqlType );
void setString( uint32_t parameterIndex, const std::string& value );
private:
PreparedStatement( const PreparedStatement& );
void operator=( PreparedStatement& );
};
}
#endif //SAPPHIRE_DB_PREPAREDSTATEMENT_H

146
deps/mysqlConnector/ResultBind.cpp vendored Normal file
View file

@ -0,0 +1,146 @@
#include "ResultBind.h"
#include "mysql_util.h"
#include "ResultBind.h"
#include <string.h>
namespace Mysql
{
struct st_buffer_size_type
{
char * buffer;
size_t size;
enum_field_types type;
st_buffer_size_type( char * b, size_t s, enum_field_types t )
: buffer( b ),
size( s ),
type( t )
{
}
};
using BufferSizePair = std::pair< char*, size_t >;
static struct st_buffer_size_type
allocate_buffer_for_field( const MYSQL_FIELD * const field )
{
switch( field->type )
{
case MYSQL_TYPE_NULL:
return st_buffer_size_type( nullptr, 0, field->type );
case MYSQL_TYPE_TINY:
return st_buffer_size_type( new char[1], 1, field->type );
case MYSQL_TYPE_SHORT:
return st_buffer_size_type( new char[2], 2, field->type );
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_FLOAT:
return st_buffer_size_type( new char[4], 4, field->type );
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_LONGLONG:
return st_buffer_size_type( new char[8], 8, field->type );
case MYSQL_TYPE_YEAR:
return st_buffer_size_type( new char[2], 2, MYSQL_TYPE_SHORT );
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
return st_buffer_size_type( new char[sizeof( MYSQL_TIME )], sizeof( MYSQL_TIME ), field->type );
case MYSQL_TYPE_TINY_BLOB:
return st_buffer_size_type( new char[256], 256, field->type );
case MYSQL_TYPE_LONG_BLOB:
return st_buffer_size_type( new char[16777215], 16777215, field->type );
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
return st_buffer_size_type( new char[65535], 65535, field->type );
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
return st_buffer_size_type( new char[64], 64, field->type );
#if A1
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_YEAR:
return st_buffer_size_type(new char[10], 10, field->type);
#endif
#if A0
// There two are not sent over the wire
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
#endif
case MYSQL_TYPE_BIT:
return st_buffer_size_type( new char[8], 8, MYSQL_TYPE_BIT );
case MYSQL_TYPE_GEOMETRY:
default:
throw std::runtime_error( "allocate_buffer_for_field: invalid rbind data type" );
}
}
ResultBind::ResultBind( MYSQL_STMT* pStmt )
: m_pStmt( pStmt ),
m_numFields( 0 ),
m_isNull( nullptr ),
m_err( nullptr ),
m_len( nullptr ),
m_pBind( nullptr )
{
}
ResultBind::~ResultBind()
{
if( m_pBind.get() )
{
for( uint32_t i = 0; i < m_numFields; ++i )
delete[] ( char* ) m_pBind[i].buffer;
}
}
void ResultBind::bindResult()
{
for( uint32_t i = 0; i < m_numFields; ++i )
delete[] ( char* ) m_pBind[i].buffer;
m_pBind.reset( nullptr );
m_isNull.reset( nullptr );
m_err.reset( nullptr );
m_len.reset( nullptr );
m_numFields = mysql_stmt_field_count( m_pStmt );
if( !m_numFields )
return;
m_pBind.reset( new MYSQL_BIND[m_numFields] );
memset( m_pBind.get(), 0, sizeof( MYSQL_BIND ) * m_numFields );
m_isNull.reset( new my_bool[m_numFields] );
memset( m_isNull.get(), 0, sizeof( my_bool ) * m_numFields );
m_err.reset( new my_bool[m_numFields] );
memset( m_err.get(), 0, sizeof( my_bool ) * m_numFields );
m_len.reset( new unsigned long[m_numFields] );
memset( m_len.get(), 0, sizeof( unsigned long ) * m_numFields );
MYSQL_RES* info = mysql_stmt_result_metadata( m_pStmt );
for( uint32_t i = 0; i < m_numFields; ++i )
{
// MYSQL_FIELD * field = resultMeta->fetch_field();
MYSQL_FIELD * field = mysql_fetch_field_direct( info, i );
struct st_buffer_size_type p = allocate_buffer_for_field(field);
m_pBind[i].buffer_type = p.type;
m_pBind[i].buffer = p.buffer;
m_pBind[i].buffer_length = static_cast< unsigned long >( p.size );
m_pBind[i].length = &m_len[i];
m_pBind[i].is_null = &m_isNull[i];
m_pBind[i].error = &m_err[i];
m_pBind[i].is_unsigned = field->flags & UNSIGNED_FLAG;
}
if( mysql_stmt_bind_result( m_pStmt, m_pBind.get() ) )
throw std::runtime_error( "Couldn't bind : " + std::to_string( mysql_stmt_errno( m_pStmt ) ) );
}
}

33
deps/mysqlConnector/ResultBind.h vendored Normal file
View file

@ -0,0 +1,33 @@
#ifndef SAPPHIRE_RESULTBIND_H
#define SAPPHIRE_RESULTBIND_H
#include <memory>
#include "mysql_util.h"
#include "mysql.h"
#include "PreparedStatement.h"
namespace Mysql
{
class ResultBind
{
uint32_t m_numFields;
std::unique_ptr< char[] > m_isNull;
std::unique_ptr< char[] > m_err;
std::unique_ptr< unsigned long[] > m_len;
MYSQL_STMT* m_pStmt;
public:
std::unique_ptr< MYSQL_BIND[] > m_pBind;
MYSQL_STMT* getStmt() { return m_pStmt; }
ResultBind( MYSQL_STMT* pStmt );
~ResultBind();
void bindResult();
};
}
#endif //SAPPHIRE_RESULTBIND_H

329
deps/mysqlConnector/ResultSet.cpp vendored Normal file
View file

@ -0,0 +1,329 @@
#include "ResultSet.h"
#include "Connection.h"
#include "Statement.h"
#include "mysql_util.h"
#include <cctype>
#include <clocale>
#include <vector>
#include <string.h>
#include <algorithm>
#include <mysql.h>
Mysql::ResultSet::ResultSet( MYSQL_RES* res, std::shared_ptr< Mysql::Statement > par )
{
if( !res )
return;
m_pRes = res;
m_numRows = mysql_num_rows( res );
m_numFields = mysql_num_fields( res );
m_pStmt = par;
m_rowPosition = 1;
for( uint32_t i = 0; i < m_numFields; ++i )
{
std::string fieldName( getFieldMeta(i + 1)->name );
std::transform( fieldName.begin(), fieldName.end(), fieldName.begin(),
[]( unsigned char c ){ return std::toupper(c); } );
m_fieldNameToIndex[fieldName] = i;
}
}
Mysql::ResultSet::~ResultSet()
{
}
MYSQL_FIELD* Mysql::ResultSet::getFieldMeta( uint32_t columnIndex ) const
{
return mysql_fetch_field_direct( m_pRes, columnIndex - 1 );
}
uint32_t Mysql::ResultSet::findColumn( const std::string &columnLabel ) const
{
std::string searchColumn = columnLabel;
std::transform( searchColumn.begin(), searchColumn.end(), searchColumn.begin(),
[](unsigned char c){ return std::toupper(c); } );
auto iter = m_fieldNameToIndex.find( searchColumn );
if( iter == m_fieldNameToIndex.end() )
return 0;
return iter->second + 1;
}
size_t Mysql::ResultSet::getRow() const
{
return static_cast< size_t >( m_rowPosition );
}
bool Mysql::ResultSet::isLast() const
{
return ( m_rowPosition == m_numRows );
}
bool Mysql::ResultSet::isFirst() const
{
return ( m_rowPosition == 1 );
}
bool Mysql::ResultSet::next()
{
bool ret = false;
m_lastQueriedColumn = -1;
m_row = mysql_fetch_row( m_pRes );
if( m_row == nullptr )
{
if( m_pStmt->errNo() == 2013 || m_pStmt->errNo() == 2000 )
throw std::runtime_error( "Error fetching next row " + std::to_string( m_pStmt->errNo() ) +
": " + m_pStmt->getConnection()->getError() );
}
if( ( ret = ( m_row != nullptr ) ) )
++m_rowPosition;
else
m_rowPosition = 0;
return ret;
}
size_t Mysql::ResultSet::rowsCount() const
{
return static_cast< uint32_t >( m_numRows );
}
const std::shared_ptr< Mysql::Statement > Mysql::ResultSet::getStatement() const
{
return m_pStmt;
}
int64_t Mysql::ResultSet::getInt64( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "ResultSet::getInt64: invalid value of 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( m_row[columnIndex - 1] == nullptr )
{
m_wasNull = true;
return 0;
}
m_wasNull = false;
if( getFieldMeta(columnIndex)->type == MYSQL_TYPE_BIT &&
getFieldMeta(columnIndex)->flags != ( BINARY_FLAG | UNSIGNED_FLAG ) )
{
uint64_t uval = 0;
std::div_t length = std::div( getFieldMeta( columnIndex )->length, 8 );
if( length.rem != 0 )
++length.quot;
switch( length.quot )
{
case 8:uval = (uint64_t) bit_uint8korr( m_row[columnIndex - 1] );break;
case 7:uval = (uint64_t) bit_uint7korr( m_row[columnIndex - 1] );break;
case 6:uval = (uint64_t) bit_uint6korr( m_row[columnIndex - 1] );break;
case 5:uval = (uint64_t) bit_uint5korr( m_row[columnIndex - 1] );break;
case 4:uval = (uint64_t) bit_uint4korr( m_row[columnIndex - 1] );break;
case 3:uval = (uint64_t) bit_uint3korr( m_row[columnIndex - 1] );break;
case 2:uval = (uint64_t) bit_uint2korr( m_row[columnIndex - 1] );break;
case 1:uval = (uint64_t) bit_uint1korr( m_row[columnIndex - 1] );break;
}
return uval;
}
if( getFieldMeta( columnIndex)->flags & UNSIGNED_FLAG )
return std::stoll( m_row[columnIndex - 1] );
return std::stoll( m_row[columnIndex - 1] );
}
int64_t Mysql::ResultSet::getInt64( const std::string &columnLabel ) const
{
return getInt64( findColumn( columnLabel ) );
}
uint64_t Mysql::ResultSet::getUInt64( uint32_t columnIndex ) const
{
return static_cast< uint64_t >( getInt64( columnIndex ) );
}
uint64_t Mysql::ResultSet::getUInt64( const std::string &columnLabel ) const
{
return getUInt64( findColumn( columnLabel ) );
}
uint16_t Mysql::ResultSet::getUInt16( uint32_t columnIndex ) const
{
return static_cast< uint16_t >( getInt( columnIndex ) );
}
uint16_t Mysql::ResultSet::getUInt16( const std::string &columnLabel ) const
{
return getUInt16( findColumn( columnLabel ) );
}
int16_t Mysql::ResultSet::getInt16( uint32_t columnIndex ) const
{
return static_cast< int16_t >( getInt( columnIndex ) );
}
int16_t Mysql::ResultSet::getInt16( const std::string &columnLabel ) const
{
return getUInt16( findColumn( columnLabel ) );
}
int32_t Mysql::ResultSet::getInt( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "ResultSet::getInt: invalid value of 'columnIndex'" );
if( ( getFieldMeta( columnIndex )->flags & UNSIGNED_FLAG ) != 0 )
return static_cast< uint32_t >( getInt64( columnIndex ) );
return static_cast< int32_t >( getInt64( columnIndex ) );
}
int32_t Mysql::ResultSet::getInt( const std::string &columnLabel ) const
{
return getInt( findColumn( columnLabel ) );
}
uint32_t Mysql::ResultSet::getUInt( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "ResultSet::getUInt: invalid value of 'columnIndex'" );
return static_cast< uint32_t >( getUInt64( columnIndex ) );
}
uint32_t Mysql::ResultSet::getUInt( const std::string &columnLabel ) const
{
return getUInt( findColumn( columnLabel ) );
}
long double Mysql::ResultSet::getDouble( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "ResultSet::getDouble: invalid value of 'columnIndex'" );
m_lastQueriedColumn = columnIndex;
if( m_row[columnIndex - 1] == nullptr )
{
m_wasNull = true;
return 0.0;
}
m_wasNull = false;
if( getFieldMeta(columnIndex)->type == MYSQL_TYPE_BIT )
return static_cast< long double >( getInt64( columnIndex ) );
return Mysql::Util::strtonum( m_row[columnIndex - 1] );
}
long double Mysql::ResultSet::getDouble( const std::string &columnLabel ) const
{
return getDouble( findColumn( columnLabel ) );
}
float Mysql::ResultSet::getFloat( uint32_t columnIndex ) const
{
return static_cast< float >( getDouble( columnIndex ) );
}
float Mysql::ResultSet::getFloat( const std::string &columnLabel ) const
{
return getFloat( findColumn( columnLabel ) );
}
bool Mysql::ResultSet::getBoolean( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "ResultSet::getBoolean: invalid value of 'columnIndex'" );
return getInt( columnIndex ) ? true : false;
}
bool Mysql::ResultSet::getBoolean( const std::string &columnLabel ) const
{
return getInt( columnLabel ) ? true : false;
}
std::string Mysql::ResultSet::getString( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "ResultSet::getString: invalid value of 'columnIndex'" );
if( m_row == nullptr || m_row[columnIndex - 1] == nullptr )
{
m_wasNull = true;
return "";
}
if( getFieldMeta( columnIndex )->type == MYSQL_TYPE_BIT )
{
char buf[30];
snprintf( buf, sizeof( buf ) - 1, "%llu", ( unsigned long long ) getUInt64( columnIndex ) );
return std::string( buf );
}
size_t len = mysql_fetch_lengths( m_pRes )[columnIndex - 1];
m_wasNull = false;
return std::string( m_row[columnIndex - 1], len );
}
std::string Mysql::ResultSet::getString( const std::string &columnLabel ) const
{
return getString( findColumn( columnLabel ) );
}
bool Mysql::ResultSet::isNull( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "ResultSet::isNull: invalid value of 'columnIndex'" );
return ( m_row[columnIndex - 1] == nullptr );
}
bool Mysql::ResultSet::isNull( const std::string &columnLabel ) const
{
return isNull( findColumn( columnLabel ) );
}
std::istream* Mysql::ResultSet::getBlob( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "ResultSet::getBlob: invalid value of 'columnIndex'" );
return new std::istringstream( getString( columnIndex ) );
}
std::istream* Mysql::ResultSet::getBlob( const std::string& columnLabel ) const
{
return new std::istringstream( getString( columnLabel ) );
}
std::vector< char > Mysql::ResultSet::getBlobVector( uint32_t columnIndex ) const
{
if( columnIndex == 0 || columnIndex > m_numFields )
throw std::runtime_error( "ResultSet::getBlobVector: invalid value of 'columnIndex'" );
std::unique_ptr< std::istream > inStr( getBlob( columnIndex ) );
char buff[4196];
std::vector< char > data;
inStr->read( buff, sizeof( buff ) );
if( inStr->gcount() )
{
data.resize( static_cast< const uint32_t >( inStr->gcount() ) );
memcpy(data.data(), buff, static_cast< size_t >( inStr->gcount() ) );
}
return data;
}
std::vector< char > Mysql::ResultSet::getBlobVector( const std::string& columnLabel ) const
{
return getBlobVector( findColumn( columnLabel ) );
}

107
deps/mysqlConnector/ResultSet.h vendored Normal file
View file

@ -0,0 +1,107 @@
#ifndef SAPPHIRE_RESULTSET_H
#define SAPPHIRE_RESULTSET_H
#include <vector>
#include "ResultSetBase.h"
#include <memory>
typedef char **MYSQL_ROW;
typedef struct st_mysql_res MYSQL_RES;
typedef struct st_mysql_field MYSQL_FIELD;
namespace Mysql
{
class Statement;
class ResultSet
{
MYSQL_ROW m_row;
uint32_t m_numFields;
uint64_t m_numRows;
uint64_t m_rowPosition;
using FieldNameIndexMap = std::map< std::string, uint32_t >;
FieldNameIndexMap m_fieldNameToIndex;
mutable bool m_wasNull;
mutable uint32_t m_lastQueriedColumn;
std::shared_ptr< Statement > m_pStmt;
MYSQL_RES* m_pRes;
protected:
MYSQL_FIELD* getFieldMeta( unsigned int columnIndex ) const;
public:
ResultSet( MYSQL_RES* res, std::shared_ptr< Statement > par );
virtual ~ResultSet();
virtual uint32_t findColumn( const std::string& columnLabel ) const;
virtual std::istream * getBlob( uint32_t columnIndex ) const;
virtual std::istream * getBlob( const std::string& columnLabel ) const;
virtual std::vector< char > getBlobVector( uint32_t columnIndex ) const;
virtual std::vector< char > getBlobVector( const std::string& columnLabel ) const;
virtual bool getBoolean( uint32_t columnIndex ) const;
virtual bool getBoolean( const std::string& columnLabel ) const;
virtual long double getDouble( uint32_t columnIndex ) const;
virtual long double getDouble( const std::string& columnLabel ) const;
virtual float getFloat( uint32_t columnIndex ) const;
virtual float getFloat( const std::string& columnLabel ) const;
virtual int32_t getInt( uint32_t columnIndex ) const;
virtual int32_t getInt( const std::string& columnLabel ) const;
virtual uint32_t getUInt( uint32_t columnIndex ) const;
virtual uint32_t getUInt( const std::string& columnLabel ) const;
virtual int16_t getInt16( uint32_t columnIndex ) const;
virtual int16_t getInt16( const std::string& columnLabel ) const;
virtual uint16_t getUInt16( uint32_t columnIndex ) const;
virtual uint16_t getUInt16( const std::string& columnLabel ) const;
virtual int64_t getInt64( uint32_t columnIndex ) const;
virtual int64_t getInt64( const std::string& columnLabel ) const;
virtual uint64_t getUInt64( uint32_t columnIndex ) const;
virtual uint64_t getUInt64( const std::string& columnLabel ) const;
//sql::ResultSetMetaData * getMetaData() const;
virtual size_t getRow() const;
virtual const std::shared_ptr< Statement > getStatement() const;
virtual std::string getString( uint32_t columnIndex ) const;
virtual std::string getString( const std::string& columnLabel ) const;
virtual bool isFirst() const;
virtual bool isLast() const;
virtual bool isNull( uint32_t columnIndex ) const;
virtual bool isNull( const std::string& columnLabel ) const;
virtual bool next();
size_t rowsCount() const;
private:
ResultSet( const ResultSet& );
void operator=( ResultSet& );
};
}
#endif //SAPPHIRE_RESULTSET_H

65
deps/mysqlConnector/ResultSetBase.h vendored Normal file
View file

@ -0,0 +1,65 @@
#ifndef SAPPHIRE_RESULTSETBASE_H
#define SAPPHIRE_RESULTSETBASE_H
#include <list>
#include <map>
#include <iostream>
namespace Mysql
{
class Statement;
class ResultSetBase
{
public:
virtual ~ResultSetBase() {}
virtual uint32_t findColumn( const std::string &columnLabel ) const = 0;
virtual std::istream *getBlob( uint32_t columnIndex ) const = 0;
virtual std::istream *getBlob( const std::string &columnLabel ) const = 0;
virtual bool getBoolean( uint32_t columnIndex ) const = 0;
virtual bool getBoolean( const std::string &columnLabel ) const = 0;
virtual long double getDouble( uint32_t columnIndex ) const = 0;
virtual long double getDouble( const std::string &columnLabel ) const = 0;
virtual int32_t getInt( uint32_t columnIndex ) const = 0;
virtual int32_t getInt( const std::string &columnLabel ) const = 0;
virtual uint32_t getUInt( uint32_t columnIndex ) const = 0;
virtual uint32_t getUInt( const std::string &columnLabel ) const = 0;
virtual int64_t getInt64( uint32_t columnIndex ) const = 0;
virtual int64_t getInt64( const std::string &columnLabel ) const = 0;
virtual uint64_t getUInt64( uint32_t columnIndex ) const = 0;
virtual uint64_t getUInt64( const std::string &columnLabel ) const = 0;
//virtual ResultSetMetaData *getMetaData() const = 0;
virtual size_t getRow() const = 0;
virtual const Statement *getStatement() const = 0;
virtual std::string getString( uint32_t columnIndex ) const = 0;
virtual std::string getString( const std::string &columnLabel ) const = 0;
virtual bool isFirst() const = 0;
virtual bool isLast() const = 0;
virtual bool isNull( uint32_t columnIndex ) const = 0;
virtual bool isNull( const std::string &columnLabel ) const = 0;
virtual bool next() = 0;
virtual size_t rowsCount() const = 0;
};
}
#endif //SAPPHIRE_RESULTSETBASE_H

67
deps/mysqlConnector/Statement.cpp vendored Normal file
View file

@ -0,0 +1,67 @@
#include "Statement.h"
#include "Connection.h"
#include "ResultSet.h"
#include "mysql_util.h"
#include <mysql.h>
std::shared_ptr< Mysql::Connection > Mysql::Statement::getConnection()
{
return m_pConnection;
}
Mysql::Statement::Statement( std::shared_ptr< Mysql::Connection > conn ) :
m_pConnection( conn )
{
}
void Mysql::Statement::doQuery( const std::string &q )
{
mysql_real_query( m_pConnection->getRawCon(), q.c_str(), q.length() );
if( errNo() )
throw std::runtime_error( m_pConnection->getError() );
m_warningsCount = getWarningCount();
}
bool Mysql::Statement::execute( const std::string &sql )
{
doQuery( sql );
bool ret = mysql_field_count( m_pConnection->getRawCon() ) == 0;
m_lastUpdateCount = mysql_affected_rows( m_pConnection->getRawCon() );
return ret;
}
uint64_t Mysql::Statement::getUpdateCount()
{
return m_lastUpdateCount;
}
uint32_t Mysql::Statement::getWarningCount()
{
return mysql_warning_count( m_pConnection->getRawCon() );
}
uint32_t Mysql::Statement::errNo()
{
return mysql_errno( m_pConnection->getRawCon() );
}
std::shared_ptr< Mysql::ResultSet > Mysql::Statement::executeQuery( const std::string &sql )
{
m_lastUpdateCount = UL64(~0);
doQuery( sql );
return std::make_shared< ResultSet >( mysql_store_result( m_pConnection->getRawCon() ), shared_from_this() );
}
std::shared_ptr< Mysql::ResultSet > Mysql::Statement::getResultSet()
{
if( errNo() != 0 )
throw std::runtime_error( "Error during getResultSet() : " + std::to_string( errNo() ) + ": " +
m_pConnection->getError() );
return std::make_shared< ResultSet >( mysql_store_result( m_pConnection->getRawCon() ), shared_from_this() );
}

50
deps/mysqlConnector/Statement.h vendored Normal file
View file

@ -0,0 +1,50 @@
#ifndef SAPPHIRE_STATEMENT_H
#define SAPPHIRE_STATEMENT_H
#include <stdint.h>
#include <string>
#include <memory>
namespace Mysql
{
class Connection;
class ResultSet;
class Statement : public std::enable_shared_from_this< Statement >
{
protected:
std::shared_ptr< Connection > m_pConnection;
void doQuery( const std::string& q );
uint64_t m_lastUpdateCount;
unsigned int m_warningsCount;
public:
Statement( std::shared_ptr< Connection > conn );
virtual ~Statement() {};
virtual std::shared_ptr< Connection > getConnection();
virtual bool execute( const std::string& sql );
virtual std::shared_ptr< ResultSet > executeQuery( const std::string& sql );
virtual std::shared_ptr< ResultSet > getResultSet();
virtual uint64_t getUpdateCount();
virtual uint32_t getWarningCount();
virtual uint32_t errNo();
private:
/* Prevent use of these */
Statement( const Statement& );
void operator=( Statement& );
};
}
#endif //SAPPHIRE_STATEMENT_H

32
deps/mysqlConnector/StatementBase.h vendored Normal file
View file

@ -0,0 +1,32 @@
#ifndef SAPPHIRE_STATEMENTBASE_H
#define SAPPHIRE_STATEMENTBASE_H
#include <string>
namespace Mysql
{
class Connection;
class ResultSet;
class StatementBase
{
public:
virtual ~StatementBase() {};
virtual Connection* getConnection() = 0;
virtual bool execute( const std::string& sql ) = 0;
virtual ResultSet* executeQuery( const std::string& sql ) = 0;
virtual ResultSet* getResultSet() = 0;
virtual uint64_t getUpdateCount() = 0;
virtual uint32_t getWarningCount() = 0;
virtual uint32_t errNo() = 0;
};
}
#endif //SAPPHIRE_STATEMENTBASE_H

457
deps/mysqlConnector/mysql_util.cpp vendored Normal file
View file

@ -0,0 +1,457 @@
#include "mysql_util.h"
#include "DataType.h"
#include <mysql.h>
#include <vector>
#include <stdexcept>
long double Mysql::Util::strtold(const char *nptr, char **endptr)
{
/*
* Experienced odd compilation errors on one of windows build hosts -
* cmake reported there is strold function. Since double and long double on windows
* are of the same size - we are using strtod on those platforms regardless
* to the HAVE_FUNCTION_STRTOLD value
*/
#ifdef _WIN32
return ::strtod(nptr, endptr);
#else
# ifndef HAVE_FUNCTION_STRTOLD
// on linux, strtod would return a value that is 1 less than the input string
// for reasons when the number is in the 64bit range
return std::strtoll( nptr, endptr, 10 );
//return ::strtod(nptr, endptr);
# else
# if defined(__hpux) && defined(_LONG_DOUBLE)
union {
long_double l_d;
long double ld;
} u;
u.l_d = ::strtold( nptr, endptr);
return u.ld;
# else
return ::strtold(nptr, endptr);
# endif
# endif
#endif
}
int64_t Mysql::Util::strtoll( const char* nptr, char** endptr )
{
return static_cast< int64_t >( strtold( nptr, endptr ) );
}
uint64_t Mysql::Util::strtoull( const char* nptr, char** endptr )
{
return static_cast< uint64_t >( strtold( nptr, endptr ) );
}
long double Mysql::Util::strtonum( const std::string &str, int radix )
{
using iter_t = std::istreambuf_iterator< char >;
static std::locale c_locale( "C" );
static const std::num_get< char > &cvt = std::use_facet< std::num_get< char > >( c_locale );
std::istringstream inp( str );
long double val = 0.0L;
inp.imbue( c_locale );
switch( radix )
{
case 10: inp.setf( std::ios_base::dec, std::ios_base::basefield ); break;
case 16: inp.setf( std::ios_base::hex, std::ios_base::basefield ); break;
case 8: inp.setf( std::ios_base::oct, std::ios_base::basefield ); break;
default:
inp.setf( std::ios_base::fmtflags( 0 ), std::ios_base::basefield );
break;
}
iter_t beg( inp ), end;
std::ios::iostate err = std::ios_base::goodbit;
cvt.get( beg, end, inp, err, val );
return val;
}
#define cppconn_mbcharlen_big5 NULL
#define check_mb_big5 NULL
#define cppconn_mbcharlen_ujis NULL
#define check_mb_ujis NULL
#define cppconn_mbcharlen_sjis NULL
#define check_mb_sjis NULL
#define cppconn_mbcharlen_euckr NULL
#define check_mb_euckr NULL
#define cppconn_mbcharlen_gb2312 NULL
#define check_mb_gb2312 NULL
#define cppconn_mbcharlen_gbk NULL
#define check_mb_gbk NULL
#define cppconn_mbcharlen_utf8 NULL
#define check_mb_utf8_valid NULL
#define cppconn_mbcharlen_ucs2 NULL
#define check_mb_ucs2 NULL
#define cppconn_mbcharlen_cp932 NULL
#define check_mb_cp932 NULL
#define cppconn_mbcharlen_eucjpms NULL
#define check_mb_eucjpms NULL
#define cppconn_mbcharlen_utf8 NULL
#define check_mb_utf8_valid NULL
#define cppconn_mbcharlen_utf8mb4 cppconn_mbcharlen_utf8
#define check_mb_utf8mb4_valid check_mb_utf8_valid
#define cppconn_mbcharlen_utf16 NULL
#define check_mb_utf16_valid NULL
#define cppconn_mbcharlen_utf32 NULL
#define check_mb_utf32_valid NULL
/* {{{ our_charsets60 */
const Mysql::Util::OUR_CHARSET our_charsets60[] =
{
{ 1, "big5","big5_chinese_ci", 1, 2, "", cppconn_mbcharlen_big5, check_mb_big5},
{ 3, "dec8", "dec8_swedisch_ci", 1, 1, "", NULL, NULL},
{ 4, "cp850", "cp850_general_ci", 1, 1, "", NULL, NULL},
{ 6, "hp8", "hp8_english_ci", 1, 1, "", NULL, NULL},
{ 7, "koi8r", "koi8r_general_ci", 1, 1, "", NULL, NULL},
{ 8, "latin1", "latin1_swedish_ci", 1, 1, "", NULL, NULL},
{ 9, "latin2", "latin2_general_ci", 1, 1, "", NULL, NULL},
{ 10, "swe7", "swe7_swedish_ci", 1, 1, "", NULL, NULL},
{ 11, "ascii", "ascii_general_ci", 1, 1, "", NULL, NULL},
{ 12, "ujis", "ujis_japanese_ci", 1, 3, "", cppconn_mbcharlen_ujis, check_mb_ujis},
{ 13, "sjis", "sjis_japanese_ci", 1, 2, "", cppconn_mbcharlen_sjis, check_mb_sjis},
{ 16, "hebrew", "hebrew_general_ci", 1, 1, "", NULL, NULL},
{ 18, "tis620", "tis620_thai_ci", 1, 1, "", NULL, NULL},
{ 19, "euckr", "euckr_korean_ci", 1, 2, "", cppconn_mbcharlen_euckr, check_mb_euckr},
{ 22, "koi8u", "koi8u_general_ci", 1, 1, "", NULL, NULL},
{ 24, "gb2312", "gb2312_chinese_ci", 1, 2, "", cppconn_mbcharlen_gb2312, check_mb_gb2312},
{ 25, "greek", "greek_general_ci", 1, 1, "", NULL, NULL},
{ 26, "cp1250", "cp1250_general_ci", 1, 1, "", NULL, NULL},
{ 28, "gbk", "gbk_chinese_ci", 1, 2, "", cppconn_mbcharlen_gbk, check_mb_gbk},
{ 30, "latin5", "latin5_turkish_ci", 1, 1, "", NULL, NULL},
{ 32, "armscii8", "armscii8_general_ci", 1, 1, "", NULL, NULL},
{ 33, "utf8", "utf8_general_ci", 1, 3, "UTF-8 Unicode", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 35, "ucs2", "ucs2_general_ci", 2, 2, "UCS-2 Unicode", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 36, "cp866", "cp866_general_ci", 1, 1, "", NULL, NULL},
{ 37, "keybcs2", "keybcs2_general_ci", 1, 1, "", NULL, NULL},
{ 38, "macce", "macce_general_ci", 1, 1, "", NULL, NULL},
{ 39, "macroman", "macroman_general_ci", 1, 1, "", NULL, NULL},
{ 40, "cp852", "cp852_general_ci", 1, 1, "", NULL, NULL},
{ 41, "latin7", "latin7_general_ci", 1, 1, "", NULL, NULL},
{ 51, "cp1251", "cp1251_general_ci", 1, 1, "", NULL, NULL},
{ 57, "cp1256", "cp1256_general_ci", 1, 1, "", NULL, NULL},
{ 59, "cp1257", "cp1257_general_ci", 1, 1, "", NULL, NULL},
{ 63, "binary", "binary", 1, 1, "", NULL, NULL},
{ 92, "geostd8", "geostd8_general_ci", 1, 1, "", NULL, NULL},
{ 95, "cp932", "cp932_japanese_ci", 1, 2, "", cppconn_mbcharlen_cp932, check_mb_cp932},
{ 97, "eucjpms", "eucjpms_japanese_ci", 1, 3, "", cppconn_mbcharlen_eucjpms, check_mb_eucjpms},
{ 2, "latin2", "latin2_czech_cs", 1, 1, "", NULL, NULL},
{ 5, "latin1", "latin1_german_ci", 1, 1, "", NULL, NULL},
{ 14, "cp1251", "cp1251_bulgarian_ci", 1, 1, "", NULL, NULL},
{ 15, "latin1", "latin1_danish_ci", 1, 1, "", NULL, NULL},
{ 17, "filename", "filename", 1, 5, "", NULL, NULL},
{ 20, "latin7", "latin7_estonian_cs", 1, 1, "", NULL, NULL},
{ 21, "latin2", "latin2_hungarian_ci", 1, 1, "", NULL, NULL},
{ 23, "cp1251", "cp1251_ukrainian_ci", 1, 1, "", NULL, NULL},
{ 27, "latin2", "latin2_croatian_ci", 1, 1, "", NULL, NULL},
{ 29, "cp1257", "cp1257_lithunian_ci", 1, 1, "", NULL, NULL},
{ 31, "latin1", "latin1_german2_ci", 1, 1, "", NULL, NULL},
{ 34, "cp1250", "cp1250_czech_cs", 1, 1, "", NULL, NULL},
{ 42, "latin7", "latin7_general_cs", 1, 1, "", NULL, NULL},
{ 43, "macce", "macce_bin", 1, 1, "", NULL, NULL},
{ 44, "cp1250", "cp1250_croatian_ci", 1, 1, "", NULL, NULL},
{ 47, "latin1", "latin1_bin", 1, 1, "", NULL, NULL},
{ 48, "latin1", "latin1_general_ci", 1, 1, "", NULL, NULL},
{ 49, "latin1", "latin1_general_cs", 1, 1, "", NULL, NULL},
{ 50, "cp1251", "cp1251_bin", 1, 1, "", NULL, NULL},
{ 52, "cp1251", "cp1251_general_cs", 1, 1, "", NULL, NULL},
{ 53, "macroman", "macroman_bin", 1, 1, "", NULL, NULL},
{ 58, "cp1257", "cp1257_bin", 1, 1, "", NULL, NULL},
{ 60, "armascii8", "armascii8_bin", 1, 1, "", NULL, NULL},
{ 65, "ascii", "ascii_bin", 1, 1, "", NULL, NULL},
{ 66, "cp1250", "cp1250_bin", 1, 1, "", NULL, NULL},
{ 67, "cp1256", "cp1256_bin", 1, 1, "", NULL, NULL},
{ 68, "cp866", "cp866_bin", 1, 1, "", NULL, NULL},
{ 69, "dec8", "dec8_bin", 1, 1, "", NULL, NULL},
{ 70, "greek", "greek_bin", 1, 1, "", NULL, NULL},
{ 71, "hebrew", "hebrew_bin", 1, 1, "", NULL, NULL},
{ 72, "hp8", "hp8_bin", 1, 1, "", NULL, NULL},
{ 73, "keybcs2", "keybcs2_bin", 1, 1, "", NULL, NULL},
{ 74, "koi8r", "koi8r_bin", 1, 1, "", NULL, NULL},
{ 75, "koi8u", "koi8u_bin", 1, 1, "", NULL, NULL},
{ 77, "latin2", "latin2_bin", 1, 1, "", NULL, NULL},
{ 78, "latin5", "latin5_bin", 1, 1, "", NULL, NULL},
{ 79, "latin7", "latin7_bin", 1, 1, "", NULL, NULL},
{ 80, "cp850", "cp850_bin", 1, 1, "", NULL, NULL},
{ 81, "cp852", "cp852_bin", 1, 1, "", NULL, NULL},
{ 82, "swe7", "swe7_bin", 1, 1, "", NULL, NULL},
{ 93, "geostd8", "geostd8_bin", 1, 1, "", NULL, NULL},
{ 83, "utf8", "utf8_bin", 1, 3, "UTF-8 Unicode", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 84, "big5", "big5_bin", 1, 2, "", cppconn_mbcharlen_big5, check_mb_big5},
{ 85, "euckr", "euckr_bin", 1, 2, "", cppconn_mbcharlen_euckr, check_mb_euckr},
{ 86, "gb2312", "gb2312_bin", 1, 2, "", cppconn_mbcharlen_gb2312, check_mb_gb2312},
{ 87, "gbk", "gbk_bin", 1, 2, "", cppconn_mbcharlen_gbk, check_mb_gbk},
{ 88, "sjis", "sjis_bin", 1, 2, "", cppconn_mbcharlen_sjis, check_mb_sjis},
{ 89, "tis620", "tis620_bin", 1, 1, "", NULL, NULL},
{ 90, "ucs2", "ucs2_bin", 2, 2, "UCS-2 Unicode", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 91, "ujis", "ujis_bin", 1, 3, "", cppconn_mbcharlen_ujis, check_mb_ujis},
{ 94, "latin1", "latin1_spanish_ci", 1, 1, "", NULL, NULL},
{ 96, "cp932", "cp932_bin", 1, 2, "", cppconn_mbcharlen_cp932, check_mb_cp932},
{ 99, "cp1250", "cp1250_polish_ci", 1, 1, "", NULL, NULL},
{ 98, "eucjpms", "eucjpms_bin", 1, 3, "", cppconn_mbcharlen_eucjpms, check_mb_eucjpms},
{ 128, "ucs2", "ucs2_unicode_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 129, "ucs2", "ucs2_icelandic_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 130, "ucs2", "ucs2_latvian_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 131, "ucs2", "ucs2_romanian_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 132, "ucs2", "ucs2_slovenian_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 133, "ucs2", "ucs2_polish_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 134, "ucs2", "ucs2_estonian_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 135, "ucs2", "ucs2_spanish_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 136, "ucs2", "ucs2_swedish_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 137, "ucs2", "ucs2_turkish_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 138, "ucs2", "ucs2_czech_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 139, "ucs2", "ucs2_danish_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 140, "ucs2", "ucs2_lithunian_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 141, "ucs2", "ucs2_slovak_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 142, "ucs2", "ucs2_spanish2_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 143, "ucs2", "ucs2_roman_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 144, "ucs2", "ucs2_persian_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 145, "ucs2", "ucs2_esperanto_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 146, "ucs2", "ucs2_hungarian_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 147, "ucs2", "ucs2_sinhala_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 148, "ucs2", "ucs2_german2_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 149, "ucs2", "ucs2_croatian_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 150, "ucs2", "ucs2_unicode_520_ci", 2, 2, "", cppconn_mbcharlen_ucs2, check_mb_ucs2},
{ 192, "utf8", "utf8_unicode_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 193, "utf8", "utf8_icelandic_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 194, "utf8", "utf8_latvian_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 195, "utf8", "utf8_romanian_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 196, "utf8", "utf8_slovenian_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 197, "utf8", "utf8_polish_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 198, "utf8", "utf8_estonian_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 199, "utf8", "utf8_spanish_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 200, "utf8", "utf8_swedish_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 201, "utf8", "utf8_turkish_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 202, "utf8", "utf8_czech_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 203, "utf8", "utf8_danish_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid },
{ 204, "utf8", "utf8_lithunian_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid },
{ 205, "utf8", "utf8_slovak_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 206, "utf8", "utf8_spanish2_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 207, "utf8", "utf8_roman_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 208, "utf8", "utf8_persian_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 209, "utf8", "utf8_esperanto_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 210, "utf8", "utf8_hungarian_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 211, "utf8", "utf8_sinhala_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 212, "utf8", "utf8_german2_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 213, "utf8", "utf8_croatian_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 214, "utf8", "utf8_unicode_520_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 215, "utf8", "utf8_vietnamese_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 223, "utf8", "utf8_general_mysql500_ci", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 45, "utf8mb4", "utf8mb4_general_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 46, "utf8mb4", "utf8mb4_bin", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 224, "utf8mb4", "utf8mb4_unicode_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 225, "utf8mb4", "utf8mb4_icelandic_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 226, "utf8mb4", "utf8mb4_latvian_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 227, "utf8mb4", "utf8mb4_romanian_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 228, "utf8mb4", "utf8mb4_slovenian_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 229, "utf8mb4", "utf8mb4_polish_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 230, "utf8mb4", "utf8mb4_estonian_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 231, "utf8mb4", "utf8mb4_spanish_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 232, "utf8mb4", "utf8mb4_swedish_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 233, "utf8mb4", "utf8mb4_turkish_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 234, "utf8mb4", "utf8mb4_czech_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 235, "utf8mb4", "utf8mb4_danish_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 236, "utf8mb4", "utf8mb4_lithuanian_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 237, "utf8mb4", "utf8mb4_slovak_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 238, "utf8mb4", "utf8mb4_spanish2_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 239, "utf8mb4", "utf8mb4_roman_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 240, "utf8mb4", "utf8mb4_persian_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 241, "utf8mb4", "utf8mb4_esperanto_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 242, "utf8mb4", "utf8mb4_hungarian_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 243, "utf8mb4", "utf8mb4_sinhala_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 244, "utf8mb4", "utf8mb4_german2_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 245, "utf8mb4", "utf8mb4_croatian_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 246, "utf8mb4", "utf8mb4_unicode_520_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
{ 247, "utf8mb4", "utf8mb4_vietnamese_ci", 1, 4, "", cppconn_mbcharlen_utf8mb4, check_mb_utf8mb4_valid},
/*Should not really happen, but adding them */
{ 254, "utf8", "utf8_general_cs", 1, 3, "", cppconn_mbcharlen_utf8, check_mb_utf8_valid},
{ 101, "utf16", "utf16_unicode_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 102, "utf16", "utf16_icelandic_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 103, "utf16", "utf16_latvian_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 104, "utf16", "utf16_romanian_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 105, "utf16", "utf16_slovenian_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 106, "utf16", "utf16_polish_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 107, "utf16", "utf16_estonian_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 108, "utf16", "utf16_spanish_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 109, "utf16", "utf16_swedish_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 110, "utf16", "utf16_turkish_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 111, "utf16", "utf16_czech_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 112, "utf16", "utf16_danish_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 113, "utf16", "utf16_lithuanian_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 114, "utf16", "utf16_slovak_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 115, "utf16", "utf16_spanish2_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 116, "utf16", "utf16_roman_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 117, "utf16", "utf16_persian_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 118, "utf16", "utf16_esperanto_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 119, "utf16", "utf16_hungarian_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 120, "utf16", "utf16_sinhala_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 121, "utf16", "utf16_german2_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 122, "utf16", "utf16_croatian_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 123, "utf16", "utf16_unicode_520_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 124, "utf16", "utf16_vietnamese_ci", 2, 4, "", cppconn_mbcharlen_utf16, check_mb_utf16_valid},
{ 160, "utf32", "utf32_unicode_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 161, "utf32", "utf32_icelandic_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 162, "utf32", "utf32_latvian_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 163, "utf32", "utf32_romanian_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 164, "utf32", "utf32_slovenian_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 165, "utf32", "utf32_polish_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 166, "utf32", "utf32_estonian_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 167, "utf32", "utf32_spanish_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 168, "utf32", "utf32_swedish_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 169, "utf32", "utf32_turkish_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 170, "utf32", "utf32_czech_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 171, "utf32", "utf32_danish_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 172, "utf32", "utf32_lithuanian_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 173, "utf32", "utf32_slovak_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 174, "utf32", "utf32_spanish2_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 175, "utf32", "utf32_roman_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 176, "utf32", "utf32_persian_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 177, "utf32", "utf32_esperanto_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 178, "utf32", "utf32_hungarian_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 179, "utf32", "utf32_sinhala_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 180, "utf32", "utf32_german2_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 181, "utf32", "utf32_croatian_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 182, "utf32", "utf32_unicode_520_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 183, "utf32", "utf32_vietnamese_ci", 4, 4, "", cppconn_mbcharlen_utf32, check_mb_utf32_valid},
{ 0, NULL, NULL, 0, 0, NULL, NULL, NULL}
};
#define MAGIC_BINARY_CHARSET_NR 63
const Mysql::Util::OUR_CHARSET* Mysql::Util::find_charset(unsigned int charsetnr)
{
const OUR_CHARSET * c = our_charsets60;
do {
if (c->nr == charsetnr) {
return c;
}
++c;
} while (c[0].nr != 0);
return NULL;
}
int Mysql::Util::mysql_type_to_datatype( const MYSQL_FIELD* const field )
{
switch( field->type )
{
case MYSQL_TYPE_BIT:
if( field->flags != ( BINARY_FLAG|UNSIGNED_FLAG ) )
return Mysql::DataType::BIT;
return Mysql::DataType::BINARY;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_NEWDECIMAL:
return Mysql::DataType::DECIMAL;
case MYSQL_TYPE_TINY:
return Mysql::DataType::TINYINT;
case MYSQL_TYPE_SHORT:
return Mysql::DataType::SMALLINT;
case MYSQL_TYPE_INT24:
return Mysql::DataType::MEDIUMINT;
case MYSQL_TYPE_LONG:
return Mysql::DataType::INTEGER;
case MYSQL_TYPE_LONGLONG:
return Mysql::DataType::BIGINT;
case MYSQL_TYPE_FLOAT:
return Mysql::DataType::REAL;
case MYSQL_TYPE_DOUBLE:
return Mysql::DataType::DOUBLE;
case MYSQL_TYPE_NULL:
return Mysql::DataType::SQLNULL;
case MYSQL_TYPE_TIMESTAMP:
return Mysql::DataType::TIMESTAMP;
case MYSQL_TYPE_DATE:
return Mysql::DataType::DATE;
case MYSQL_TYPE_TIME:
return Mysql::DataType::TIME;
case MYSQL_TYPE_YEAR:
return Mysql::DataType::YEAR;
case MYSQL_TYPE_DATETIME:
return Mysql::DataType::TIMESTAMP;
case MYSQL_TYPE_TINY_BLOB:// should no appear over the wire
{
bool isBinary = ( field->flags & BINARY_FLAG ) &&
field->charsetnr == MAGIC_BINARY_CHARSET_NR;
const Mysql::Util::OUR_CHARSET * const cs =
Mysql::Util::find_charset(field->charsetnr);
if (!cs) {
std::ostringstream msg("Server sent unknown charsetnr (");
msg << field->charsetnr << ") . Please report";
throw std::runtime_error( msg.str() );
}
return isBinary ? Mysql::DataType::VARBINARY : Mysql::DataType::VARCHAR;
}
case MYSQL_TYPE_MEDIUM_BLOB:// should no appear over the wire
case MYSQL_TYPE_LONG_BLOB:// should no appear over the wire
case MYSQL_TYPE_BLOB:
{
bool isBinary = ( field->flags & BINARY_FLAG ) &&
field->charsetnr == MAGIC_BINARY_CHARSET_NR;
const Mysql::Util::OUR_CHARSET * const cs =
Mysql::Util::find_charset( field->charsetnr );
if( !cs )
{
std::ostringstream msg("Server sent unknown charsetnr (");
msg << field->charsetnr << ") . Please report";
throw std::runtime_error( msg.str() );
}
return isBinary ? Mysql::DataType::LONGVARBINARY : Mysql::DataType::LONGVARCHAR;
}
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
if( field->flags & SET_FLAG )
{
return Mysql::DataType::SET;
}
if( field->flags & ENUM_FLAG )
{
return Mysql::DataType::ENUM;
}
if( ( field->flags & BINARY_FLAG ) && field->charsetnr == MAGIC_BINARY_CHARSET_NR )
{
return Mysql::DataType::VARBINARY;
}
return Mysql::DataType::VARCHAR;
case MYSQL_TYPE_STRING:
if( field->flags & SET_FLAG )
{
return Mysql::DataType::SET;
}
if( field->flags & ENUM_FLAG )
{
return Mysql::DataType::ENUM;
}
if( ( field->flags & BINARY_FLAG ) && field->charsetnr == MAGIC_BINARY_CHARSET_NR )
{
return Mysql::DataType::BINARY;
}
return Mysql::DataType::CHAR;
case MYSQL_TYPE_ENUM:
/* This hould never happen - MYSQL_TYPE_ENUM is not sent over the wire, just used in the server */
return Mysql::DataType::ENUM;
case MYSQL_TYPE_SET:
/* This hould never happen - MYSQL_TYPE_SET is not sent over the wire, just used in the server */
return Mysql::DataType::SET;
case MYSQL_TYPE_GEOMETRY:
return Mysql::DataType::GEOMETRY;
#if LIBMYSQL_VERSION_ID > 50700
case MYSQL_TYPE_JSON:
return Mysql::DataType::JSON;
#endif //LIBMYSQL_VERSION_ID > 50700
default:
return Mysql::DataType::UNKNOWN;
}
}

117
deps/mysqlConnector/mysql_util.h vendored Normal file
View file

@ -0,0 +1,117 @@
/*
Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/C++ is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
MySQL Connectors. There are special exceptions to the terms and
conditions of the GPLv2 as it is applied to this software, see the
FLOSS License Exception
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SAPPHIRE_MYSQL_UTIL_H
#define SAPPHIRE_MYSQL_UTIL_H
#include <iostream>
#include <sstream>
typedef struct st_mysql_field MYSQL_FIELD;
#ifndef UL64
#ifdef _WIN32
#define UL64(x) x##ui64
#else
#define UL64(x) x##ULL
#endif
#endif
#ifndef L64
#ifdef _WIN32
#define L64(x) x##i64
#else
#define L64(x) x##LL
#endif
#endif
#define NULLCSTR static_cast<char *>(0)
#define bit_uint1korr(A) (*(((uint8_t*)(A))))
#define bit_uint2korr(A) ((uint16_t) (((uint16_t) (((unsigned char*) (A))[1])) +\
((uint16_t) (((unsigned char*) (A))[0]) << 8)))
#define bit_uint3korr(A) ((uint32_t) (((uint32_t) (((unsigned char*) (A))[2])) +\
(((uint32_t) (((unsigned char*) (A))[1])) << 8) +\
(((uint32_t) (((unsigned char*) (A))[0])) << 16)))
#define bit_uint4korr(A) ((uint32_t) (((uint32_t) (((unsigned char*) (A))[3])) +\
(((uint32_t) (((unsigned char*) (A))[2])) << 8) +\
(((uint32_t) (((unsigned char*) (A))[1])) << 16) +\
(((uint32_t) (((unsigned char*) (A))[0])) << 24)))
#define bit_uint5korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[4])) +\
(((uint32_t) (((unsigned char*) (A))[3])) << 8) +\
(((uint32_t) (((unsigned char*) (A))[2])) << 16) +\
(((uint32_t) (((unsigned char*) (A))[1])) << 24)) +\
(((uint64_t) (((unsigned char*) (A))[0])) << 32))
#define bit_uint6korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[5])) +\
(((uint32_t) (((unsigned char*) (A))[4])) << 8) +\
(((uint32_t) (((unsigned char*) (A))[3])) << 16) +\
(((uint32_t) (((unsigned char*) (A))[2])) << 24)) +\
(((uint64_t) (((uint32_t) (((unsigned char*) (A))[1])) +\
(((uint32_t) (((unsigned char*) (A))[0]) << 8)))) <<\
32))
#define bit_uint7korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[6])) +\
(((uint32_t) (((unsigned char*) (A))[5])) << 8) +\
(((uint32_t) (((unsigned char*) (A))[4])) << 16) +\
(((uint32_t) (((unsigned char*) (A))[3])) << 24)) +\
(((uint64_t) (((uint32_t) (((unsigned char*) (A))[2])) +\
(((uint32_t) (((unsigned char*) (A))[1])) << 8) +\
(((uint32_t) (((unsigned char*) (A))[0])) << 16))) <<\
32))
#define bit_uint8korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[7])) +\
(((uint32_t) (((unsigned char*) (A))[6])) << 8) +\
(((uint32_t) (((unsigned char*) (A))[5])) << 16) +\
(((uint32_t) (((unsigned char*) (A))[4])) << 24)) +\
(((uint64_t) (((uint32_t) (((unsigned char*) (A))[3])) +\
(((uint32_t) (((unsigned char*) (A))[2])) << 8) +\
(((uint32_t) (((unsigned char*) (A))[1])) << 16) +\
(((uint32_t) (((unsigned char*) (A))[0])) << 24))) <<\
32))
namespace Mysql
{
namespace Util
{
long double strtold( const char *nptr, char **endptr );
long double strtonum( const std::string &str, int radix = 10 );
int64_t strtoll( const char* nptr, char** endptr );
uint64_t strtoull( const char* nptr, char** endptr );
int32_t mysql_type_to_datatype( const MYSQL_FIELD * const field );
typedef struct st_our_charset
{
unsigned int nr;
const char *name;
const char *collation;
unsigned int char_minlen;
unsigned int char_maxlen;
const char *comment;
unsigned int (*mb_charlen)(unsigned int c);
unsigned int (*mb_valid)(const char *start, const char *end);
} OUR_CHARSET;
const OUR_CHARSET * find_charset(unsigned int charsetnr);
}
}
#endif //SAPPHIRE_MYSQL_UTIL_H

19430
deps/nlohmann/json.hpp vendored Normal file

File diff suppressed because it is too large Load diff

1
deps/spdlog vendored Submodule

@ -0,0 +1 @@
Subproject commit 240a58fd6e8bfe8fa62dd3ea777d1909f6d89a72

323
deps/watchdog/Watchdog.h vendored Normal file
View file

@ -0,0 +1,323 @@
/*
Watchdog
Copyright (c) 2014, Simon Geilfus
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that
the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <map>
#include <string>
#include <thread>
#include <memory>
#include <atomic>
#include <mutex>
#include <functional>
#include <experimental/filesystem>
namespace ci { namespace fs = std::experimental::filesystem; }
//! Exception for when Watchdog can't locate a file or parse the wildcard
class WatchedFileSystemExc : public std::exception {
public:
WatchedFileSystemExc( const ci::fs::path &path )
{
m_message = "Failed to find the file or directory at: " + path.string();
}
virtual const char* what() const throw() { return m_message.c_str(); }
std::string m_message;
};
//! Watchdog class.
class Watchdog {
public:
//! Watches a file or directory for modification and call back the specified std::function. The path specified is passed as argument of the callback even if there is multiple files. Use the second watch method if you want to receive a list of all the files that have been modified.
static void watch( const ci::fs::path &path, const std::function<void(const ci::fs::path&)> &callback )
{
watchImpl( path, callback, std::function<void(const std::vector<ci::fs::path>&)>() );
}
//! Watches a file or directory for modification and call back the specified std::function. A list of modified files or directory is passed as argument of the callback. Use this version only if you are watching multiple files or a directory.
static void watchMany( const ci::fs::path &path, const std::function<void(const std::vector<ci::fs::path>&)> &callback )
{
watchImpl( path, std::function<void(const ci::fs::path&)>(), callback );
}
//! Unwatches a previously registrated file or directory
static void unwatch( const ci::fs::path &path )
{
watchImpl( path );
}
//! Unwatches all previously registrated file or directory
static void unwatchAll()
{
watchImpl( ci::fs::path() );
}
//! Sets the last modification time of a file or directory. by default sets the time to the current time
static void touch( const ci::fs::path &path, ci::fs::file_time_type time = ci::fs::file_time_type::clock::now() )
{
// if the file or directory exists change its last write time
if( ci::fs::exists( path ) ){
ci::fs::last_write_time( path, time );
return;
}
// if not, visit each path if there's a wildcard
if( path.string().find( "*" ) != std::string::npos ){
visitWildCardPath( path, [time]( const ci::fs::path &p ){
ci::fs::last_write_time( p, time );
return false;
} );
}
// otherwise throw an exception
else {
throw WatchedFileSystemExc( path );
}
}
protected:
Watchdog()
: mWatching(false)
{
}
void close()
{
// remove all watchers
unwatchAll();
// stop the thread
mWatching = false;
if( mThread->joinable() ) mThread->join();
}
void start()
{
mWatching = true;
mThread = std::unique_ptr<std::thread>( new std::thread( [this](){
// keep watching for modifications every ms milliseconds
auto ms = std::chrono::milliseconds( 500 );
while( mWatching ) {
do {
// iterate through each watcher and check for modification
std::lock_guard<std::mutex> lock( mMutex );
auto end = mFileWatchers.end();
for( auto it = mFileWatchers.begin(); it != end; ++it ) {
it->second.watch();
}
// lock will be released before this thread goes to sleep
} while( false );
// make this thread sleep for a while
std::this_thread::sleep_for( ms );
}
} ) );
}
static void watchImpl( const ci::fs::path &path, const std::function<void(const ci::fs::path&)> &callback = std::function<void(const ci::fs::path&)>(), const std::function<void(const std::vector<ci::fs::path>&)> &listCallback = std::function<void(const std::vector<ci::fs::path>&)>() )
{
// create the static Watchdog instance
static Watchdog wd;
// and start its thread
if( !wd.mWatching ) {
wd.start();
}
const std::string key = path.string();
// add a new watcher
if( callback || listCallback ){
std::string filter;
ci::fs::path p = path;
// try to see if there's a match for the wildcard
if( path.string().find( "*" ) != std::string::npos ){
bool found = false;
std::pair<ci::fs::path,std::string> pathFilter = visitWildCardPath( path, [&found]( const ci::fs::path &p ){
found = true;
return true;
} );
if( !found ){
throw WatchedFileSystemExc( path );
}
else {
p = pathFilter.first;
filter = pathFilter.second;
}
}
std::lock_guard<std::mutex> lock( wd.mMutex );
if( wd.mFileWatchers.find( key ) == wd.mFileWatchers.end() ){
wd.mFileWatchers.emplace( make_pair( key, Watcher( p, filter, callback, listCallback ) ) );
}
}
// if there is no callback that means that we are unwatching
else {
// if the path is empty we unwatch all files
if( path.empty() ){
std::lock_guard<std::mutex> lock( wd.mMutex );
for( auto it = wd.mFileWatchers.begin(); it != wd.mFileWatchers.end(); ) {
it = wd.mFileWatchers.erase( it );
}
}
// or the specified file or directory
else {
std::lock_guard<std::mutex> lock( wd.mMutex );
auto watcher = wd.mFileWatchers.find( key );
if( watcher != wd.mFileWatchers.end() ){
wd.mFileWatchers.erase( watcher );
}
}
}
}
static std::pair<ci::fs::path,std::string> getPathFilterPair( const ci::fs::path &path )
{
// extract wildcard and parent path
std::string key = path.string();
ci::fs::path p = path;
size_t wildCardPos = key.find( "*" );
std::string filter;
if( wildCardPos != std::string::npos ){
filter = path.filename().string();
p = path.parent_path();
}
// throw an exception if the file doesn't exist
if( filter.empty() && !ci::fs::exists( p ) ){
throw WatchedFileSystemExc( path );
}
return std::make_pair( p, filter );
}
static std::pair<ci::fs::path,std::string> visitWildCardPath( const ci::fs::path &path, const std::function<bool(const ci::fs::path&)> &visitor ){
std::pair<ci::fs::path, std::string> pathFilter = getPathFilterPair( path );
if( !pathFilter.second.empty() ){
std::string full = ( pathFilter.first / pathFilter.second ).string();
size_t wildcardPos = full.find( "*" );
std::string before = full.substr( 0, wildcardPos );
std::string after = full.substr( wildcardPos + 1 );
ci::fs::directory_iterator end;
for( ci::fs::directory_iterator it( pathFilter.first ); it != end; ++it ){
std::string current = it->path().string();
size_t beforePos = current.find( before );
size_t afterPos = current.find( after );
if( ( beforePos != std::string::npos || before.empty() )
&& ( afterPos != std::string::npos || after.empty() ) ) {
if( visitor( it->path() ) ){
break;
}
}
}
}
return pathFilter;
}
class Watcher {
public:
Watcher( const ci::fs::path &path, const std::string &filter, const std::function<void(const ci::fs::path&)> &callback, const std::function<void(const std::vector<ci::fs::path>&)> &listCallback )
: mPath(path), mFilter(filter), mCallback(callback), mListCallback(listCallback)
{
// make sure we store all initial write time
if( !mFilter.empty() ) {
std::vector<ci::fs::path> paths;
visitWildCardPath( path / filter, [this,&paths]( const ci::fs::path &p ){
hasChanged( p );
paths.push_back( p );
return false;
} );
// this means that the first watch won't call the callback function
// so we have to manually call it here
if( mCallback ){
mCallback( mPath / mFilter );
}
else {
mListCallback( paths );
}
}
}
void watch()
{
// if there's no filter we just check for one item
if( mFilter.empty() && hasChanged( mPath ) && mCallback ){
mCallback( mPath );
//#error TODO: still have to figure out an elegant way to do this without cinder
}
// otherwise we check the whole parent directory
else if( !mFilter.empty() ){
std::vector<ci::fs::path> paths;
visitWildCardPath( mPath / mFilter, [this,&paths]( const ci::fs::path &p ){
bool pathHasChanged = hasChanged( p );
if( pathHasChanged && mCallback ){
mCallback( mPath / mFilter );
//#error TODO: still have to figure out an elegant way to do this without cinder
return true;
}
else if( pathHasChanged && mListCallback ){
paths.push_back( p );
}
return false;
} );
if( paths.size() && mListCallback ){
mListCallback( paths );
}
}
}
bool hasChanged( const ci::fs::path &path )
{
// get the last modification time
auto time = ci::fs::last_write_time( path );
// add a new modification time to the map
std::string key = path.string();
if( mModificationTimes.find( key ) == mModificationTimes.end() ) {
mModificationTimes[ key ] = time;
return true;
}
// or compare with an older one
auto &prev = mModificationTimes[ key ];
if( prev < time ) {
prev = time;
return true;
}
return false;
};
protected:
ci::fs::path mPath;
std::string mFilter;
std::function<void(const ci::fs::path&)> mCallback;
std::function<void(const std::vector<ci::fs::path>&)> mListCallback;
std::map< std::string, std::experimental::filesystem::file_time_type > mModificationTimes;
};
std::mutex mMutex;
std::atomic<bool> mWatching;
std::unique_ptr<std::thread> mThread;
std::map<std::string,Watcher> mFileWatchers;
};

50
deps/zlib/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,50 @@
# Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
if(UNIX)
# Look for an installed zlib on unix
find_package(ZLIB REQUIRED)
add_library(zlib SHARED IMPORTED GLOBAL)
set_target_properties(zlib
PROPERTIES
IMPORTED_LOCATION
"${ZLIB_LIBRARIES}"
INTERFACE_INCLUDE_DIRECTORIES
"${ZLIB_INCLUDE_DIRS}")
else()
# Use the bundled source on windows
SET(zlib_STAT_SRCS
adler32.c
compress.c
crc32.c
deflate.c
infback.c
inffast.c
inflate.c
inftrees.c
trees.c
uncompr.c
zutil.c
)
add_library(zlib STATIC
${zlib_STAT_SRCS})
target_include_directories(zlib
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(zlib
PROPERTIES
FOLDER
"deps")
endif()

179
deps/zlib/adler32.c vendored Normal file
View file

@ -0,0 +1,179 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2011 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#include "zutil.h"
#define local static
local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
#define BASE 65521 /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* use NO_DIVIDE if your processor does not do division in hardware --
try it both ways to see which is faster */
#ifdef NO_DIVIDE
/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
(thank you to John Reiser for pointing this out) */
# define CHOP(a) \
do { \
unsigned long tmp = a >> 16; \
a &= 0xffffUL; \
a += (tmp << 4) - tmp; \
} while (0)
# define MOD28(a) \
do { \
CHOP(a); \
if (a >= BASE) a -= BASE; \
} while (0)
# define MOD(a) \
do { \
CHOP(a); \
MOD28(a); \
} while (0)
# define MOD63(a) \
do { /* this assumes a is not negative */ \
z_off64_t tmp = a >> 32; \
a &= 0xffffffffL; \
a += (tmp << 8) - (tmp << 5) + tmp; \
tmp = a >> 16; \
a &= 0xffffL; \
a += (tmp << 4) - tmp; \
tmp = a >> 16; \
a &= 0xffffL; \
a += (tmp << 4) - tmp; \
if (a >= BASE) a -= BASE; \
} while (0)
#else
# define MOD(a) a %= BASE
# define MOD28(a) a %= BASE
# define MOD63(a) a %= BASE
#endif
/* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len)
uLong adler;
const Bytef *buf;
uInt len;
{
unsigned long sum2;
unsigned n;
/* split Adler-32 into component sums */
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
/* in case user likes doing a byte at a time, keep it fast */
if (len == 1) {
adler += buf[0];
if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return adler | (sum2 << 16);
}
/* initial Adler-32 value (deferred check for len == 1 speed) */
if (buf == Z_NULL)
return 1L;
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
while (len--) {
adler += *buf++;
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
MOD28(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */
do {
DO16(buf); /* 16 sums unrolled */
buf += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
while (len >= 16) {
len -= 16;
DO16(buf);
buf += 16;
}
while (len--) {
adler += *buf++;
sum2 += adler;
}
MOD(adler);
MOD(sum2);
}
/* return recombined sums */
return adler | (sum2 << 16);
}
/* ========================================================================= */
local uLong adler32_combine_(adler1, adler2, len2)
uLong adler1;
uLong adler2;
z_off64_t len2;
{
unsigned long sum1;
unsigned long sum2;
unsigned rem;
/* for negative len, return invalid adler32 as a clue for debugging */
if (len2 < 0)
return 0xffffffffUL;
/* the derivation of this formula is left as an exercise for the reader */
MOD63(len2); /* assumes len2 >= 0 */
rem = (unsigned)len2;
sum1 = adler1 & 0xffff;
sum2 = rem * sum1;
MOD(sum2);
sum1 += (adler2 & 0xffff) + BASE - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if (sum1 >= BASE) sum1 -= BASE;
if (sum1 >= BASE) sum1 -= BASE;
if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
if (sum2 >= BASE) sum2 -= BASE;
return sum1 | (sum2 << 16);
}
/* ========================================================================= */
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
uLong adler1;
uLong adler2;
z_off_t len2;
{
return adler32_combine_(adler1, adler2, len2);
}
uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
uLong adler1;
uLong adler2;
z_off64_t len2;
{
return adler32_combine_(adler1, adler2, len2);
}

80
deps/zlib/compress.c vendored Normal file
View file

@ -0,0 +1,80 @@
/* compress.c -- compress a memory buffer
* Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#define ZLIB_INTERNAL
#include "zlib.h"
/* ===========================================================================
Compresses the source buffer into the destination buffer. The level
parameter has the same meaning as in deflateInit. sourceLen is the byte
length of the source buffer. Upon entry, destLen is the total size of the
destination buffer, which must be at least 0.1% larger than sourceLen plus
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
Z_STREAM_ERROR if the level parameter is invalid.
*/
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
int level;
{
z_stream stream;
int err;
stream.next_in = (z_const Bytef *)source;
stream.avail_in = (uInt)sourceLen;
#ifdef MAXSEG_64K
/* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
#endif
stream.next_out = dest;
stream.avail_out = (uInt)*destLen;
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
err = deflateInit(&stream, level);
if (err != Z_OK) return err;
err = deflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
deflateEnd(&stream);
return err == Z_OK ? Z_BUF_ERROR : err;
}
*destLen = stream.total_out;
err = deflateEnd(&stream);
return err;
}
/* ===========================================================================
*/
int ZEXPORT compress (dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
{
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
}
/* ===========================================================================
If the default memLevel or windowBits for deflateInit() is changed, then
this function needs to be updated.
*/
uLong ZEXPORT compressBound (sourceLen)
uLong sourceLen;
{
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
(sourceLen >> 25) + 13;
}

425
deps/zlib/crc32.c vendored Normal file
View file

@ -0,0 +1,425 @@
/* crc32.c -- compute the CRC-32 of a data stream
* Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
* tables for updating the shift register in one step with three exclusive-ors
* instead of four steps with four exclusive-ors. This results in about a
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
*/
/* @(#) $Id$ */
/*
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
protection on the static variables used to control the first-use generation
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
first call get_crc_table() to initialize the tables before allowing more than
one thread to use crc32().
DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
*/
#ifdef MAKECRCH
# include <stdio.h>
# ifndef DYNAMIC_CRC_TABLE
# define DYNAMIC_CRC_TABLE
# endif /* !DYNAMIC_CRC_TABLE */
#endif /* MAKECRCH */
#include "zutil.h" /* for STDC and FAR definitions */
#define local static
/* Definitions for doing the crc four data bytes at a time. */
#if !defined(NOBYFOUR) && defined(Z_U4)
# define BYFOUR
#endif
#ifdef BYFOUR
local unsigned long crc32_little OF((unsigned long,
const unsigned char FAR *, unsigned));
local unsigned long crc32_big OF((unsigned long,
const unsigned char FAR *, unsigned));
# define TBLS 8
#else
# define TBLS 1
#endif /* BYFOUR */
/* Local functions for crc concatenation */
local unsigned long gf2_matrix_times OF((unsigned long *mat,
unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
#ifdef DYNAMIC_CRC_TABLE
local volatile int crc_table_empty = 1;
local z_crc_t FAR crc_table[TBLS][256];
local void make_crc_table OF((void));
#ifdef MAKECRCH
local void write_table OF((FILE *, const z_crc_t FAR *));
#endif /* MAKECRCH */
/*
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
Polynomials over GF(2) are represented in binary, one bit per coefficient,
with the lowest powers in the most significant bit. Then adding polynomials
is just exclusive-or, and multiplying a polynomial by x is a right shift by
one. If we call the above polynomial p, and represent a byte as the
polynomial q, also with the lowest power in the most significant bit (so the
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
where a mod b means the remainder after dividing a by b.
This calculation is done using the shift-register method of multiplying and
taking the remainder. The register is initialized to zero, and for each
incoming bit, x^32 is added mod p to the register if the bit is a one (where
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
x (which is shifting right by one and adding x^32 mod p if the bit shifted
out is a one). We start with the highest power (least significant bit) of
q and repeat for all eight bits of q.
The first table is simply the CRC of all possible eight bit values. This is
all the information needed to generate CRCs on data a byte at a time for all
combinations of CRC register values and incoming bytes. The remaining tables
allow for word-at-a-time CRC calculation for both big-endian and little-
endian machines, where a word is four bytes.
*/
local void make_crc_table()
{
z_crc_t c;
int n, k;
z_crc_t poly; /* polynomial exclusive-or pattern */
/* terms of polynomial defining this crc (except x^32): */
static volatile int first = 1; /* flag to limit concurrent making */
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
/* See if another task is already doing this (not thread-safe, but better
than nothing -- significantly reduces duration of vulnerability in
case the advice about DYNAMIC_CRC_TABLE is ignored) */
if (first) {
first = 0;
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
poly = 0;
for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
poly |= (z_crc_t)1 << (31 - p[n]);
/* generate a crc for every 8-bit value */
for (n = 0; n < 256; n++) {
c = (z_crc_t)n;
for (k = 0; k < 8; k++)
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
crc_table[0][n] = c;
}
#ifdef BYFOUR
/* generate crc for each value followed by one, two, and three zeros,
and then the byte reversal of those as well as the first table */
for (n = 0; n < 256; n++) {
c = crc_table[0][n];
crc_table[4][n] = ZSWAP32(c);
for (k = 1; k < 4; k++) {
c = crc_table[0][c & 0xff] ^ (c >> 8);
crc_table[k][n] = c;
crc_table[k + 4][n] = ZSWAP32(c);
}
}
#endif /* BYFOUR */
crc_table_empty = 0;
}
else { /* not first */
/* wait for the other guy to finish (not efficient, but rare) */
while (crc_table_empty)
;
}
#ifdef MAKECRCH
/* write out CRC tables to crc32.h */
{
FILE *out;
out = fopen("crc32.h", "w");
if (out == NULL) return;
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
fprintf(out, "local const z_crc_t FAR ");
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
write_table(out, crc_table[0]);
# ifdef BYFOUR
fprintf(out, "#ifdef BYFOUR\n");
for (k = 1; k < 8; k++) {
fprintf(out, " },\n {\n");
write_table(out, crc_table[k]);
}
fprintf(out, "#endif\n");
# endif /* BYFOUR */
fprintf(out, " }\n};\n");
fclose(out);
}
#endif /* MAKECRCH */
}
#ifdef MAKECRCH
local void write_table(out, table)
FILE *out;
const z_crc_t FAR *table;
{
int n;
for (n = 0; n < 256; n++)
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
(unsigned long)(table[n]),
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
}
#endif /* MAKECRCH */
#else /* !DYNAMIC_CRC_TABLE */
/* ========================================================================
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
*/
#include "crc32.h"
#endif /* DYNAMIC_CRC_TABLE */
/* =========================================================================
* This function can be used by asm versions of crc32()
*/
const z_crc_t FAR * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
return (const z_crc_t FAR *)crc_table;
}
/* ========================================================================= */
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
/* ========================================================================= */
unsigned long ZEXPORT crc32(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
uInt len;
{
if (buf == Z_NULL) return 0UL;
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
#ifdef BYFOUR
if (sizeof(void *) == sizeof(ptrdiff_t)) {
z_crc_t endian;
endian = 1;
if (*((unsigned char *)(&endian)))
return crc32_little(crc, buf, len);
else
return crc32_big(crc, buf, len);
}
#endif /* BYFOUR */
crc = crc ^ 0xffffffffUL;
while (len >= 8) {
DO8;
len -= 8;
}
if (len) do {
DO1;
} while (--len);
return crc ^ 0xffffffffUL;
}
#ifdef BYFOUR
/* ========================================================================= */
#define DOLIT4 c ^= *buf4++; \
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
/* ========================================================================= */
local unsigned long crc32_little(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
register z_crc_t c;
register const z_crc_t FAR *buf4;
c = (z_crc_t)crc;
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
len--;
}
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
while (len >= 32) {
DOLIT32;
len -= 32;
}
while (len >= 4) {
DOLIT4;
len -= 4;
}
buf = (const unsigned char FAR *)buf4;
if (len) do {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
} while (--len);
c = ~c;
return (unsigned long)c;
}
/* ========================================================================= */
#define DOBIG4 c ^= *++buf4; \
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
/* ========================================================================= */
local unsigned long crc32_big(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
register z_crc_t c;
register const z_crc_t FAR *buf4;
c = ZSWAP32((z_crc_t)crc);
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
len--;
}
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
buf4--;
while (len >= 32) {
DOBIG32;
len -= 32;
}
while (len >= 4) {
DOBIG4;
len -= 4;
}
buf4++;
buf = (const unsigned char FAR *)buf4;
if (len) do {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
} while (--len);
c = ~c;
return (unsigned long)(ZSWAP32(c));
}
#endif /* BYFOUR */
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
/* ========================================================================= */
local unsigned long gf2_matrix_times(mat, vec)
unsigned long *mat;
unsigned long vec;
{
unsigned long sum;
sum = 0;
while (vec) {
if (vec & 1)
sum ^= *mat;
vec >>= 1;
mat++;
}
return sum;
}
/* ========================================================================= */
local void gf2_matrix_square(square, mat)
unsigned long *square;
unsigned long *mat;
{
int n;
for (n = 0; n < GF2_DIM; n++)
square[n] = gf2_matrix_times(mat, mat[n]);
}
/* ========================================================================= */
local uLong crc32_combine_(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off64_t len2;
{
int n;
unsigned long row;
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
/* degenerate case (also disallow negative lengths) */
if (len2 <= 0)
return crc1;
/* put operator for one zero bit in odd */
odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
row = 1;
for (n = 1; n < GF2_DIM; n++) {
odd[n] = row;
row <<= 1;
}
/* put operator for two zero bits in even */
gf2_matrix_square(even, odd);
/* put operator for four zero bits in odd */
gf2_matrix_square(odd, even);
/* apply len2 zeros to crc1 (first square will put the operator for one
zero byte, eight zero bits, in even) */
do {
/* apply zeros operator for this bit of len2 */
gf2_matrix_square(even, odd);
if (len2 & 1)
crc1 = gf2_matrix_times(even, crc1);
len2 >>= 1;
/* if no more bits set, then done */
if (len2 == 0)
break;
/* another iteration of the loop with odd and even swapped */
gf2_matrix_square(odd, even);
if (len2 & 1)
crc1 = gf2_matrix_times(odd, crc1);
len2 >>= 1;
/* if no more bits set, then done */
} while (len2 != 0);
/* return combined crc */
crc1 ^= crc2;
return crc1;
}
/* ========================================================================= */
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off_t len2;
{
return crc32_combine_(crc1, crc2, len2);
}
uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off64_t len2;
{
return crc32_combine_(crc1, crc2, len2);
}

441
deps/zlib/crc32.h vendored Normal file
View file

@ -0,0 +1,441 @@
/* crc32.h -- tables for rapid CRC calculation
* Generated automatically by crc32.c
*/
local const z_crc_t FAR crc_table[TBLS][256] =
{
{
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
0x2d02ef8dUL
#ifdef BYFOUR
},
{
0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
0x9324fd72UL
},
{
0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
0xbe9834edUL
},
{
0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
0xde0506f1UL
},
{
0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
0x8def022dUL
},
{
0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
0x72fd2493UL
},
{
0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
0xed3498beUL
},
{
0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
0xf10605deUL
#endif
}
};

1967
deps/zlib/deflate.c vendored Normal file

File diff suppressed because it is too large Load diff

346
deps/zlib/deflate.h vendored Normal file
View file

@ -0,0 +1,346 @@
/* deflate.h -- internal compression state
* Copyright (C) 1995-2012 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id$ */
#ifndef DEFLATE_H
#define DEFLATE_H
#include "zutil.h"
/* define NO_GZIP when compiling if you want to disable gzip header and
trailer creation by deflate(). NO_GZIP would be used to avoid linking in
the crc code when it is not needed. For shared libraries, gzip encoding
should be left enabled. */
#ifndef NO_GZIP
# define GZIP
#endif
/* ===========================================================================
* Internal compression state.
*/
#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */
#define LITERALS 256
/* number of literal bytes 0..255 */
#define L_CODES (LITERALS+1+LENGTH_CODES)
/* number of Literal or Length codes, including the END_BLOCK code */
#define D_CODES 30
/* number of distance codes */
#define BL_CODES 19
/* number of codes used to transfer the bit lengths */
#define HEAP_SIZE (2*L_CODES+1)
/* maximum heap size */
#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */
#define Buf_size 16
/* size of bit buffer in bi_buf */
#define INIT_STATE 42
#define EXTRA_STATE 69
#define NAME_STATE 73
#define COMMENT_STATE 91
#define HCRC_STATE 103
#define BUSY_STATE 113
#define FINISH_STATE 666
/* Stream status */
/* Data structure describing a single value and its code string. */
typedef struct ct_data_s {
union {
ush freq; /* frequency count */
ush code; /* bit string */
} fc;
union {
ush dad; /* father node in Huffman tree */
ush len; /* length of bit string */
} dl;
} FAR ct_data;
#define Freq fc.freq
#define Code fc.code
#define Dad dl.dad
#define Len dl.len
typedef struct static_tree_desc_s static_tree_desc;
typedef struct tree_desc_s {
ct_data *dyn_tree; /* the dynamic tree */
int max_code; /* largest code with non zero frequency */
static_tree_desc *stat_desc; /* the corresponding static tree */
} FAR tree_desc;
typedef ush Pos;
typedef Pos FAR Posf;
typedef unsigned IPos;
/* A Pos is an index in the character window. We use short instead of int to
* save space in the various tables. IPos is used only for parameter passing.
*/
typedef struct internal_state {
z_streamp strm; /* pointer back to this zlib stream */
int status; /* as the name implies */
Bytef *pending_buf; /* output still pending */
ulg pending_buf_size; /* size of pending_buf */
Bytef *pending_out; /* next pending byte to output to the stream */
uInt pending; /* nb of bytes in the pending buffer */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
gz_headerp gzhead; /* gzip header information to write */
uInt gzindex; /* where in extra, name, or comment */
Byte method; /* can only be DEFLATED */
int last_flush; /* value of flush param for previous deflate call */
/* used by deflate.c: */
uInt w_size; /* LZ77 window size (32K by default) */
uInt w_bits; /* log2(w_size) (8..16) */
uInt w_mask; /* w_size - 1 */
Bytef *window;
/* Sliding window. Input bytes are read into the second half of the window,
* and move to the first half later to keep a dictionary of at least wSize
* bytes. With this organization, matches are limited to a distance of
* wSize-MAX_MATCH bytes, but this ensures that IO is always
* performed with a length multiple of the block size. Also, it limits
* the window size to 64K, which is quite useful on MSDOS.
* To do: use the user input buffer as sliding window.
*/
ulg window_size;
/* Actual size of window: 2*wSize, except when the user input buffer
* is directly used as sliding window.
*/
Posf *prev;
/* Link to older string with same hash index. To limit the size of this
* array to 64K, this link is maintained only for the last 32K strings.
* An index in this array is thus a window index modulo 32K.
*/
Posf *head; /* Heads of the hash chains or NIL. */
uInt ins_h; /* hash index of string to be inserted */
uInt hash_size; /* number of elements in hash table */
uInt hash_bits; /* log2(hash_size) */
uInt hash_mask; /* hash_size-1 */
uInt hash_shift;
/* Number of bits by which ins_h must be shifted at each input
* step. It must be such that after MIN_MATCH steps, the oldest
* byte no longer takes part in the hash key, that is:
* hash_shift * MIN_MATCH >= hash_bits
*/
long block_start;
/* Window position at the beginning of the current output block. Gets
* negative when the window is moved backwards.
*/
uInt match_length; /* length of best match */
IPos prev_match; /* previous match */
int match_available; /* set if previous match exists */
uInt strstart; /* start of string to insert */
uInt match_start; /* start of matching string */
uInt lookahead; /* number of valid bytes ahead in window */
uInt prev_length;
/* Length of the best match at previous step. Matches not greater than this
* are discarded. This is used in the lazy match evaluation.
*/
uInt max_chain_length;
/* To speed up deflation, hash chains are never searched beyond this
* length. A higher limit improves compression ratio but degrades the
* speed.
*/
uInt max_lazy_match;
/* Attempt to find a better match only when the current match is strictly
* smaller than this value. This mechanism is used only for compression
* levels >= 4.
*/
# define max_insert_length max_lazy_match
/* Insert new strings in the hash table only if the match length is not
* greater than this length. This saves time but degrades compression.
* max_insert_length is used only for compression levels <= 3.
*/
int level; /* compression level (1..9) */
int strategy; /* favor or force Huffman coding*/
uInt good_match;
/* Use a faster search when the previous match is longer than this */
int nice_match; /* Stop searching when current match exceeds this */
/* used by trees.c: */
/* Didn't use ct_data typedef below to suppress compiler warning */
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
struct tree_desc_s l_desc; /* desc. for literal tree */
struct tree_desc_s d_desc; /* desc. for distance tree */
struct tree_desc_s bl_desc; /* desc. for bit length tree */
ush bl_count[MAX_BITS+1];
/* number of codes at each bit length for an optimal tree */
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
int heap_len; /* number of elements in the heap */
int heap_max; /* element of largest frequency */
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
* The same heap array is used to build all trees.
*/
uch depth[2*L_CODES+1];
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
uchf *l_buf; /* buffer for literals or lengths */
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
* limiting lit_bufsize to 64K:
* - frequencies can be kept in 16 bit counters
* - if compression is not successful for the first block, all input
* data is still in the window so we can still emit a stored block even
* when input comes from standard input. (This can also be done for
* all blocks if lit_bufsize is not greater than 32K.)
* - if compression is not successful for a file smaller than 64K, we can
* even emit a stored file instead of a stored block (saving 5 bytes).
* This is applicable only for zip (not gzip or zlib).
* - creating new Huffman trees less frequently may not provide fast
* adaptation to changes in the input data statistics. (Take for
* example a binary file with poorly compressible code followed by
* a highly compressible string table.) Smaller buffer sizes give
* fast adaptation but have of course the overhead of transmitting
* trees more frequently.
* - I can't count above 4
*/
uInt last_lit; /* running index in l_buf */
ushf *d_buf;
/* Buffer for distances. To simplify the code, d_buf and l_buf have
* the same number of elements. To use different lengths, an extra flag
* array would be necessary.
*/
ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */
uInt matches; /* number of string matches in current block */
uInt insert; /* bytes at end of window left to insert */
#ifdef DEBUG
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
#endif
ush bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least
* significant bits).
*/
int bi_valid;
/* Number of valid bits in bi_buf. All bits above the last valid bit
* are always zero.
*/
ulg high_water;
/* High water mark offset in window for initialized bytes -- bytes above
* this are set to zero in order to avoid memory check warnings when
* longest match routines access bytes past the input. This is then
* updated to the new high water mark.
*/
} FAR deflate_state;
/* Output a byte on the stream.
* IN assertion: there is enough room in pending_buf.
*/
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
* See deflate.c for comments about the MIN_MATCH+1.
*/
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
/* In order to simplify the code, particularly on 16 bit machines, match
* distances are limited to MAX_DIST instead of WSIZE.
*/
#define WIN_INIT MAX_MATCH
/* Number of bytes after end of data in window to initialize in order to avoid
memory checker errors from longest match routines */
/* in trees.c */
void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
ulg stored_len, int last));
void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
ulg stored_len, int last));
#define d_code(dist) \
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
/* Mapping from a distance to a distance code. dist is the distance - 1 and
* must not have side effects. _dist_code[256] and _dist_code[257] are never
* used.
*/
#ifndef DEBUG
/* Inline versions of _tr_tally for speed: */
#if defined(GEN_TREES_H) || !defined(STDC)
extern uch ZLIB_INTERNAL _length_code[];
extern uch ZLIB_INTERNAL _dist_code[];
#else
extern const uch ZLIB_INTERNAL _length_code[];
extern const uch ZLIB_INTERNAL _dist_code[];
#endif
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
s->d_buf[s->last_lit] = 0; \
s->l_buf[s->last_lit++] = cc; \
s->dyn_ltree[cc].Freq++; \
flush = (s->last_lit == s->lit_bufsize-1); \
}
# define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (length); \
ush dist = (distance); \
s->d_buf[s->last_lit] = dist; \
s->l_buf[s->last_lit++] = len; \
dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->last_lit == s->lit_bufsize-1); \
}
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
# define _tr_tally_dist(s, distance, length, flush) \
flush = _tr_tally(s, distance, length)
#endif
#endif /* DEFLATE_H */

25
deps/zlib/gzclose.c vendored Normal file
View file

@ -0,0 +1,25 @@
/* gzclose.c -- zlib gzclose() function
* Copyright (C) 2004, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
/* gzclose() is in a separate file so that it is linked in only if it is used.
That way the other gzclose functions can be used instead to avoid linking in
unneeded compression or decompression routines. */
int ZEXPORT gzclose(file)
gzFile file;
{
#ifndef NO_GZCOMPRESS
gz_statep state;
if (file == NULL)
return Z_STREAM_ERROR;
state = (gz_statep)file;
return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
#else
return gzclose_r(file);
#endif
}

209
deps/zlib/gzguts.h vendored Normal file
View file

@ -0,0 +1,209 @@
/* gzguts.h -- zlib internal header definitions for gz* operations
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#ifdef _LARGEFILE64_SOURCE
# ifndef _LARGEFILE_SOURCE
# define _LARGEFILE_SOURCE 1
# endif
# ifdef _FILE_OFFSET_BITS
# undef _FILE_OFFSET_BITS
# endif
#endif
#ifdef HAVE_HIDDEN
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
# define ZLIB_INTERNAL
#endif
#include <stdio.h>
#include "zlib.h"
#ifdef STDC
# include <string.h>
# include <stdlib.h>
# include <limits.h>
#endif
#include <fcntl.h>
#ifdef _WIN32
# include <stddef.h>
#endif
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
# include <io.h>
#endif
#ifdef WINAPI_FAMILY
# define open _open
# define read _read
# define write _write
# define close _close
#endif
#ifdef NO_DEFLATE /* for compatibility with old definition */
# define NO_GZCOMPRESS
#endif
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#if defined(__CYGWIN__)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#ifndef HAVE_VSNPRINTF
# ifdef MSDOS
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
but for now we just assume it doesn't. */
# define NO_vsnprintf
# endif
# ifdef __TURBOC__
# define NO_vsnprintf
# endif
# ifdef WIN32
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
# define vsnprintf _vsnprintf
# endif
# endif
# endif
# ifdef __SASC
# define NO_vsnprintf
# endif
# ifdef VMS
# define NO_vsnprintf
# endif
# ifdef __OS400__
# define NO_vsnprintf
# endif
# ifdef __MVS__
# define NO_vsnprintf
# endif
#endif
/* unlike snprintf (which is required in C99, yet still not supported by
Microsoft more than a decade later!), _snprintf does not guarantee null
termination of the result -- however this is only used in gzlib.c where
the result is assured to fit in the space provided */
#ifdef _MSC_VER
# define snprintf _snprintf
#endif
#ifndef local
# define local static
#endif
/* compile with -Dlocal if your debugger can't find static symbols */
/* gz* functions always use library allocation functions */
#ifndef STDC
extern voidp malloc OF((uInt size));
extern void free OF((voidpf ptr));
#endif
/* get errno and strerror definition */
#if defined UNDER_CE
# include <windows.h>
# define zstrerror() gz_strwinerror((DWORD)GetLastError())
#else
# ifndef NO_STRERROR
# include <errno.h>
# define zstrerror() strerror(errno)
# else
# define zstrerror() "stdio error (consult errno)"
# endif
#endif
/* provide prototypes for these when building zlib without LFS */
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
#endif
/* default memLevel */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
/* default i/o buffer size -- double this for output when reading (this and
twice this must be able to fit in an unsigned type) */
#define GZBUFSIZE 8192
/* gzip modes, also provide a little integrity check on the passed structure */
#define GZ_NONE 0
#define GZ_READ 7247
#define GZ_WRITE 31153
#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
/* values for gz_state how */
#define LOOK 0 /* look for a gzip header */
#define COPY 1 /* copy input directly */
#define GZIP 2 /* decompress a gzip stream */
/* internal gzip file state data structure */
typedef struct {
/* exposed contents for gzgetc() macro */
struct gzFile_s x; /* "x" for exposed */
/* x.have: number of bytes available at x.next */
/* x.next: next output data to deliver or write */
/* x.pos: current position in uncompressed data */
/* used for both reading and writing */
int mode; /* see gzip modes above */
int fd; /* file descriptor */
char *path; /* path or fd for error messages */
unsigned size; /* buffer size, zero if not allocated yet */
unsigned want; /* requested buffer size, default is GZBUFSIZE */
unsigned char *in; /* input buffer */
unsigned char *out; /* output buffer (double-sized when reading) */
int direct; /* 0 if processing gzip, 1 if transparent */
/* just for reading */
int how; /* 0: get header, 1: copy, 2: decompress */
z_off64_t start; /* where the gzip data started, for rewinding */
int eof; /* true if end of input file reached */
int past; /* true if read requested past end */
/* just for writing */
int level; /* compression level */
int strategy; /* compression strategy */
/* seek request */
z_off64_t skip; /* amount to skip (already rewound if backwards) */
int seek; /* true if seek request pending */
/* error information */
int err; /* error code */
char *msg; /* error message */
/* zlib inflate or deflate stream */
z_stream strm; /* stream structure in-place (not a pointer) */
} gz_state;
typedef gz_state FAR *gz_statep;
/* shared functions */
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
#if defined UNDER_CE
char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
#endif
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
value -- needed when comparing unsigned to z_off64_t, which is signed
(possible z_off64_t types off_t, off64_t, and long are all signed) */
#ifdef INT_MAX
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
#else
unsigned ZLIB_INTERNAL gz_intmax OF((void));
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
#endif

634
deps/zlib/gzlib.c vendored Normal file
View file

@ -0,0 +1,634 @@
/* gzlib.c -- zlib functions common to reading and writing gzip files
* Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
#if defined(_WIN32) && !defined(__BORLANDC__)
# define LSEEK _lseeki64
#else
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
# define LSEEK lseek64
#else
# define LSEEK lseek
#endif
#endif
/* Local functions */
local void gz_reset OF((gz_statep));
local gzFile gz_open OF((const void *, int, const char *));
#if defined UNDER_CE
/* Map the Windows error number in ERROR to a locale-dependent error message
string and return a pointer to it. Typically, the values for ERROR come
from GetLastError.
The string pointed to shall not be modified by the application, but may be
overwritten by a subsequent call to gz_strwinerror
The gz_strwinerror function does not change the current setting of
GetLastError. */
char ZLIB_INTERNAL *gz_strwinerror (error)
DWORD error;
{
static char buf[1024];
wchar_t *msgbuf;
DWORD lasterr = GetLastError();
DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
error,
0, /* Default language */
(LPVOID)&msgbuf,
0,
NULL);
if (chars != 0) {
/* If there is an \r\n appended, zap it. */
if (chars >= 2
&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
chars -= 2;
msgbuf[chars] = 0;
}
if (chars > sizeof (buf) - 1) {
chars = sizeof (buf) - 1;
msgbuf[chars] = 0;
}
wcstombs(buf, msgbuf, chars + 1);
LocalFree(msgbuf);
}
else {
sprintf(buf, "unknown win32 error (%ld)", error);
}
SetLastError(lasterr);
return buf;
}
#endif /* UNDER_CE */
/* Reset gzip file state */
local void gz_reset(state)
gz_statep state;
{
state->x.have = 0; /* no output data available */
if (state->mode == GZ_READ) { /* for reading ... */
state->eof = 0; /* not at end of file */
state->past = 0; /* have not read past end yet */
state->how = LOOK; /* look for gzip header */
}
state->seek = 0; /* no seek request pending */
gz_error(state, Z_OK, NULL); /* clear error */
state->x.pos = 0; /* no uncompressed data yet */
state->strm.avail_in = 0; /* no input data yet */
}
/* Open a gzip file either by name or file descriptor. */
local gzFile gz_open(path, fd, mode)
const void *path;
int fd;
const char *mode;
{
gz_statep state;
size_t len;
int oflag;
#ifdef O_CLOEXEC
int cloexec = 0;
#endif
#ifdef O_EXCL
int exclusive = 0;
#endif
/* check input */
if (path == NULL)
return NULL;
/* allocate gzFile structure to return */
state = (gz_statep)malloc(sizeof(gz_state));
if (state == NULL)
return NULL;
state->size = 0; /* no buffers allocated yet */
state->want = GZBUFSIZE; /* requested buffer size */
state->msg = NULL; /* no error message yet */
/* interpret mode */
state->mode = GZ_NONE;
state->level = Z_DEFAULT_COMPRESSION;
state->strategy = Z_DEFAULT_STRATEGY;
state->direct = 0;
while (*mode) {
if (*mode >= '0' && *mode <= '9')
state->level = *mode - '0';
else
switch (*mode) {
case 'r':
state->mode = GZ_READ;
break;
#ifndef NO_GZCOMPRESS
case 'w':
state->mode = GZ_WRITE;
break;
case 'a':
state->mode = GZ_APPEND;
break;
#endif
case '+': /* can't read and write at the same time */
free(state);
return NULL;
case 'b': /* ignore -- will request binary anyway */
break;
#ifdef O_CLOEXEC
case 'e':
cloexec = 1;
break;
#endif
#ifdef O_EXCL
case 'x':
exclusive = 1;
break;
#endif
case 'f':
state->strategy = Z_FILTERED;
break;
case 'h':
state->strategy = Z_HUFFMAN_ONLY;
break;
case 'R':
state->strategy = Z_RLE;
break;
case 'F':
state->strategy = Z_FIXED;
break;
case 'T':
state->direct = 1;
break;
default: /* could consider as an error, but just ignore */
;
}
mode++;
}
/* must provide an "r", "w", or "a" */
if (state->mode == GZ_NONE) {
free(state);
return NULL;
}
/* can't force transparent read */
if (state->mode == GZ_READ) {
if (state->direct) {
free(state);
return NULL;
}
state->direct = 1; /* for empty file */
}
/* save the path name for error messages */
#ifdef _WIN32
if (fd == -2) {
len = wcstombs(NULL, path, 0);
if (len == (size_t)-1)
len = 0;
}
else
#endif
len = strlen((const char *)path);
state->path = (char *)malloc(len + 1);
if (state->path == NULL) {
free(state);
return NULL;
}
#ifdef _WIN32
if (fd == -2)
if (len)
wcstombs(state->path, path, len + 1);
else
*(state->path) = 0;
else
#endif
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
snprintf(state->path, len + 1, "%s", (const char *)path);
#else
strcpy(state->path, path);
#endif
/* compute the flags for open() */
oflag =
#ifdef O_LARGEFILE
O_LARGEFILE |
#endif
#ifdef O_BINARY
O_BINARY |
#endif
#ifdef O_CLOEXEC
(cloexec ? O_CLOEXEC : 0) |
#endif
(state->mode == GZ_READ ?
O_RDONLY :
(O_WRONLY | O_CREAT |
#ifdef O_EXCL
(exclusive ? O_EXCL : 0) |
#endif
(state->mode == GZ_WRITE ?
O_TRUNC :
O_APPEND)));
/* open the file with the appropriate flags (or just use fd) */
state->fd = fd > -1 ? fd : (
#ifdef _WIN32
fd == -2 ? _wopen(path, oflag, 0666) :
#endif
open((const char *)path, oflag, 0666));
if (state->fd == -1) {
free(state->path);
free(state);
return NULL;
}
if (state->mode == GZ_APPEND)
state->mode = GZ_WRITE; /* simplify later checks */
/* save the current position for rewinding (only if reading) */
if (state->mode == GZ_READ) {
state->start = LSEEK(state->fd, 0, SEEK_CUR);
if (state->start == -1) state->start = 0;
}
/* initialize stream */
gz_reset(state);
/* return stream */
return (gzFile)state;
}
/* -- see zlib.h -- */
gzFile ZEXPORT gzopen(path, mode)
const char *path;
const char *mode;
{
return gz_open(path, -1, mode);
}
/* -- see zlib.h -- */
gzFile ZEXPORT gzopen64(path, mode)
const char *path;
const char *mode;
{
return gz_open(path, -1, mode);
}
/* -- see zlib.h -- */
gzFile ZEXPORT gzdopen(fd, mode)
int fd;
const char *mode;
{
char *path; /* identifier for error messages */
gzFile gz;
if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
return NULL;
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
#else
sprintf(path, "<fd:%d>", fd); /* for debugging */
#endif
gz = gz_open(path, fd, mode);
free(path);
return gz;
}
/* -- see zlib.h -- */
#ifdef _WIN32
gzFile ZEXPORT gzopen_w(path, mode)
const wchar_t *path;
const char *mode;
{
return gz_open(path, -2, mode);
}
#endif
/* -- see zlib.h -- */
int ZEXPORT gzbuffer(file, size)
gzFile file;
unsigned size;
{
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return -1;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return -1;
/* make sure we haven't already allocated memory */
if (state->size != 0)
return -1;
/* check and set requested size */
if (size < 2)
size = 2; /* need two bytes to check magic header */
state->want = size;
return 0;
}
/* -- see zlib.h -- */
int ZEXPORT gzrewind(file)
gzFile file;
{
gz_statep state;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
/* check that we're reading and that there's no error */
if (state->mode != GZ_READ ||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
return -1;
/* back up and start over */
if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
return -1;
gz_reset(state);
return 0;
}
/* -- see zlib.h -- */
z_off64_t ZEXPORT gzseek64(file, offset, whence)
gzFile file;
z_off64_t offset;
int whence;
{
unsigned n;
z_off64_t ret;
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return -1;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return -1;
/* check that there's no error */
if (state->err != Z_OK && state->err != Z_BUF_ERROR)
return -1;
/* can only seek from start or relative to current position */
if (whence != SEEK_SET && whence != SEEK_CUR)
return -1;
/* normalize offset to a SEEK_CUR specification */
if (whence == SEEK_SET)
offset -= state->x.pos;
else if (state->seek)
offset += state->skip;
state->seek = 0;
/* if within raw area while reading, just go there */
if (state->mode == GZ_READ && state->how == COPY &&
state->x.pos + offset >= 0) {
ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
if (ret == -1)
return -1;
state->x.have = 0;
state->eof = 0;
state->past = 0;
state->seek = 0;
gz_error(state, Z_OK, NULL);
state->strm.avail_in = 0;
state->x.pos += offset;
return state->x.pos;
}
/* calculate skip amount, rewinding if needed for back seek when reading */
if (offset < 0) {
if (state->mode != GZ_READ) /* writing -- can't go backwards */
return -1;
offset += state->x.pos;
if (offset < 0) /* before start of file! */
return -1;
if (gzrewind(file) == -1) /* rewind, then skip to offset */
return -1;
}
/* if reading, skip what's in output buffer (one less gzgetc() check) */
if (state->mode == GZ_READ) {
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
(unsigned)offset : state->x.have;
state->x.have -= n;
state->x.next += n;
state->x.pos += n;
offset -= n;
}
/* request skip (if not zero) */
if (offset) {
state->seek = 1;
state->skip = offset;
}
return state->x.pos + offset;
}
/* -- see zlib.h -- */
z_off_t ZEXPORT gzseek(file, offset, whence)
gzFile file;
z_off_t offset;
int whence;
{
z_off64_t ret;
ret = gzseek64(file, (z_off64_t)offset, whence);
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}
/* -- see zlib.h -- */
z_off64_t ZEXPORT gztell64(file)
gzFile file;
{
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return -1;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return -1;
/* return position */
return state->x.pos + (state->seek ? state->skip : 0);
}
/* -- see zlib.h -- */
z_off_t ZEXPORT gztell(file)
gzFile file;
{
z_off64_t ret;
ret = gztell64(file);
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}
/* -- see zlib.h -- */
z_off64_t ZEXPORT gzoffset64(file)
gzFile file;
{
z_off64_t offset;
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return -1;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return -1;
/* compute and return effective offset in file */
offset = LSEEK(state->fd, 0, SEEK_CUR);
if (offset == -1)
return -1;
if (state->mode == GZ_READ) /* reading */
offset -= state->strm.avail_in; /* don't count buffered input */
return offset;
}
/* -- see zlib.h -- */
z_off_t ZEXPORT gzoffset(file)
gzFile file;
{
z_off64_t ret;
ret = gzoffset64(file);
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}
/* -- see zlib.h -- */
int ZEXPORT gzeof(file)
gzFile file;
{
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return 0;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return 0;
/* return end-of-file state */
return state->mode == GZ_READ ? state->past : 0;
}
/* -- see zlib.h -- */
const char * ZEXPORT gzerror(file, errnum)
gzFile file;
int *errnum;
{
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return NULL;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return NULL;
/* return error information */
if (errnum != NULL)
*errnum = state->err;
return state->err == Z_MEM_ERROR ? "out of memory" :
(state->msg == NULL ? "" : state->msg);
}
/* -- see zlib.h -- */
void ZEXPORT gzclearerr(file)
gzFile file;
{
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return;
/* clear error and end-of-file */
if (state->mode == GZ_READ) {
state->eof = 0;
state->past = 0;
}
gz_error(state, Z_OK, NULL);
}
/* Create an error message in allocated memory and set state->err and
state->msg accordingly. Free any previous error message already there. Do
not try to free or allocate space if the error is Z_MEM_ERROR (out of
memory). Simply save the error message as a static string. If there is an
allocation failure constructing the error message, then convert the error to
out of memory. */
void ZLIB_INTERNAL gz_error(state, err, msg)
gz_statep state;
int err;
const char *msg;
{
/* free previously allocated message and clear */
if (state->msg != NULL) {
if (state->err != Z_MEM_ERROR)
free(state->msg);
state->msg = NULL;
}
/* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
if (err != Z_OK && err != Z_BUF_ERROR)
state->x.have = 0;
/* set error code, and if no message, then done */
state->err = err;
if (msg == NULL)
return;
/* for an out of memory error, return literal string when requested */
if (err == Z_MEM_ERROR)
return;
/* construct error message with path */
if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
NULL) {
state->err = Z_MEM_ERROR;
return;
}
#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
"%s%s%s", state->path, ": ", msg);
#else
strcpy(state->msg, state->path);
strcat(state->msg, ": ");
strcat(state->msg, msg);
#endif
return;
}
#ifndef INT_MAX
/* portably return maximum value for an int (when limits.h presumed not
available) -- we need to do this to cover cases where 2's complement not
used, since C standard permits 1's complement and sign-bit representations,
otherwise we could just use ((unsigned)-1) >> 1 */
unsigned ZLIB_INTERNAL gz_intmax()
{
unsigned p, q;
p = 1;
do {
q = p;
p <<= 1;
p++;
} while (p > q);
return q >> 1;
}
#endif

594
deps/zlib/gzread.c vendored Normal file
View file

@ -0,0 +1,594 @@
/* gzread.c -- zlib functions for reading gzip files
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
/* Local functions */
local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
local int gz_avail OF((gz_statep));
local int gz_look OF((gz_statep));
local int gz_decomp OF((gz_statep));
local int gz_fetch OF((gz_statep));
local int gz_skip OF((gz_statep, z_off64_t));
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
state->fd, and update state->eof, state->err, and state->msg as appropriate.
This function needs to loop on read(), since read() is not guaranteed to
read the number of bytes requested, depending on the type of descriptor. */
local int gz_load(state, buf, len, have)
gz_statep state;
unsigned char *buf;
unsigned len;
unsigned *have;
{
int ret;
*have = 0;
do {
ret = read(state->fd, buf + *have, len - *have);
if (ret <= 0)
break;
*have += ret;
} while (*have < len);
if (ret < 0) {
gz_error(state, Z_ERRNO, zstrerror());
return -1;
}
if (ret == 0)
state->eof = 1;
return 0;
}
/* Load up input buffer and set eof flag if last data loaded -- return -1 on
error, 0 otherwise. Note that the eof flag is set when the end of the input
file is reached, even though there may be unused data in the buffer. Once
that data has been used, no more attempts will be made to read the file.
If strm->avail_in != 0, then the current data is moved to the beginning of
the input buffer, and then the remainder of the buffer is loaded with the
available data from the input file. */
local int gz_avail(state)
gz_statep state;
{
unsigned got;
z_streamp strm = &(state->strm);
if (state->err != Z_OK && state->err != Z_BUF_ERROR)
return -1;
if (state->eof == 0) {
if (strm->avail_in) { /* copy what's there to the start */
unsigned char *p = state->in;
unsigned const char *q = strm->next_in;
unsigned n = strm->avail_in;
do {
*p++ = *q++;
} while (--n);
}
if (gz_load(state, state->in + strm->avail_in,
state->size - strm->avail_in, &got) == -1)
return -1;
strm->avail_in += got;
strm->next_in = state->in;
}
return 0;
}
/* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
If this is the first time in, allocate required memory. state->how will be
left unchanged if there is no more input data available, will be set to COPY
if there is no gzip header and direct copying will be performed, or it will
be set to GZIP for decompression. If direct copying, then leftover input
data from the input buffer will be copied to the output buffer. In that
case, all further file reads will be directly to either the output buffer or
a user buffer. If decompressing, the inflate state will be initialized.
gz_look() will return 0 on success or -1 on failure. */
local int gz_look(state)
gz_statep state;
{
z_streamp strm = &(state->strm);
/* allocate read buffers and inflate memory */
if (state->size == 0) {
/* allocate buffers */
state->in = (unsigned char *)malloc(state->want);
state->out = (unsigned char *)malloc(state->want << 1);
if (state->in == NULL || state->out == NULL) {
if (state->out != NULL)
free(state->out);
if (state->in != NULL)
free(state->in);
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
state->size = state->want;
/* allocate inflate memory */
state->strm.zalloc = Z_NULL;
state->strm.zfree = Z_NULL;
state->strm.opaque = Z_NULL;
state->strm.avail_in = 0;
state->strm.next_in = Z_NULL;
if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
free(state->out);
free(state->in);
state->size = 0;
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
}
/* get at least the magic bytes in the input buffer */
if (strm->avail_in < 2) {
if (gz_avail(state) == -1)
return -1;
if (strm->avail_in == 0)
return 0;
}
/* look for gzip magic bytes -- if there, do gzip decoding (note: there is
a logical dilemma here when considering the case of a partially written
gzip file, to wit, if a single 31 byte is written, then we cannot tell
whether this is a single-byte file, or just a partially written gzip
file -- for here we assume that if a gzip file is being written, then
the header will be written in a single operation, so that reading a
single byte is sufficient indication that it is not a gzip file) */
if (strm->avail_in > 1 &&
strm->next_in[0] == 31 && strm->next_in[1] == 139) {
inflateReset(strm);
state->how = GZIP;
state->direct = 0;
return 0;
}
/* no gzip header -- if we were decoding gzip before, then this is trailing
garbage. Ignore the trailing garbage and finish. */
if (state->direct == 0) {
strm->avail_in = 0;
state->eof = 1;
state->x.have = 0;
return 0;
}
/* doing raw i/o, copy any leftover input to output -- this assumes that
the output buffer is larger than the input buffer, which also assures
space for gzungetc() */
state->x.next = state->out;
if (strm->avail_in) {
memcpy(state->x.next, strm->next_in, strm->avail_in);
state->x.have = strm->avail_in;
strm->avail_in = 0;
}
state->how = COPY;
state->direct = 1;
return 0;
}
/* Decompress from input to the provided next_out and avail_out in the state.
On return, state->x.have and state->x.next point to the just decompressed
data. If the gzip stream completes, state->how is reset to LOOK to look for
the next gzip stream or raw data, once state->x.have is depleted. Returns 0
on success, -1 on failure. */
local int gz_decomp(state)
gz_statep state;
{
int ret = Z_OK;
unsigned had;
z_streamp strm = &(state->strm);
/* fill output buffer up to end of deflate stream */
had = strm->avail_out;
do {
/* get more input for inflate() */
if (strm->avail_in == 0 && gz_avail(state) == -1)
return -1;
if (strm->avail_in == 0) {
gz_error(state, Z_BUF_ERROR, "unexpected end of file");
break;
}
/* decompress and handle errors */
ret = inflate(strm, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
gz_error(state, Z_STREAM_ERROR,
"internal error: inflate stream corrupt");
return -1;
}
if (ret == Z_MEM_ERROR) {
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
gz_error(state, Z_DATA_ERROR,
strm->msg == NULL ? "compressed data error" : strm->msg);
return -1;
}
} while (strm->avail_out && ret != Z_STREAM_END);
/* update available output */
state->x.have = had - strm->avail_out;
state->x.next = strm->next_out - state->x.have;
/* if the gzip stream completed successfully, look for another */
if (ret == Z_STREAM_END)
state->how = LOOK;
/* good decompression */
return 0;
}
/* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
Data is either copied from the input file or decompressed from the input
file depending on state->how. If state->how is LOOK, then a gzip header is
looked for to determine whether to copy or decompress. Returns -1 on error,
otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
end of the input file has been reached and all data has been processed. */
local int gz_fetch(state)
gz_statep state;
{
z_streamp strm = &(state->strm);
do {
switch(state->how) {
case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
if (gz_look(state) == -1)
return -1;
if (state->how == LOOK)
return 0;
break;
case COPY: /* -> COPY */
if (gz_load(state, state->out, state->size << 1, &(state->x.have))
== -1)
return -1;
state->x.next = state->out;
return 0;
case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
strm->avail_out = state->size << 1;
strm->next_out = state->out;
if (gz_decomp(state) == -1)
return -1;
}
} while (state->x.have == 0 && (!state->eof || strm->avail_in));
return 0;
}
/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
local int gz_skip(state, len)
gz_statep state;
z_off64_t len;
{
unsigned n;
/* skip over len bytes or reach end-of-file, whichever comes first */
while (len)
/* skip over whatever is in output buffer */
if (state->x.have) {
n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
(unsigned)len : state->x.have;
state->x.have -= n;
state->x.next += n;
state->x.pos += n;
len -= n;
}
/* output buffer empty -- return if we're at the end of the input */
else if (state->eof && state->strm.avail_in == 0)
break;
/* need more data to skip -- load up output buffer */
else {
/* get more output, looking for header if required */
if (gz_fetch(state) == -1)
return -1;
}
return 0;
}
/* -- see zlib.h -- */
int ZEXPORT gzread(file, buf, len)
gzFile file;
voidp buf;
unsigned len;
{
unsigned got, n;
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're reading and that there's no (serious) error */
if (state->mode != GZ_READ ||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
return -1;
/* since an int is returned, make sure len fits in one, otherwise return
with an error (this avoids the flaw in the interface) */
if ((int)len < 0) {
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
return -1;
}
/* if len is zero, avoid unnecessary operations */
if (len == 0)
return 0;
/* process a skip request */
if (state->seek) {
state->seek = 0;
if (gz_skip(state, state->skip) == -1)
return -1;
}
/* get len bytes to buf, or less than len if at the end */
got = 0;
do {
/* first just try copying data from the output buffer */
if (state->x.have) {
n = state->x.have > len ? len : state->x.have;
memcpy(buf, state->x.next, n);
state->x.next += n;
state->x.have -= n;
}
/* output buffer empty -- return if we're at the end of the input */
else if (state->eof && strm->avail_in == 0) {
state->past = 1; /* tried to read past end */
break;
}
/* need output data -- for small len or new stream load up our output
buffer */
else if (state->how == LOOK || len < (state->size << 1)) {
/* get more output, looking for header if required */
if (gz_fetch(state) == -1)
return -1;
continue; /* no progress yet -- go back to copy above */
/* the copy above assures that we will leave with space in the
output buffer, allowing at least one gzungetc() to succeed */
}
/* large len -- read directly into user buffer */
else if (state->how == COPY) { /* read directly */
if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
return -1;
}
/* large len -- decompress directly into user buffer */
else { /* state->how == GZIP */
strm->avail_out = len;
strm->next_out = (unsigned char *)buf;
if (gz_decomp(state) == -1)
return -1;
n = state->x.have;
state->x.have = 0;
}
/* update progress */
len -= n;
buf = (char *)buf + n;
got += n;
state->x.pos += n;
} while (len);
/* return number of bytes read into user buffer (will fit in int) */
return (int)got;
}
/* -- see zlib.h -- */
#ifdef Z_PREFIX_SET
# undef z_gzgetc
#else
# undef gzgetc
#endif
int ZEXPORT gzgetc(file)
gzFile file;
{
int ret;
unsigned char buf[1];
gz_statep state;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
/* check that we're reading and that there's no (serious) error */
if (state->mode != GZ_READ ||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
return -1;
/* try output buffer (no need to check for skip request) */
if (state->x.have) {
state->x.have--;
state->x.pos++;
return *(state->x.next)++;
}
/* nothing there -- try gzread() */
ret = gzread(file, buf, 1);
return ret < 1 ? -1 : buf[0];
}
int ZEXPORT gzgetc_(file)
gzFile file;
{
return gzgetc(file);
}
/* -- see zlib.h -- */
int ZEXPORT gzungetc(c, file)
int c;
gzFile file;
{
gz_statep state;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
/* check that we're reading and that there's no (serious) error */
if (state->mode != GZ_READ ||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
return -1;
/* process a skip request */
if (state->seek) {
state->seek = 0;
if (gz_skip(state, state->skip) == -1)
return -1;
}
/* can't push EOF */
if (c < 0)
return -1;
/* if output buffer empty, put byte at end (allows more pushing) */
if (state->x.have == 0) {
state->x.have = 1;
state->x.next = state->out + (state->size << 1) - 1;
state->x.next[0] = c;
state->x.pos--;
state->past = 0;
return c;
}
/* if no room, give up (must have already done a gzungetc()) */
if (state->x.have == (state->size << 1)) {
gz_error(state, Z_DATA_ERROR, "out of room to push characters");
return -1;
}
/* slide output data if needed and insert byte before existing data */
if (state->x.next == state->out) {
unsigned char *src = state->out + state->x.have;
unsigned char *dest = state->out + (state->size << 1);
while (src > state->out)
*--dest = *--src;
state->x.next = dest;
}
state->x.have++;
state->x.next--;
state->x.next[0] = c;
state->x.pos--;
state->past = 0;
return c;
}
/* -- see zlib.h -- */
char * ZEXPORT gzgets(file, buf, len)
gzFile file;
char *buf;
int len;
{
unsigned left, n;
char *str;
unsigned char *eol;
gz_statep state;
/* check parameters and get internal structure */
if (file == NULL || buf == NULL || len < 1)
return NULL;
state = (gz_statep)file;
/* check that we're reading and that there's no (serious) error */
if (state->mode != GZ_READ ||
(state->err != Z_OK && state->err != Z_BUF_ERROR))
return NULL;
/* process a skip request */
if (state->seek) {
state->seek = 0;
if (gz_skip(state, state->skip) == -1)
return NULL;
}
/* copy output bytes up to new line or len - 1, whichever comes first --
append a terminating zero to the string (we don't check for a zero in
the contents, let the user worry about that) */
str = buf;
left = (unsigned)len - 1;
if (left) do {
/* assure that something is in the output buffer */
if (state->x.have == 0 && gz_fetch(state) == -1)
return NULL; /* error */
if (state->x.have == 0) { /* end of file */
state->past = 1; /* read past end */
break; /* return what we have */
}
/* look for end-of-line in current output buffer */
n = state->x.have > left ? left : state->x.have;
eol = (unsigned char *)memchr(state->x.next, '\n', n);
if (eol != NULL)
n = (unsigned)(eol - state->x.next) + 1;
/* copy through end-of-line, or remainder if not found */
memcpy(buf, state->x.next, n);
state->x.have -= n;
state->x.next += n;
state->x.pos += n;
left -= n;
buf += n;
} while (left && eol == NULL);
/* return terminated string, or if nothing, end of file */
if (buf == str)
return NULL;
buf[0] = 0;
return str;
}
/* -- see zlib.h -- */
int ZEXPORT gzdirect(file)
gzFile file;
{
gz_statep state;
/* get internal structure */
if (file == NULL)
return 0;
state = (gz_statep)file;
/* if the state is not known, but we can find out, then do so (this is
mainly for right after a gzopen() or gzdopen()) */
if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
(void)gz_look(state);
/* return 1 if transparent, 0 if processing a gzip stream */
return state->direct;
}
/* -- see zlib.h -- */
int ZEXPORT gzclose_r(file)
gzFile file;
{
int ret, err;
gz_statep state;
/* get internal structure */
if (file == NULL)
return Z_STREAM_ERROR;
state = (gz_statep)file;
/* check that we're reading */
if (state->mode != GZ_READ)
return Z_STREAM_ERROR;
/* free memory and close file */
if (state->size) {
inflateEnd(&(state->strm));
free(state->out);
free(state->in);
}
err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
gz_error(state, Z_OK, NULL);
free(state->path);
ret = close(state->fd);
free(state);
return ret ? Z_ERRNO : err;
}

577
deps/zlib/gzwrite.c vendored Normal file
View file

@ -0,0 +1,577 @@
/* gzwrite.c -- zlib functions for writing gzip files
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
/* Local functions */
local int gz_init OF((gz_statep));
local int gz_comp OF((gz_statep, int));
local int gz_zero OF((gz_statep, z_off64_t));
/* Initialize state for writing a gzip file. Mark initialization by setting
state->size to non-zero. Return -1 on failure or 0 on success. */
local int gz_init(state)
gz_statep state;
{
int ret;
z_streamp strm = &(state->strm);
/* allocate input buffer */
state->in = (unsigned char *)malloc(state->want);
if (state->in == NULL) {
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
/* only need output buffer and deflate state if compressing */
if (!state->direct) {
/* allocate output buffer */
state->out = (unsigned char *)malloc(state->want);
if (state->out == NULL) {
free(state->in);
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
/* allocate deflate memory, set up for gzip compression */
strm->zalloc = Z_NULL;
strm->zfree = Z_NULL;
strm->opaque = Z_NULL;
ret = deflateInit2(strm, state->level, Z_DEFLATED,
MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
if (ret != Z_OK) {
free(state->out);
free(state->in);
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
}
/* mark state as initialized */
state->size = state->want;
/* initialize write buffer if compressing */
if (!state->direct) {
strm->avail_out = state->size;
strm->next_out = state->out;
state->x.next = strm->next_out;
}
return 0;
}
/* Compress whatever is at avail_in and next_in and write to the output file.
Return -1 if there is an error writing to the output file, otherwise 0.
flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
then the deflate() state is reset to start a new gzip stream. If gz->direct
is true, then simply write to the output file without compressing, and
ignore flush. */
local int gz_comp(state, flush)
gz_statep state;
int flush;
{
int ret, got;
unsigned have;
z_streamp strm = &(state->strm);
/* allocate memory if this is the first time through */
if (state->size == 0 && gz_init(state) == -1)
return -1;
/* write directly if requested */
if (state->direct) {
got = write(state->fd, strm->next_in, strm->avail_in);
if (got < 0 || (unsigned)got != strm->avail_in) {
gz_error(state, Z_ERRNO, zstrerror());
return -1;
}
strm->avail_in = 0;
return 0;
}
/* run deflate() on provided input until it produces no more output */
ret = Z_OK;
do {
/* write out current buffer contents if full, or if flushing, but if
doing Z_FINISH then don't write until we get to Z_STREAM_END */
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
(flush != Z_FINISH || ret == Z_STREAM_END))) {
have = (unsigned)(strm->next_out - state->x.next);
if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
(unsigned)got != have)) {
gz_error(state, Z_ERRNO, zstrerror());
return -1;
}
if (strm->avail_out == 0) {
strm->avail_out = state->size;
strm->next_out = state->out;
}
state->x.next = strm->next_out;
}
/* compress */
have = strm->avail_out;
ret = deflate(strm, flush);
if (ret == Z_STREAM_ERROR) {
gz_error(state, Z_STREAM_ERROR,
"internal error: deflate stream corrupt");
return -1;
}
have -= strm->avail_out;
} while (have);
/* if that completed a deflate stream, allow another to start */
if (flush == Z_FINISH)
deflateReset(strm);
/* all done, no errors */
return 0;
}
/* Compress len zeros to output. Return -1 on error, 0 on success. */
local int gz_zero(state, len)
gz_statep state;
z_off64_t len;
{
int first;
unsigned n;
z_streamp strm = &(state->strm);
/* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return -1;
/* compress len zeros (len guaranteed > 0) */
first = 1;
while (len) {
n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
(unsigned)len : state->size;
if (first) {
memset(state->in, 0, n);
first = 0;
}
strm->avail_in = n;
strm->next_in = state->in;
state->x.pos += n;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return -1;
len -= n;
}
return 0;
}
/* -- see zlib.h -- */
int ZEXPORT gzwrite(file, buf, len)
gzFile file;
voidpc buf;
unsigned len;
{
unsigned put = len;
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return 0;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return 0;
/* since an int is returned, make sure len fits in one, otherwise return
with an error (this avoids the flaw in the interface) */
if ((int)len < 0) {
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
return 0;
}
/* if len is zero, avoid unnecessary operations */
if (len == 0)
return 0;
/* allocate memory if this is the first time through */
if (state->size == 0 && gz_init(state) == -1)
return 0;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return 0;
}
/* for small len, copy to input buffer, otherwise compress directly */
if (len < state->size) {
/* copy to input buffer, compress when full */
do {
unsigned have, copy;
if (strm->avail_in == 0)
strm->next_in = state->in;
have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
copy = state->size - have;
if (copy > len)
copy = len;
memcpy(state->in + have, buf, copy);
strm->avail_in += copy;
state->x.pos += copy;
buf = (const char *)buf + copy;
len -= copy;
if (len && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
} while (len);
}
else {
/* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
/* directly compress user buffer to file */
strm->avail_in = len;
strm->next_in = (z_const Bytef *)buf;
state->x.pos += len;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
}
/* input was all buffered or compressed (put will fit in int) */
return (int)put;
}
/* -- see zlib.h -- */
int ZEXPORT gzputc(file, c)
gzFile file;
int c;
{
unsigned have;
unsigned char buf[1];
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return -1;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return -1;
}
/* try writing to input buffer for speed (state->size == 0 if buffer not
initialized) */
if (state->size) {
if (strm->avail_in == 0)
strm->next_in = state->in;
have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
if (have < state->size) {
state->in[have] = c;
strm->avail_in++;
state->x.pos++;
return c & 0xff;
}
}
/* no room in buffer or not initialized, use gz_write() */
buf[0] = c;
if (gzwrite(file, buf, 1) != 1)
return -1;
return c & 0xff;
}
/* -- see zlib.h -- */
int ZEXPORT gzputs(file, str)
gzFile file;
const char *str;
{
int ret;
unsigned len;
/* write string */
len = (unsigned)strlen(str);
ret = gzwrite(file, str, len);
return ret == 0 && len != 0 ? -1 : ret;
}
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
#include <stdarg.h>
/* -- see zlib.h -- */
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
{
int size, len;
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return 0;
/* make sure we have some buffer space */
if (state->size == 0 && gz_init(state) == -1)
return 0;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return 0;
}
/* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
/* do the printf() into the input buffer, put length in len */
size = (int)(state->size);
state->in[size - 1] = 0;
#ifdef NO_vsnprintf
# ifdef HAS_vsprintf_void
(void)vsprintf((char *)(state->in), format, va);
for (len = 0; len < size; len++)
if (state->in[len] == 0) break;
# else
len = vsprintf((char *)(state->in), format, va);
# endif
#else
# ifdef HAS_vsnprintf_void
(void)vsnprintf((char *)(state->in), size, format, va);
len = strlen((char *)(state->in));
# else
len = vsnprintf((char *)(state->in), size, format, va);
# endif
#endif
/* check that printf() results fit in buffer */
if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
return 0;
/* update buffer and position, defer compression until needed */
strm->avail_in = (unsigned)len;
strm->next_in = state->in;
state->x.pos += len;
return len;
}
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
{
va_list va;
int ret;
va_start(va, format);
ret = gzvprintf(file, format, va);
va_end(va);
return ret;
}
#else /* !STDC && !Z_HAVE_STDARG_H */
/* -- see zlib.h -- */
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
gzFile file;
const char *format;
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
{
int size, len;
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
strm = &(state->strm);
/* check that can really pass pointer in ints */
if (sizeof(int) != sizeof(void *))
return 0;
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return 0;
/* make sure we have some buffer space */
if (state->size == 0 && gz_init(state) == -1)
return 0;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return 0;
}
/* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
/* do the printf() into the input buffer, put length in len */
size = (int)(state->size);
state->in[size - 1] = 0;
#ifdef NO_snprintf
# ifdef HAS_sprintf_void
sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
for (len = 0; len < size; len++)
if (state->in[len] == 0) break;
# else
len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
# endif
#else
# ifdef HAS_snprintf_void
snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
len = strlen((char *)(state->in));
# else
len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
a19, a20);
# endif
#endif
/* check that printf() results fit in buffer */
if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
return 0;
/* update buffer and position, defer compression until needed */
strm->avail_in = (unsigned)len;
strm->next_in = state->in;
state->x.pos += len;
return len;
}
#endif
/* -- see zlib.h -- */
int ZEXPORT gzflush(file, flush)
gzFile file;
int flush;
{
gz_statep state;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return Z_STREAM_ERROR;
/* check flush parameter */
if (flush < 0 || flush > Z_FINISH)
return Z_STREAM_ERROR;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return -1;
}
/* compress remaining data with requested flush */
gz_comp(state, flush);
return state->err;
}
/* -- see zlib.h -- */
int ZEXPORT gzsetparams(file, level, strategy)
gzFile file;
int level;
int strategy;
{
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return Z_STREAM_ERROR;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return Z_STREAM_ERROR;
/* if no change is requested, then do nothing */
if (level == state->level && strategy == state->strategy)
return Z_OK;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return -1;
}
/* change compression parameters for subsequent input */
if (state->size) {
/* flush previous input with previous parameters before changing */
if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
return state->err;
deflateParams(strm, level, strategy);
}
state->level = level;
state->strategy = strategy;
return Z_OK;
}
/* -- see zlib.h -- */
int ZEXPORT gzclose_w(file)
gzFile file;
{
int ret = Z_OK;
gz_statep state;
/* get internal structure */
if (file == NULL)
return Z_STREAM_ERROR;
state = (gz_statep)file;
/* check that we're writing */
if (state->mode != GZ_WRITE)
return Z_STREAM_ERROR;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
ret = state->err;
}
/* flush, free memory, and close file */
if (gz_comp(state, Z_FINISH) == -1)
ret = state->err;
if (state->size) {
if (!state->direct) {
(void)deflateEnd(&(state->strm));
free(state->out);
}
free(state->in);
}
gz_error(state, Z_OK, NULL);
free(state->path);
if (close(state->fd) == -1)
ret = Z_ERRNO;
free(state);
return ret;
}

640
deps/zlib/infback.c vendored Normal file
View file

@ -0,0 +1,640 @@
/* infback.c -- inflate using a call-back interface
* Copyright (C) 1995-2011 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/*
This code is largely copied from inflate.c. Normally either infback.o or
inflate.o would be linked into an application--not both. The interface
with inffast.c is retained so that optimized assembler-coded versions of
inflate_fast() can be used with either inflate.c or infback.c.
*/
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
/* function prototypes */
local void fixedtables OF((struct inflate_state FAR *state));
/*
strm provides memory allocation functions in zalloc and zfree, or
Z_NULL to use the library memory allocation functions.
windowBits is in the range 8..15, and window is a user-supplied
window and output buffer that is 2**windowBits bytes.
*/
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
z_streamp strm;
int windowBits;
unsigned char FAR *window;
const char *version;
int stream_size;
{
struct inflate_state FAR *state;
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
stream_size != (int)(sizeof(z_stream)))
return Z_VERSION_ERROR;
if (strm == Z_NULL || window == Z_NULL ||
windowBits < 8 || windowBits > 15)
return Z_STREAM_ERROR;
strm->msg = Z_NULL; /* in case we return an error */
if (strm->zalloc == (alloc_func)0) {
#ifdef Z_SOLO
return Z_STREAM_ERROR;
#else
strm->zalloc = zcalloc;
strm->opaque = (voidpf)0;
#endif
}
if (strm->zfree == (free_func)0)
#ifdef Z_SOLO
return Z_STREAM_ERROR;
#else
strm->zfree = zcfree;
#endif
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n"));
strm->state = (struct internal_state FAR *)state;
state->dmax = 32768U;
state->wbits = windowBits;
state->wsize = 1U << windowBits;
state->window = window;
state->wnext = 0;
state->whave = 0;
return Z_OK;
}
/*
Return state with length and distance decoding tables and index sizes set to
fixed code decoding. Normally this returns fixed tables from inffixed.h.
If BUILDFIXED is defined, then instead this routine builds the tables the
first time it's called, and returns those tables the first time and
thereafter. This reduces the size of the code by about 2K bytes, in
exchange for a little execution time. However, BUILDFIXED should not be
used for threaded applications, since the rewriting of the tables and virgin
may not be thread-safe.
*/
local void fixedtables(state)
struct inflate_state FAR *state;
{
#ifdef BUILDFIXED
static int virgin = 1;
static code *lenfix, *distfix;
static code fixed[544];
/* build fixed huffman tables if first call (may not be thread safe) */
if (virgin) {
unsigned sym, bits;
static code *next;
/* literal/length table */
sym = 0;
while (sym < 144) state->lens[sym++] = 8;
while (sym < 256) state->lens[sym++] = 9;
while (sym < 280) state->lens[sym++] = 7;
while (sym < 288) state->lens[sym++] = 8;
next = fixed;
lenfix = next;
bits = 9;
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
/* distance table */
sym = 0;
while (sym < 32) state->lens[sym++] = 5;
distfix = next;
bits = 5;
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
/* do this just once */
virgin = 0;
}
#else /* !BUILDFIXED */
# include "inffixed.h"
#endif /* BUILDFIXED */
state->lencode = lenfix;
state->lenbits = 9;
state->distcode = distfix;
state->distbits = 5;
}
/* Macros for inflateBack(): */
/* Load returned state from inflate_fast() */
#define LOAD() \
do { \
put = strm->next_out; \
left = strm->avail_out; \
next = strm->next_in; \
have = strm->avail_in; \
hold = state->hold; \
bits = state->bits; \
} while (0)
/* Set state from registers for inflate_fast() */
#define RESTORE() \
do { \
strm->next_out = put; \
strm->avail_out = left; \
strm->next_in = next; \
strm->avail_in = have; \
state->hold = hold; \
state->bits = bits; \
} while (0)
/* Clear the input bit accumulator */
#define INITBITS() \
do { \
hold = 0; \
bits = 0; \
} while (0)
/* Assure that some input is available. If input is requested, but denied,
then return a Z_BUF_ERROR from inflateBack(). */
#define PULL() \
do { \
if (have == 0) { \
have = in(in_desc, &next); \
if (have == 0) { \
next = Z_NULL; \
ret = Z_BUF_ERROR; \
goto inf_leave; \
} \
} \
} while (0)
/* Get a byte of input into the bit accumulator, or return from inflateBack()
with an error if there is no input available. */
#define PULLBYTE() \
do { \
PULL(); \
have--; \
hold += (unsigned long)(*next++) << bits; \
bits += 8; \
} while (0)
/* Assure that there are at least n bits in the bit accumulator. If there is
not enough available input to do that, then return from inflateBack() with
an error. */
#define NEEDBITS(n) \
do { \
while (bits < (unsigned)(n)) \
PULLBYTE(); \
} while (0)
/* Return the low n bits of the bit accumulator (n < 16) */
#define BITS(n) \
((unsigned)hold & ((1U << (n)) - 1))
/* Remove n bits from the bit accumulator */
#define DROPBITS(n) \
do { \
hold >>= (n); \
bits -= (unsigned)(n); \
} while (0)
/* Remove zero to seven bits as needed to go to a byte boundary */
#define BYTEBITS() \
do { \
hold >>= bits & 7; \
bits -= bits & 7; \
} while (0)
/* Assure that some output space is available, by writing out the window
if it's full. If the write fails, return from inflateBack() with a
Z_BUF_ERROR. */
#define ROOM() \
do { \
if (left == 0) { \
put = state->window; \
left = state->wsize; \
state->whave = left; \
if (out(out_desc, put, left)) { \
ret = Z_BUF_ERROR; \
goto inf_leave; \
} \
} \
} while (0)
/*
strm provides the memory allocation functions and window buffer on input,
and provides information on the unused input on return. For Z_DATA_ERROR
returns, strm will also provide an error message.
in() and out() are the call-back input and output functions. When
inflateBack() needs more input, it calls in(). When inflateBack() has
filled the window with output, or when it completes with data in the
window, it calls out() to write out the data. The application must not
change the provided input until in() is called again or inflateBack()
returns. The application must not change the window/output buffer until
inflateBack() returns.
in() and out() are called with a descriptor parameter provided in the
inflateBack() call. This parameter can be a structure that provides the
information required to do the read or write, as well as accumulated
information on the input and output such as totals and check values.
in() should return zero on failure. out() should return non-zero on
failure. If either in() or out() fails, than inflateBack() returns a
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
was in() or out() that caused in the error. Otherwise, inflateBack()
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
error, or Z_MEM_ERROR if it could not allocate memory for the state.
inflateBack() can also return Z_STREAM_ERROR if the input parameters
are not correct, i.e. strm is Z_NULL or the state was not initialized.
*/
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
z_streamp strm;
in_func in;
void FAR *in_desc;
out_func out;
void FAR *out_desc;
{
struct inflate_state FAR *state;
z_const unsigned char FAR *next; /* next input */
unsigned char FAR *put; /* next output */
unsigned have, left; /* available input and output */
unsigned long hold; /* bit buffer */
unsigned bits; /* bits in bit buffer */
unsigned copy; /* number of stored or match bytes to copy */
unsigned char FAR *from; /* where to copy match bytes from */
code here; /* current decoding table entry */
code last; /* parent table entry */
unsigned len; /* length to copy for repeats, bits to drop */
int ret; /* return code */
static const unsigned short order[19] = /* permutation of code lengths */
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
/* Check that the strm exists and that the state was initialized */
if (strm == Z_NULL || strm->state == Z_NULL)
return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
/* Reset the state */
strm->msg = Z_NULL;
state->mode = TYPE;
state->last = 0;
state->whave = 0;
next = strm->next_in;
have = next != Z_NULL ? strm->avail_in : 0;
hold = 0;
bits = 0;
put = state->window;
left = state->wsize;
/* Inflate until end of block marked as last */
for (;;)
switch (state->mode) {
case TYPE:
/* determine and dispatch block type */
if (state->last) {
BYTEBITS();
state->mode = DONE;
break;
}
NEEDBITS(3);
state->last = BITS(1);
DROPBITS(1);
switch (BITS(2)) {
case 0: /* stored block */
Tracev((stderr, "inflate: stored block%s\n",
state->last ? " (last)" : ""));
state->mode = STORED;
break;
case 1: /* fixed block */
fixedtables(state);
Tracev((stderr, "inflate: fixed codes block%s\n",
state->last ? " (last)" : ""));
state->mode = LEN; /* decode codes */
break;
case 2: /* dynamic block */
Tracev((stderr, "inflate: dynamic codes block%s\n",
state->last ? " (last)" : ""));
state->mode = TABLE;
break;
case 3:
strm->msg = (char *)"invalid block type";
state->mode = BAD;
}
DROPBITS(2);
break;
case STORED:
/* get and verify stored block length */
BYTEBITS(); /* go to byte boundary */
NEEDBITS(32);
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
strm->msg = (char *)"invalid stored block lengths";
state->mode = BAD;
break;
}
state->length = (unsigned)hold & 0xffff;
Tracev((stderr, "inflate: stored length %u\n",
state->length));
INITBITS();
/* copy stored block from input to output */
while (state->length != 0) {
copy = state->length;
PULL();
ROOM();
if (copy > have) copy = have;
if (copy > left) copy = left;
zmemcpy(put, next, copy);
have -= copy;
next += copy;
left -= copy;
put += copy;
state->length -= copy;
}
Tracev((stderr, "inflate: stored end\n"));
state->mode = TYPE;
break;
case TABLE:
/* get dynamic table entries descriptor */
NEEDBITS(14);
state->nlen = BITS(5) + 257;
DROPBITS(5);
state->ndist = BITS(5) + 1;
DROPBITS(5);
state->ncode = BITS(4) + 4;
DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
if (state->nlen > 286 || state->ndist > 30) {
strm->msg = (char *)"too many length or distance symbols";
state->mode = BAD;
break;
}
#endif
Tracev((stderr, "inflate: table sizes ok\n"));
/* get code length code lengths (not a typo) */
state->have = 0;
while (state->have < state->ncode) {
NEEDBITS(3);
state->lens[order[state->have++]] = (unsigned short)BITS(3);
DROPBITS(3);
}
while (state->have < 19)
state->lens[order[state->have++]] = 0;
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 7;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid code lengths set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: code lengths ok\n"));
/* get length and distance code code lengths */
state->have = 0;
while (state->have < state->nlen + state->ndist) {
for (;;) {
here = state->lencode[BITS(state->lenbits)];
if ((unsigned)(here.bits) <= bits) break;
PULLBYTE();
}
if (here.val < 16) {
DROPBITS(here.bits);
state->lens[state->have++] = here.val;
}
else {
if (here.val == 16) {
NEEDBITS(here.bits + 2);
DROPBITS(here.bits);
if (state->have == 0) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
len = (unsigned)(state->lens[state->have - 1]);
copy = 3 + BITS(2);
DROPBITS(2);
}
else if (here.val == 17) {
NEEDBITS(here.bits + 3);
DROPBITS(here.bits);
len = 0;
copy = 3 + BITS(3);
DROPBITS(3);
}
else {
NEEDBITS(here.bits + 7);
DROPBITS(here.bits);
len = 0;
copy = 11 + BITS(7);
DROPBITS(7);
}
if (state->have + copy > state->nlen + state->ndist) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
while (copy--)
state->lens[state->have++] = (unsigned short)len;
}
}
/* handle error breaks in while */
if (state->mode == BAD) break;
/* check for end-of-block code (better have one) */
if (state->lens[256] == 0) {
strm->msg = (char *)"invalid code -- missing end-of-block";
state->mode = BAD;
break;
}
/* build code tables -- note: do not change the lenbits or distbits
values here (9 and 6) without reading the comments in inftrees.h
concerning the ENOUGH constants, which depend on those values */
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 9;
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid literal/lengths set";
state->mode = BAD;
break;
}
state->distcode = (code const FAR *)(state->next);
state->distbits = 6;
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
&(state->next), &(state->distbits), state->work);
if (ret) {
strm->msg = (char *)"invalid distances set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN;
case LEN:
/* use inflate_fast() if we have enough input and output */
if (have >= 6 && left >= 258) {
RESTORE();
if (state->whave < state->wsize)
state->whave = state->wsize - left;
inflate_fast(strm, state->wsize);
LOAD();
break;
}
/* get a literal, length, or end-of-block code */
for (;;) {
here = state->lencode[BITS(state->lenbits)];
if ((unsigned)(here.bits) <= bits) break;
PULLBYTE();
}
if (here.op && (here.op & 0xf0) == 0) {
last = here;
for (;;) {
here = state->lencode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + here.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(here.bits);
state->length = (unsigned)here.val;
/* process literal */
if (here.op == 0) {
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", here.val));
ROOM();
*put++ = (unsigned char)(state->length);
left--;
state->mode = LEN;
break;
}
/* process end of block */
if (here.op & 32) {
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}
/* invalid code */
if (here.op & 64) {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}
/* length code -- get extra bits, if any */
state->extra = (unsigned)(here.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->length += BITS(state->extra);
DROPBITS(state->extra);
}
Tracevv((stderr, "inflate: length %u\n", state->length));
/* get distance code */
for (;;) {
here = state->distcode[BITS(state->distbits)];
if ((unsigned)(here.bits) <= bits) break;
PULLBYTE();
}
if ((here.op & 0xf0) == 0) {
last = here;
for (;;) {
here = state->distcode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + here.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(here.bits);
if (here.op & 64) {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
state->offset = (unsigned)here.val;
/* get distance extra bits, if any */
state->extra = (unsigned)(here.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->offset += BITS(state->extra);
DROPBITS(state->extra);
}
if (state->offset > state->wsize - (state->whave < state->wsize ?
left : 0)) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
Tracevv((stderr, "inflate: distance %u\n", state->offset));
/* copy match from window to output */
do {
ROOM();
copy = state->wsize - state->offset;
if (copy < left) {
from = put + copy;
copy = left - copy;
}
else {
from = put - state->offset;
copy = left;
}
if (copy > state->length) copy = state->length;
state->length -= copy;
left -= copy;
do {
*put++ = *from++;
} while (--copy);
} while (state->length != 0);
break;
case DONE:
/* inflate stream terminated properly -- write leftover output */
ret = Z_STREAM_END;
if (left < state->wsize) {
if (out(out_desc, state->window, state->wsize - left))
ret = Z_BUF_ERROR;
}
goto inf_leave;
case BAD:
ret = Z_DATA_ERROR;
goto inf_leave;
default: /* can't happen, but makes compilers happy */
ret = Z_STREAM_ERROR;
goto inf_leave;
}
/* Return unused input */
inf_leave:
strm->next_in = next;
strm->avail_in = have;
return ret;
}
int ZEXPORT inflateBackEnd(strm)
z_streamp strm;
{
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR;
ZFREE(strm, strm->state);
strm->state = Z_NULL;
Tracev((stderr, "inflate: end\n"));
return Z_OK;
}

340
deps/zlib/inffast.c vendored Normal file
View file

@ -0,0 +1,340 @@
/* inffast.c -- fast decoding
* Copyright (C) 1995-2008, 2010, 2013 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
#ifndef ASMINF
/* Allow machine dependent optimization for post-increment or pre-increment.
Based on testing to date,
Pre-increment preferred for:
- PowerPC G3 (Adler)
- MIPS R5000 (Randers-Pehrson)
Post-increment preferred for:
- none
No measurable difference:
- Pentium III (Anderson)
- M68060 (Nikl)
*/
#ifdef POSTINC
# define OFF 0
# define PUP(a) *(a)++
#else
# define OFF 1
# define PUP(a) *++(a)
#endif
/*
Decode literal, length, and distance codes and write out the resulting
literal and match bytes until either not enough input or output is
available, an end-of-block is encountered, or a data error is encountered.
When large enough input and output buffers are supplied to inflate(), for
example, a 16K input buffer and a 64K output buffer, more than 95% of the
inflate execution time is spent in this routine.
Entry assumptions:
state->mode == LEN
strm->avail_in >= 6
strm->avail_out >= 258
start >= strm->avail_out
state->bits < 8
On return, state->mode is one of:
LEN -- ran out of enough output space or enough available input
TYPE -- reached end of block code, inflate() to interpret next block
BAD -- error in block data
Notes:
- The maximum input bits used by a length/distance pair is 15 bits for the
length code, 5 bits for the length extra, 15 bits for the distance code,
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
Therefore if strm->avail_in >= 6, then there is enough input to avoid
checking for available input while decoding.
- The maximum bytes that a single length/distance pair can output is 258
bytes, which is the maximum length that can be coded. inflate_fast()
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
*/
void ZLIB_INTERNAL inflate_fast(strm, start)
z_streamp strm;
unsigned start; /* inflate()'s starting value for strm->avail_out */
{
struct inflate_state FAR *state;
z_const unsigned char FAR *in; /* local strm->next_in */
z_const unsigned char FAR *last; /* have enough input while in < last */
unsigned char FAR *out; /* local strm->next_out */
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
unsigned char FAR *end; /* while out < end, enough space available */
#ifdef INFLATE_STRICT
unsigned dmax; /* maximum distance from zlib header */
#endif
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned wnext; /* window write index */
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
unsigned long hold; /* local strm->hold */
unsigned bits; /* local strm->bits */
code const FAR *lcode; /* local strm->lencode */
code const FAR *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */
code here; /* retrieved table entry */
unsigned op; /* code bits, operation, extra bits, or */
/* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */
unsigned dist; /* match distance */
unsigned char FAR *from; /* where to copy match from */
/* copy state to local variables */
state = (struct inflate_state FAR *)strm->state;
in = strm->next_in - OFF;
last = in + (strm->avail_in - 5);
out = strm->next_out - OFF;
beg = out - (start - strm->avail_out);
end = out + (strm->avail_out - 257);
#ifdef INFLATE_STRICT
dmax = state->dmax;
#endif
wsize = state->wsize;
whave = state->whave;
wnext = state->wnext;
window = state->window;
hold = state->hold;
bits = state->bits;
lcode = state->lencode;
dcode = state->distcode;
lmask = (1U << state->lenbits) - 1;
dmask = (1U << state->distbits) - 1;
/* decode literals and length/distances until end-of-block or not enough
input data or output space */
do {
if (bits < 15) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
here = lcode[hold & lmask];
dolen:
op = (unsigned)(here.bits);
hold >>= op;
bits -= op;
op = (unsigned)(here.op);
if (op == 0) { /* literal */
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", here.val));
PUP(out) = (unsigned char)(here.val);
}
else if (op & 16) { /* length base */
len = (unsigned)(here.val);
op &= 15; /* number of extra bits */
if (op) {
if (bits < op) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
len += (unsigned)hold & ((1U << op) - 1);
hold >>= op;
bits -= op;
}
Tracevv((stderr, "inflate: length %u\n", len));
if (bits < 15) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
here = dcode[hold & dmask];
dodist:
op = (unsigned)(here.bits);
hold >>= op;
bits -= op;
op = (unsigned)(here.op);
if (op & 16) { /* distance base */
dist = (unsigned)(here.val);
op &= 15; /* number of extra bits */
if (bits < op) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
if (bits < op) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
}
dist += (unsigned)hold & ((1U << op) - 1);
#ifdef INFLATE_STRICT
if (dist > dmax) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#endif
hold >>= op;
bits -= op;
Tracevv((stderr, "inflate: distance %u\n", dist));
op = (unsigned)(out - beg); /* max distance in output */
if (dist > op) { /* see if copy from window */
op = dist - op; /* distance back in window */
if (op > whave) {
if (state->sane) {
strm->msg =
(char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
if (len <= op - whave) {
do {
PUP(out) = 0;
} while (--len);
continue;
}
len -= op - whave;
do {
PUP(out) = 0;
} while (--op > whave);
if (op == 0) {
from = out - dist;
do {
PUP(out) = PUP(from);
} while (--len);
continue;
}
#endif
}
from = window - OFF;
if (wnext == 0) { /* very common case */
from += wsize - op;
if (op < len) { /* some from window */
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = out - dist; /* rest from output */
}
}
else if (wnext < op) { /* wrap around window */
from += wsize + wnext - op;
op -= wnext;
if (op < len) { /* some from end of window */
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = window - OFF;
if (wnext < len) { /* some from start of window */
op = wnext;
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = out - dist; /* rest from output */
}
}
}
else { /* contiguous in window */
from += wnext - op;
if (op < len) { /* some from window */
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = out - dist; /* rest from output */
}
}
while (len > 2) {
PUP(out) = PUP(from);
PUP(out) = PUP(from);
PUP(out) = PUP(from);
len -= 3;
}
if (len) {
PUP(out) = PUP(from);
if (len > 1)
PUP(out) = PUP(from);
}
}
else {
from = out - dist; /* copy direct from output */
do { /* minimum length is three */
PUP(out) = PUP(from);
PUP(out) = PUP(from);
PUP(out) = PUP(from);
len -= 3;
} while (len > 2);
if (len) {
PUP(out) = PUP(from);
if (len > 1)
PUP(out) = PUP(from);
}
}
}
else if ((op & 64) == 0) { /* 2nd level distance code */
here = dcode[here.val + (hold & ((1U << op) - 1))];
goto dodist;
}
else {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
}
else if ((op & 64) == 0) { /* 2nd level length code */
here = lcode[here.val + (hold & ((1U << op) - 1))];
goto dolen;
}
else if (op & 32) { /* end-of-block */
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}
else {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}
} while (in < last && out < end);
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
len = bits >> 3;
in -= len;
bits -= len << 3;
hold &= (1U << bits) - 1;
/* update state and return */
strm->next_in = in + OFF;
strm->next_out = out + OFF;
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
strm->avail_out = (unsigned)(out < end ?
257 + (end - out) : 257 - (out - end));
state->hold = hold;
state->bits = bits;
return;
}
/*
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
- Using bit fields for code structure
- Different op definition to avoid & for extra bits (do & for table bits)
- Three separate decoding do-loops for direct, window, and wnext == 0
- Special case for distance > 1 copies to do overlapped load and store copy
- Explicit branch predictions (based on measured branch probabilities)
- Deferring match copy and interspersed it with decoding subsequent codes
- Swapping literal/length else
- Swapping window/direct else
- Larger unrolled copy loops (three is about right)
- Moving len -= 3 statement into middle of loop
*/
#endif /* !ASMINF */

11
deps/zlib/inffast.h vendored Normal file
View file

@ -0,0 +1,11 @@
/* inffast.h -- header to use inffast.c
* Copyright (C) 1995-2003, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));

94
deps/zlib/inffixed.h vendored Normal file
View file

@ -0,0 +1,94 @@
/* inffixed.h -- table for decoding fixed codes
* Generated automatically by makefixed().
*/
/* WARNING: this file should *not* be used by applications.
It is part of the implementation of this library and is
subject to change. Applications should only use zlib.h.
*/
static const code lenfix[512] = {
{96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
{0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
{0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
{0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
{0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
{21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
{0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
{0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
{18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
{0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
{0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
{0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
{20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
{0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
{0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
{16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
{0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
{0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
{0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
{0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
{0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
{0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
{0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
{17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
{0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
{0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
{0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
{19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
{0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
{0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
{16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
{0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
{0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
{0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
{0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
{20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
{0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
{0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
{17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
{0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
{0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
{0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
{20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
{0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
{0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
{0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
{16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
{0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
{0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
{0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
{0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
{0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
{0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
{0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
{16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
{0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
{0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
{0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
{19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
{0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
{0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
{16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
{0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
{0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
{0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
{0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
{64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
{0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
{0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
{18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
{0,9,255}
};
static const code distfix[32] = {
{16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
{21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
{18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
{19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
{16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
{22,5,193},{64,5,0}
};

1512
deps/zlib/inflate.c vendored Normal file

File diff suppressed because it is too large Load diff

122
deps/zlib/inflate.h vendored Normal file
View file

@ -0,0 +1,122 @@
/* inflate.h -- internal inflate state definition
* Copyright (C) 1995-2009 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* define NO_GZIP when compiling if you want to disable gzip header and
trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
the crc code when it is not needed. For shared libraries, gzip decoding
should be left enabled. */
#ifndef NO_GZIP
# define GUNZIP
#endif
/* Possible inflate modes between inflate() calls */
typedef enum {
HEAD, /* i: waiting for magic header */
FLAGS, /* i: waiting for method and flags (gzip) */
TIME, /* i: waiting for modification time (gzip) */
OS, /* i: waiting for extra flags and operating system (gzip) */
EXLEN, /* i: waiting for extra length (gzip) */
EXTRA, /* i: waiting for extra bytes (gzip) */
NAME, /* i: waiting for end of file name (gzip) */
COMMENT, /* i: waiting for end of comment (gzip) */
HCRC, /* i: waiting for header crc (gzip) */
DICTID, /* i: waiting for dictionary check value */
DICT, /* waiting for inflateSetDictionary() call */
TYPE, /* i: waiting for type bits, including last-flag bit */
TYPEDO, /* i: same, but skip check to exit inflate on new block */
STORED, /* i: waiting for stored size (length and complement) */
COPY_, /* i/o: same as COPY below, but only first time in */
COPY, /* i/o: waiting for input or output to copy stored block */
TABLE, /* i: waiting for dynamic block table lengths */
LENLENS, /* i: waiting for code length code lengths */
CODELENS, /* i: waiting for length/lit and distance code lengths */
LEN_, /* i: same as LEN below, but only first time in */
LEN, /* i: waiting for length/lit/eob code */
LENEXT, /* i: waiting for length extra bits */
DIST, /* i: waiting for distance code */
DISTEXT, /* i: waiting for distance extra bits */
MATCH, /* o: waiting for output space to copy string */
LIT, /* o: waiting for output space to write literal */
CHECK, /* i: waiting for 32-bit check value */
LENGTH, /* i: waiting for 32-bit length (gzip) */
DONE, /* finished check, done -- remain here until reset */
BAD, /* got a data error -- remain here until reset */
MEM, /* got an inflate() memory error -- remain here until reset */
SYNC /* looking for synchronization bytes to restart inflate() */
} inflate_mode;
/*
State transitions between above modes -
(most modes can go to BAD or MEM on error -- not shown for clarity)
Process header:
HEAD -> (gzip) or (zlib) or (raw)
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
HCRC -> TYPE
(zlib) -> DICTID or TYPE
DICTID -> DICT -> TYPE
(raw) -> TYPEDO
Read deflate blocks:
TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
STORED -> COPY_ -> COPY -> TYPE
TABLE -> LENLENS -> CODELENS -> LEN_
LEN_ -> LEN
Read deflate codes in fixed or dynamic block:
LEN -> LENEXT or LIT or TYPE
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
LIT -> LEN
Process trailer:
CHECK -> LENGTH -> DONE
*/
/* state maintained between inflate() calls. Approximately 10K bytes. */
struct inflate_state {
inflate_mode mode; /* current inflate mode */
int last; /* true if processing last block */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
int havedict; /* true if dictionary provided */
int flags; /* gzip header method and flags (0 if zlib) */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */
gz_headerp head; /* where to save gzip header information */
/* sliding window */
unsigned wbits; /* log base 2 of requested window size */
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned wnext; /* window write index */
unsigned char FAR *window; /* allocated sliding window, if needed */
/* bit accumulator */
unsigned long hold; /* input bit accumulator */
unsigned bits; /* number of bits in "in" */
/* for string and stored block copying */
unsigned length; /* literal or length of data to copy */
unsigned offset; /* distance back to copy string from */
/* for table and code decoding */
unsigned extra; /* extra bits needed */
/* fixed and dynamic code tables */
code const FAR *lencode; /* starting table for length/literal codes */
code const FAR *distcode; /* starting table for distance codes */
unsigned lenbits; /* index bits for lencode */
unsigned distbits; /* index bits for distcode */
/* dynamic table building */
unsigned ncode; /* number of code length code lengths */
unsigned nlen; /* number of length code lengths */
unsigned ndist; /* number of distance code lengths */
unsigned have; /* number of code lengths in lens[] */
code FAR *next; /* next available space in codes[] */
unsigned short lens[320]; /* temporary storage for code lengths */
unsigned short work[288]; /* work area for code table building */
code codes[ENOUGH]; /* space for code tables */
int sane; /* if false, allow invalid distance too far */
int back; /* bits back of last unprocessed length/lit */
unsigned was; /* initial length of match */
};

306
deps/zlib/inftrees.c vendored Normal file
View file

@ -0,0 +1,306 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2013 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#define MAXBITS 15
const char inflate_copyright[] =
" inflate 1.2.8 Copyright 1995-2013 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
include such an acknowledgment, I would appreciate that you keep this
copyright string in the executable of your product.
*/
/*
Build a set of tables to decode the provided canonical Huffman code.
The code lengths are lens[0..codes-1]. The result starts at *table,
whose indices are 0..2^bits-1. work is a writable array of at least
lens shorts, which is used as a work area. type is the type of code
to be generated, CODES, LENS, or DISTS. On return, zero is success,
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
on return points to the next available entry's address. bits is the
requested root table index bits, and on return it is the actual root
table index bits. It will differ if the request is greater than the
longest code or if it is less than the shortest code.
*/
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
codetype type;
unsigned short FAR *lens;
unsigned codes;
code FAR * FAR *table;
unsigned FAR *bits;
unsigned short FAR *work;
{
unsigned len; /* a code's length in bits */
unsigned sym; /* index of code symbols */
unsigned min, max; /* minimum and maximum code lengths */
unsigned root; /* number of index bits for root table */
unsigned curr; /* number of index bits for current table */
unsigned drop; /* code bits to drop for sub-table */
int left; /* number of prefix codes available */
unsigned used; /* code entries in table used */
unsigned huff; /* Huffman code */
unsigned incr; /* for incrementing code, index */
unsigned fill; /* index for replicating entries */
unsigned low; /* low bits for current root entry */
unsigned mask; /* mask for low root bits */
code here; /* table entry for duplication */
code FAR *next; /* next available space in table */
const unsigned short FAR *base; /* base value table to use */
const unsigned short FAR *extra; /* extra bits table to use */
int end; /* use base and extra for symbol > end */
unsigned short count[MAXBITS+1]; /* number of codes of each length */
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
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 unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577, 0, 0};
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
28, 28, 29, 29, 64, 64};
/*
Process a set of code lengths to create a canonical Huffman code. The
code lengths are lens[0..codes-1]. Each length corresponds to the
symbols 0..codes-1. The Huffman code is generated by first sorting the
symbols by length from short to long, and retaining the symbol order
for codes with equal lengths. Then the code starts with all zero bits
for the first code of the shortest length, and the codes are integer
increments for the same length, and zeros are appended as the length
increases. For the deflate format, these bits are stored backwards
from their more natural integer increment ordering, and so when the
decoding tables are built in the large loop below, the integer codes
are incremented backwards.
This routine assumes, but does not check, that all of the entries in
lens[] are in the range 0..MAXBITS. The caller must assure this.
1..MAXBITS is interpreted as that code length. zero means that that
symbol does not occur in this code.
The codes are sorted by computing a count of codes for each length,
creating from that a table of starting indices for each length in the
sorted table, and then entering the symbols in order in the sorted
table. The sorted table is work[], with that space being provided by
the caller.
The length counts are used for other purposes as well, i.e. finding
the minimum and maximum length codes, determining if there are any
codes at all, checking for a valid set of lengths, and looking ahead
at length counts to determine sub-table sizes when building the
decoding tables.
*/
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
for (len = 0; len <= MAXBITS; len++)
count[len] = 0;
for (sym = 0; sym < codes; sym++)
count[lens[sym]]++;
/* bound code lengths, force root to be within code lengths */
root = *bits;
for (max = MAXBITS; max >= 1; max--)
if (count[max] != 0) break;
if (root > max) root = max;
if (max == 0) { /* no symbols to code at all */
here.op = (unsigned char)64; /* invalid code marker */
here.bits = (unsigned char)1;
here.val = (unsigned short)0;
*(*table)++ = here; /* make a table to force an error */
*(*table)++ = here;
*bits = 1;
return 0; /* no symbols, but wait for decoding to report error */
}
for (min = 1; min < max; min++)
if (count[min] != 0) break;
if (root < min) root = min;
/* check for an over-subscribed or incomplete set of lengths */
left = 1;
for (len = 1; len <= MAXBITS; len++) {
left <<= 1;
left -= count[len];
if (left < 0) return -1; /* over-subscribed */
}
if (left > 0 && (type == CODES || max != 1))
return -1; /* incomplete set */
/* generate offsets into symbol table for each length for sorting */
offs[1] = 0;
for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + count[len];
/* sort symbols by length, by symbol order within each length */
for (sym = 0; sym < codes; sym++)
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
/*
Create and fill in decoding tables. In this loop, the table being
filled is at next and has curr index bits. The code being used is huff
with length len. That code is converted to an index by dropping drop
bits off of the bottom. For codes where len is less than drop + curr,
those top drop + curr - len bits are incremented through all values to
fill the table with replicated entries.
root is the number of index bits for the root table. When len exceeds
root, sub-tables are created pointed to by the root entry with an index
of the low root bits of huff. This is saved in low to check for when a
new sub-table should be started. drop is zero when the root table is
being filled, and drop is root when sub-tables are being filled.
When a new sub-table is needed, it is necessary to look ahead in the
code lengths to determine what size sub-table is needed. The length
counts are used for this, and so count[] is decremented as codes are
entered in the tables.
used keeps track of how many table entries have been allocated from the
provided *table space. It is checked for LENS and DIST tables against
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
the initial root table size constants. See the comments in inftrees.h
for more information.
sym increments through all symbols, and the loop terminates when
all codes of length max, i.e. all codes, have been processed. This
routine permits incomplete codes, so another loop after this one fills
in the rest of the decoding tables with invalid code markers.
*/
/* set up for code type */
switch (type) {
case CODES:
base = extra = work; /* dummy value--not used */
end = 19;
break;
case LENS:
base = lbase;
base -= 257;
extra = lext;
extra -= 257;
end = 256;
break;
default: /* DISTS */
base = dbase;
extra = dext;
end = -1;
}
/* initialize state for loop */
huff = 0; /* starting code */
sym = 0; /* starting code symbol */
len = min; /* starting code length */
next = *table; /* current table to fill in */
curr = root; /* current table index bits */
drop = 0; /* current bits to drop from code for index */
low = (unsigned)(-1); /* trigger new sub-table when len > root */
used = 1U << root; /* use root table entries */
mask = used - 1; /* mask for comparing low */
/* check available table space */
if ((type == LENS && used > ENOUGH_LENS) ||
(type == DISTS && used > ENOUGH_DISTS))
return 1;
/* process all codes and make table entries */
for (;;) {
/* create table entry */
here.bits = (unsigned char)(len - drop);
if ((int)(work[sym]) < end) {
here.op = (unsigned char)0;
here.val = work[sym];
}
else if ((int)(work[sym]) > end) {
here.op = (unsigned char)(extra[work[sym]]);
here.val = base[work[sym]];
}
else {
here.op = (unsigned char)(32 + 64); /* end of block */
here.val = 0;
}
/* replicate for those indices with low len bits equal to huff */
incr = 1U << (len - drop);
fill = 1U << curr;
min = fill; /* save offset to next table */
do {
fill -= incr;
next[(huff >> drop) + fill] = here;
} while (fill != 0);
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
/* go to next symbol, update count, len */
sym++;
if (--(count[len]) == 0) {
if (len == max) break;
len = lens[work[sym]];
}
/* create new sub-table if needed */
if (len > root && (huff & mask) != low) {
/* if first time, transition to sub-tables */
if (drop == 0)
drop = root;
/* increment past last table */
next += min; /* here min is 1 << curr */
/* determine length of next table */
curr = len - drop;
left = (int)(1 << curr);
while (curr + drop < max) {
left -= count[curr + drop];
if (left <= 0) break;
curr++;
left <<= 1;
}
/* check for enough space */
used += 1U << curr;
if ((type == LENS && used > ENOUGH_LENS) ||
(type == DISTS && used > ENOUGH_DISTS))
return 1;
/* point entry in root table to sub-table */
low = huff & mask;
(*table)[low].op = (unsigned char)curr;
(*table)[low].bits = (unsigned char)root;
(*table)[low].val = (unsigned short)(next - *table);
}
}
/* fill in remaining table entry if code is incomplete (guaranteed to have
at most one remaining entry, since if the code is incomplete, the
maximum code length that was allowed to get this far is one bit) */
if (huff != 0) {
here.op = (unsigned char)64; /* invalid code marker */
here.bits = (unsigned char)(len - drop);
here.val = (unsigned short)0;
next[huff] = here;
}
/* set return parameters */
*table += used;
*bits = root;
return 0;
}

62
deps/zlib/inftrees.h vendored Normal file
View file

@ -0,0 +1,62 @@
/* inftrees.h -- header to use inftrees.c
* Copyright (C) 1995-2005, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* Structure for decoding tables. Each entry provides either the
information needed to do the operation requested by the code that
indexed that table entry, or it provides a pointer to another
table that indexes more bits of the code. op indicates whether
the entry is a pointer to another table, a literal, a length or
distance, an end-of-block, or an invalid code. For a table
pointer, the low four bits of op is the number of index bits of
that table. For a length or distance, the low four bits of op
is the number of extra bits to get after the code. bits is
the number of bits in this code or part of the code to drop off
of the bit buffer. val is the actual byte to output in the case
of a literal, the base length or distance, or the offset from
the current table to the next table. Each entry is four bytes. */
typedef struct {
unsigned char op; /* operation, extra bits, table bits */
unsigned char bits; /* bits in this part of the code */
unsigned short val; /* offset in table or code value */
} code;
/* op values as set by inflate_table():
00000000 - literal
0000tttt - table link, tttt != 0 is the number of table index bits
0001eeee - length or distance, eeee is the number of extra bits
01100000 - end of block
01000000 - invalid code
*/
/* Maximum size of the dynamic table. The maximum number of code structures is
1444, which is the sum of 852 for literal/length codes and 592 for distance
codes. These values were found by exhaustive searches using the program
examples/enough.c found in the zlib distribtution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes
returns returns 852, and "enough 30 6 15" for distance codes returns 592.
The initial root table size (9 or 6) is found in the fifth argument of the
inflate_table() calls in inflate.c and infback.c. If the root table size is
changed, then these maximum sizes would be need to be recalculated and
updated. */
#define ENOUGH_LENS 852
#define ENOUGH_DISTS 592
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
/* Type of code to build for inflate_table() */
typedef enum {
CODES,
LENS,
DISTS
} codetype;
int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
unsigned codes, code FAR * FAR *table,
unsigned FAR *bits, unsigned short FAR *work));

1226
deps/zlib/trees.c vendored Normal file

File diff suppressed because it is too large Load diff

128
deps/zlib/trees.h vendored Normal file
View file

@ -0,0 +1,128 @@
/* header created automatically with -DGEN_TREES_H */
local const ct_data static_ltree[L_CODES+2] = {
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
};
local const ct_data static_dtree[D_CODES] = {
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
};
const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
};
const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
};
local const int base_length[LENGTH_CODES] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
64, 80, 96, 112, 128, 160, 192, 224, 0
};
local const int base_dist[D_CODES] = {
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
};

59
deps/zlib/uncompr.c vendored Normal file
View file

@ -0,0 +1,59 @@
/* uncompr.c -- decompress a memory buffer
* Copyright (C) 1995-2003, 2010 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#define ZLIB_INTERNAL
#include "zlib.h"
/* ===========================================================================
Decompresses the source buffer into the destination buffer. sourceLen is
the byte length of the source buffer. Upon entry, destLen is the total
size of the destination buffer, which must be large enough to hold the
entire uncompressed data. (The size of the uncompressed data must have
been saved previously by the compressor and transmitted to the decompressor
by some mechanism outside the scope of this compression library.)
Upon exit, destLen is the actual size of the compressed buffer.
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer, or Z_DATA_ERROR if the input data was corrupted.
*/
int ZEXPORT uncompress (dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
{
z_stream stream;
int err;
stream.next_in = (z_const Bytef *)source;
stream.avail_in = (uInt)sourceLen;
/* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
stream.next_out = dest;
stream.avail_out = (uInt)*destLen;
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
err = inflateInit(&stream);
if (err != Z_OK) return err;
err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
inflateEnd(&stream);
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
return Z_DATA_ERROR;
return err;
}
*destLen = stream.total_out;
err = inflateEnd(&stream);
return err;
}

Some files were not shown because too many files have changed in this diff Show more