Compare commits
3 Commits
v1.5.2
...
bug/30_ser
Author | SHA1 | Date | |
---|---|---|---|
b1c1e6e28d | |||
66440e2330 | |||
792610d44f |
@ -1,3 +1 @@
|
||||
build
|
||||
CMakeCache.txt
|
||||
ws/CMakeCache.txt
|
||||
|
@ -26,7 +26,6 @@ set( IXWEBSOCKET_SOURCES
|
||||
ixwebsocket/IXSocketFactory.cpp
|
||||
ixwebsocket/IXDNSLookup.cpp
|
||||
ixwebsocket/IXCancellationRequest.cpp
|
||||
ixwebsocket/IXNetSystem.cpp
|
||||
ixwebsocket/IXWebSocket.cpp
|
||||
ixwebsocket/IXWebSocketServer.cpp
|
||||
ixwebsocket/IXWebSocketTransport.cpp
|
||||
@ -37,7 +36,6 @@ set( IXWEBSOCKET_SOURCES
|
||||
ixwebsocket/IXWebSocketHttpHeaders.cpp
|
||||
ixwebsocket/IXHttpClient.cpp
|
||||
ixwebsocket/IXUrlParser.cpp
|
||||
ixwebsocket/LUrlParser.cpp
|
||||
ixwebsocket/IXSelectInterrupt.cpp
|
||||
ixwebsocket/IXSelectInterruptFactory.cpp
|
||||
ixwebsocket/IXConnectionState.cpp
|
||||
@ -51,7 +49,6 @@ set( IXWEBSOCKET_HEADERS
|
||||
ixwebsocket/IXSetThreadName.h
|
||||
ixwebsocket/IXDNSLookup.h
|
||||
ixwebsocket/IXCancellationRequest.h
|
||||
ixwebsocket/IXNetSystem.h
|
||||
ixwebsocket/IXProgressCallback.h
|
||||
ixwebsocket/IXWebSocket.h
|
||||
ixwebsocket/IXWebSocketServer.h
|
||||
@ -66,7 +63,6 @@ set( IXWEBSOCKET_HEADERS
|
||||
ixwebsocket/libwshandshake.hpp
|
||||
ixwebsocket/IXHttpClient.h
|
||||
ixwebsocket/IXUrlParser.h
|
||||
ixwebsocket/LUrlParser.h
|
||||
ixwebsocket/IXSelectInterrupt.h
|
||||
ixwebsocket/IXSelectInterruptFactory.h
|
||||
ixwebsocket/IXConnectionState.h
|
||||
@ -115,7 +111,7 @@ if (APPLE AND USE_TLS)
|
||||
target_link_libraries(ixwebsocket "-framework foundation" "-framework security")
|
||||
endif()
|
||||
|
||||
if (USE_OPEN_SSL)
|
||||
if(USE_OPEN_SSL)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
add_definitions(${OPENSSL_DEFINITIONS})
|
||||
message(STATUS "OpenSSL: " ${OPENSSL_VERSION})
|
||||
@ -124,9 +120,16 @@ if (USE_OPEN_SSL)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
add_subdirectory(third_party/zlib)
|
||||
include_directories(third_party/zlib ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib)
|
||||
target_link_libraries(ixwebsocket zlibstatic wsock32 ws2_32)
|
||||
get_filename_component(libz_path
|
||||
${PROJECT_SOURCE_DIR}/third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.lib
|
||||
ABSOLUTE)
|
||||
add_library(libz STATIC IMPORTED)
|
||||
set_target_properties(libz PROPERTIES IMPORTED_LOCATION
|
||||
${libz_path})
|
||||
|
||||
include_directories(${PROJECT_SOURCE_DIR}/third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/include)
|
||||
|
||||
target_link_libraries(ixwebsocket libz wsock32 ws2_32)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
else()
|
||||
@ -141,20 +144,8 @@ set( IXWEBSOCKET_INCLUDE_DIRS
|
||||
.
|
||||
)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
# Build with Multiple Processes
|
||||
target_compile_options(ixwebsocket PRIVATE /MP)
|
||||
endif()
|
||||
|
||||
target_include_directories( ixwebsocket PUBLIC ${IXWEBSOCKET_INCLUDE_DIRS} )
|
||||
|
||||
set_target_properties(ixwebsocket PROPERTIES PUBLIC_HEADER "${IXWEBSOCKET_HEADERS}")
|
||||
|
||||
install(TARGETS ixwebsocket
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_PREFIX}/include/ixwebsocket/
|
||||
)
|
||||
|
||||
if (NOT WIN32)
|
||||
add_subdirectory(ws)
|
||||
endif()
|
||||
|
@ -1 +1 @@
|
||||
1.4.3
|
||||
1.4.0
|
||||
|
@ -1 +0,0 @@
|
||||
docker/Dockerfile.fedora
|
47
Dockerfile
Normal file
47
Dockerfile
Normal file
@ -0,0 +1,47 @@
|
||||
# Build time
|
||||
FROM debian:buster as build
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN apt-get update
|
||||
RUN apt-get -y install wget
|
||||
RUN mkdir -p /tmp/cmake
|
||||
WORKDIR /tmp/cmake
|
||||
RUN wget https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0-Linux-x86_64.tar.gz
|
||||
RUN tar zxf cmake-3.14.0-Linux-x86_64.tar.gz
|
||||
|
||||
RUN apt-get -y install g++
|
||||
RUN apt-get -y install libssl-dev
|
||||
RUN apt-get -y install libz-dev
|
||||
RUN apt-get -y install make
|
||||
|
||||
COPY . .
|
||||
|
||||
ARG CMAKE_BIN_PATH=/tmp/cmake/cmake-3.14.0-Linux-x86_64/bin
|
||||
ENV PATH="${CMAKE_BIN_PATH}:${PATH}"
|
||||
|
||||
RUN ["make"]
|
||||
|
||||
# Runtime
|
||||
FROM debian:buster as runtime
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN apt-get update
|
||||
# Runtime
|
||||
RUN apt-get install -y libssl1.1
|
||||
|
||||
# Debugging
|
||||
RUN apt-get install -y strace
|
||||
RUN apt-get install -y gdb
|
||||
RUN apt-get install -y procps
|
||||
RUN apt-get install -y htop
|
||||
|
||||
RUN adduser --disabled-password --gecos '' app
|
||||
COPY --chown=app:app --from=build /usr/local/bin/ws /usr/local/bin/ws
|
||||
RUN chmod +x /usr/local/bin/ws
|
||||
RUN ldd /usr/local/bin/ws
|
||||
|
||||
# Now run in usermode
|
||||
USER app
|
||||
WORKDIR /home/app
|
||||
|
||||
CMD ["ws"]
|
50
README.md
50
README.md
@ -10,7 +10,8 @@
|
||||
* iOS
|
||||
* Linux
|
||||
* Android
|
||||
* Windows (no TLS)
|
||||
|
||||
The code was made to compile once on Windows but support is currently broken on this platform.
|
||||
|
||||
## Examples
|
||||
|
||||
@ -34,8 +35,8 @@ webSocket.setOnMessageCallback(
|
||||
const std::string& str,
|
||||
size_t wireSize,
|
||||
const ix::WebSocketErrorInfo& error,
|
||||
const ix::WebSocketOpenInfo& openInfo,
|
||||
const ix::WebSocketCloseInfo& closeInfo)
|
||||
const ix::WebSocketCloseInfo& closeInfo,
|
||||
const ix::WebSocketHttpHeaders& headers)
|
||||
{
|
||||
if (messageType == ix::WebSocket_MessageType_Message)
|
||||
{
|
||||
@ -186,36 +187,11 @@ auto downloadSize = std::get<6>(out);
|
||||
|
||||
## Build
|
||||
|
||||
CMakefiles for the library and the examples are available. This library has few dependencies, so it is possible to just add the source files into your project. Otherwise the usual way will suffice.
|
||||
CMakefiles for the library and the examples are available. This library has few dependencies, so it is possible to just add the source files into your project.
|
||||
|
||||
```
|
||||
mkdir build # make a build dir so that you can build out of tree.
|
||||
cd build
|
||||
cmake ..
|
||||
make -j
|
||||
make install # will install to /usr/local on Unix, on macOS it is a good idea to sudo chown -R `whoami`:staff /usr/local
|
||||
```
|
||||
There is a Dockerfile for running some code on Linux, and a unittest which can be executed by typing `make test`.
|
||||
|
||||
Headers and a static library will be installed to the target dir.
|
||||
|
||||
A [conan](https://conan.io/) file is available at [conan-IXWebSocket](https://github.com/Zinnion/conan-IXWebSocket).
|
||||
|
||||
There is a unittest which can be executed by typing `make test`.
|
||||
|
||||
There is a Dockerfile for running some code on Linux. To use docker-compose you must make a docker container first.
|
||||
|
||||
```
|
||||
$ make docker
|
||||
...
|
||||
$ docker compose up &
|
||||
...
|
||||
$ docker exec -it ixwebsocket_ws_1 bash
|
||||
app@ca2340eb9106:~$ ws --help
|
||||
ws is a websocket tool
|
||||
...
|
||||
```
|
||||
|
||||
Finally you can build and install the `ws command line tool` with Homebrew. The homebrew version might be slightly out of date.
|
||||
You can build and install the ws command line tool with Homebrew.
|
||||
|
||||
```
|
||||
brew tap bsergean/IXWebSocket
|
||||
@ -316,8 +292,8 @@ webSocket.setOnMessageCallback(
|
||||
const std::string& str,
|
||||
size_t wireSize,
|
||||
const ix::WebSocketErrorInfo& error,
|
||||
const ix::WebSocketOpenInfo& openInfo,
|
||||
const ix::WebSocketCloseInfo& closeInfo)
|
||||
const ix::WebSocketCloseInfo& closeInfo,
|
||||
const ix::WebSocketHttpHeaders& headers)
|
||||
{
|
||||
if (messageType == ix::WebSocket_MessageType_Open)
|
||||
{
|
||||
@ -353,8 +329,8 @@ webSocket.setOnMessageCallback(
|
||||
const std::string& str,
|
||||
size_t wireSize,
|
||||
const ix::WebSocketErrorInfo& error,
|
||||
const ix::WebSocketOpenInfo& openInfo,
|
||||
const ix::WebSocketCloseInfo& closeInfo)
|
||||
const ix::WebSocketCloseInfo& closeInfo,
|
||||
const ix::WebSocketHttpHeaders& headers)
|
||||
{
|
||||
if (messageType == ix::WebSocket_MessageType_Error)
|
||||
{
|
||||
@ -393,8 +369,8 @@ webSocket.setOnMessageCallback(
|
||||
const std::string& str,
|
||||
size_t wireSize,
|
||||
const ix::WebSocketErrorInfo& error,
|
||||
const ix::WebSocketOpenInfo& openInfo,
|
||||
const ix::WebSocketCloseInfo& closeInfo)
|
||||
const ix::WebSocketCloseInfo& closeInfo,
|
||||
const ix::WebSocketHttpHeaders& headers)
|
||||
{
|
||||
if (messageType == ix::WebSocket_MessageType_Ping ||
|
||||
messageType == ix::WebSocket_MessageType_Pong)
|
||||
|
@ -1,14 +1,10 @@
|
||||
image:
|
||||
- Visual Studio 2017
|
||||
- Ubuntu
|
||||
|
||||
install:
|
||||
- ls -al
|
||||
- cmd: call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
- cd test
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -G"NMake Makefiles" ..
|
||||
- nmake
|
||||
- ixwebsocket_unittest.exe
|
||||
- python test/run.py
|
||||
|
||||
build: off
|
||||
|
@ -1,23 +1,11 @@
|
||||
version: "3"
|
||||
services:
|
||||
snake:
|
||||
image: bsergean/ws:build
|
||||
entrypoint: ws snake --port 8765 --host 0.0.0.0 --redis_hosts redis1
|
||||
ports:
|
||||
- "8765:8765"
|
||||
networks:
|
||||
- ws-net
|
||||
depends_on:
|
||||
- redis1
|
||||
|
||||
ws:
|
||||
security_opt:
|
||||
- seccomp:unconfined
|
||||
cap_add:
|
||||
- SYS_PTRACE
|
||||
stdin_open: true
|
||||
tty: true
|
||||
image: bsergean/ws:build
|
||||
ports:
|
||||
- "8765:8765"
|
||||
entrypoint: bash
|
||||
networks:
|
||||
- ws-net
|
||||
|
@ -1,52 +0,0 @@
|
||||
# Build time
|
||||
FROM debian:buster as build
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN apt-get update
|
||||
RUN apt-get -y install wget
|
||||
RUN mkdir -p /tmp/cmake
|
||||
WORKDIR /tmp/cmake
|
||||
RUN wget https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0-Linux-x86_64.tar.gz
|
||||
RUN tar zxf cmake-3.14.0-Linux-x86_64.tar.gz
|
||||
|
||||
RUN apt-get -y install g++
|
||||
RUN apt-get -y install libssl-dev
|
||||
RUN apt-get -y install libz-dev
|
||||
RUN apt-get -y install make
|
||||
|
||||
COPY . .
|
||||
|
||||
ARG CMAKE_BIN_PATH=/tmp/cmake/cmake-3.14.0-Linux-x86_64/bin
|
||||
ENV PATH="${CMAKE_BIN_PATH}:${PATH}"
|
||||
|
||||
RUN ["make"]
|
||||
|
||||
# Runtime
|
||||
FROM debian:buster as runtime
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN apt-get update
|
||||
# Runtime
|
||||
RUN apt-get install -y libssl1.1
|
||||
RUN apt-get install -y ca-certificates
|
||||
RUN ["update-ca-certificates"]
|
||||
|
||||
# Debugging
|
||||
RUN apt-get install -y strace
|
||||
RUN apt-get install -y procps
|
||||
RUN apt-get install -y htop
|
||||
|
||||
RUN adduser --disabled-password --gecos '' app
|
||||
COPY --chown=app:app --from=build /usr/local/bin/ws /usr/local/bin/ws
|
||||
RUN chmod +x /usr/local/bin/ws
|
||||
RUN ldd /usr/local/bin/ws
|
||||
|
||||
# Now run in usermode
|
||||
USER app
|
||||
WORKDIR /home/app
|
||||
|
||||
COPY --chown=app:app ws/snake/appsConfig.json .
|
||||
COPY --chown=app:app ws/cobraMetricsSample.json .
|
||||
|
||||
ENTRYPOINT ["ws"]
|
||||
CMD ["--help"]
|
@ -1,42 +0,0 @@
|
||||
FROM fedora:30 as build
|
||||
|
||||
RUN yum install -y gcc-g++
|
||||
RUN yum install -y cmake
|
||||
RUN yum install -y make
|
||||
RUN yum install -y openssl-devel
|
||||
|
||||
RUN yum install -y wget
|
||||
RUN mkdir -p /tmp/cmake
|
||||
WORKDIR /tmp/cmake
|
||||
RUN wget https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0-Linux-x86_64.tar.gz
|
||||
RUN tar zxf cmake-3.14.0-Linux-x86_64.tar.gz
|
||||
|
||||
ARG CMAKE_BIN_PATH=/tmp/cmake/cmake-3.14.0-Linux-x86_64/bin
|
||||
ENV PATH="${CMAKE_BIN_PATH}:${PATH}"
|
||||
|
||||
RUN yum install -y python
|
||||
RUN yum install -y libtsan
|
||||
|
||||
COPY . .
|
||||
# RUN ["make", "test"]
|
||||
RUN ["make"]
|
||||
|
||||
# Runtime
|
||||
FROM fedora:30 as runtime
|
||||
|
||||
RUN yum install -y libtsan
|
||||
|
||||
RUN groupadd app && useradd -g app app
|
||||
COPY --chown=app:app --from=build /usr/local/bin/ws /usr/local/bin/ws
|
||||
RUN chmod +x /usr/local/bin/ws
|
||||
RUN ldd /usr/local/bin/ws
|
||||
|
||||
# Now run in usermode
|
||||
USER app
|
||||
WORKDIR /home/app
|
||||
|
||||
COPY --chown=app:app ws/snake/appsConfig.json .
|
||||
COPY --chown=app:app ws/cobraMetricsSample.json .
|
||||
|
||||
ENTRYPOINT ["ws"]
|
||||
CMD ["--help"]
|
@ -1,24 +0,0 @@
|
||||
# Build time
|
||||
FROM ubuntu:xenial as build
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN apt-get update
|
||||
RUN apt-get -y install wget
|
||||
RUN mkdir -p /tmp/cmake
|
||||
WORKDIR /tmp/cmake
|
||||
RUN wget https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0-Linux-x86_64.tar.gz
|
||||
RUN tar zxf cmake-3.14.0-Linux-x86_64.tar.gz
|
||||
|
||||
RUN apt-get -y install g++
|
||||
RUN apt-get -y install libssl-dev
|
||||
RUN apt-get -y install libz-dev
|
||||
RUN apt-get -y install make
|
||||
RUN apt-get -y install python
|
||||
|
||||
COPY . .
|
||||
|
||||
ARG CMAKE_BIN_PATH=/tmp/cmake/cmake-3.14.0-Linux-x86_64/bin
|
||||
ENV PATH="${CMAKE_BIN_PATH}:${PATH}"
|
||||
|
||||
# RUN ["make"]
|
||||
RUN ["make", "test"]
|
@ -35,7 +35,7 @@ namespace ix
|
||||
return _terminated;
|
||||
}
|
||||
|
||||
void ConnectionState::setTerminated()
|
||||
bool ConnectionState::setTerminated()
|
||||
{
|
||||
_terminated = true;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ namespace ix
|
||||
virtual void computeId();
|
||||
virtual const std::string& getId() const;
|
||||
|
||||
void setTerminated();
|
||||
bool setTerminated();
|
||||
bool isTerminated() const;
|
||||
|
||||
static std::shared_ptr<ConnectionState> createConnectionState();
|
||||
|
@ -19,19 +19,20 @@ namespace ix
|
||||
std::mutex DNSLookup::_activeJobsMutex;
|
||||
|
||||
DNSLookup::DNSLookup(const std::string& hostname, int port, int64_t wait) :
|
||||
_hostname(hostname),
|
||||
_port(port),
|
||||
_wait(wait),
|
||||
_res(nullptr),
|
||||
_done(false),
|
||||
_id(_nextId++)
|
||||
{
|
||||
setHostname(hostname);
|
||||
|
||||
}
|
||||
|
||||
DNSLookup::~DNSLookup()
|
||||
{
|
||||
// Remove this job from the active jobs list
|
||||
std::lock_guard<std::mutex> lock(_activeJobsMutex);
|
||||
std::unique_lock<std::mutex> lock(_activeJobsMutex);
|
||||
_activeJobs.erase(_id);
|
||||
}
|
||||
|
||||
@ -78,7 +79,7 @@ namespace ix
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return getAddrInfo(getHostname(), _port, errMsg);
|
||||
return getAddrInfo(_hostname, _port, errMsg);
|
||||
}
|
||||
|
||||
struct addrinfo* DNSLookup::resolveAsync(std::string& errMsg,
|
||||
@ -96,7 +97,7 @@ namespace ix
|
||||
|
||||
// Record job in the active Job set
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_activeJobsMutex);
|
||||
std::unique_lock<std::mutex> lock(_activeJobsMutex);
|
||||
_activeJobs.insert(_id);
|
||||
}
|
||||
|
||||
@ -104,7 +105,7 @@ namespace ix
|
||||
// Good resource on thread forced termination
|
||||
// https://www.bo-yang.net/2017/11/19/cpp-kill-detached-thread
|
||||
//
|
||||
_thread = std::thread(&DNSLookup::run, this, _id, getHostname(), _port);
|
||||
_thread = std::thread(&DNSLookup::run, this, _id, _hostname, _port);
|
||||
_thread.detach();
|
||||
|
||||
std::unique_lock<std::mutex> lock(_conditionVariableMutex);
|
||||
@ -134,8 +135,7 @@ namespace ix
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
errMsg = getErrMsg();
|
||||
return getRes();
|
||||
return _res;
|
||||
}
|
||||
|
||||
void DNSLookup::run(uint64_t id, const std::string& hostname, int port) // thread runner
|
||||
@ -147,55 +147,18 @@ namespace ix
|
||||
struct addrinfo* res = getAddrInfo(hostname, port, errMsg);
|
||||
|
||||
// if this isn't an active job, and the control thread is gone
|
||||
// there is nothing to do, and we don't want to touch the defunct
|
||||
// there is not thing to do, and we don't want to touch the defunct
|
||||
// object data structure such as _errMsg or _condition
|
||||
std::lock_guard<std::mutex> lock(_activeJobsMutex);
|
||||
std::unique_lock<std::mutex> lock(_activeJobsMutex);
|
||||
if (_activeJobs.count(id) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy result into the member variables
|
||||
setRes(res);
|
||||
setErrMsg(errMsg);
|
||||
|
||||
_res = res;
|
||||
_errMsg = errMsg;
|
||||
_condition.notify_one();
|
||||
_done = true;
|
||||
}
|
||||
|
||||
void DNSLookup::setHostname(const std::string& hostname)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_hostnameMutex);
|
||||
_hostname = hostname;
|
||||
}
|
||||
|
||||
const std::string& DNSLookup::getHostname()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_hostnameMutex);
|
||||
return _hostname;
|
||||
}
|
||||
|
||||
void DNSLookup::setErrMsg(const std::string& errMsg)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_errMsgMutex);
|
||||
_errMsg = errMsg;
|
||||
}
|
||||
|
||||
const std::string& DNSLookup::getErrMsg()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_errMsgMutex);
|
||||
return _errMsg;
|
||||
}
|
||||
|
||||
void DNSLookup::setRes(struct addrinfo* addr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_resMutex);
|
||||
_res = addr;
|
||||
}
|
||||
|
||||
struct addrinfo* DNSLookup::getRes()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_resMutex);
|
||||
return _res;
|
||||
}
|
||||
}
|
||||
|
@ -45,26 +45,11 @@ namespace ix
|
||||
|
||||
void run(uint64_t id, const std::string& hostname, int port); // thread runner
|
||||
|
||||
void setHostname(const std::string& hostname);
|
||||
const std::string& getHostname();
|
||||
|
||||
void setErrMsg(const std::string& errMsg);
|
||||
const std::string& getErrMsg();
|
||||
|
||||
void setRes(struct addrinfo* addr);
|
||||
struct addrinfo* getRes();
|
||||
|
||||
std::string _hostname;
|
||||
std::mutex _hostnameMutex;
|
||||
int _port;
|
||||
|
||||
int64_t _wait;
|
||||
|
||||
struct addrinfo* _res;
|
||||
std::mutex _resMutex;
|
||||
|
||||
std::string _errMsg;
|
||||
std::mutex _errMsgMutex;
|
||||
struct addrinfo* _res;
|
||||
|
||||
std::atomic<bool> _done;
|
||||
std::thread _thread;
|
||||
|
@ -47,8 +47,9 @@ namespace ix
|
||||
|
||||
std::string protocol, host, path, query;
|
||||
int port;
|
||||
bool websocket = false;
|
||||
|
||||
if (!UrlParser::parse(url, protocol, host, path, query, port))
|
||||
if (!UrlParser::parse(url, protocol, host, path, query, port, websocket))
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Cannot parse url: " << url;
|
||||
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* IXNetSystem.cpp
|
||||
* Author: Korchynskyi Dmytro
|
||||
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "IXNetSystem.h"
|
||||
|
||||
namespace ix
|
||||
{
|
||||
bool initNetSystem()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
|
||||
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
|
||||
wVersionRequested = MAKEWORD(2, 2);
|
||||
|
||||
err = WSAStartup(wVersionRequested, &wsaData);
|
||||
|
||||
return err == 0;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool uninitNetSystem()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int err = WSACleanup();
|
||||
|
||||
return err == 0;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
}
|
@ -23,9 +23,3 @@
|
||||
# include <sys/time.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace ix
|
||||
{
|
||||
bool initNetSystem();
|
||||
bool uninitNetSystem();
|
||||
}
|
||||
|
@ -45,14 +45,17 @@ namespace ix
|
||||
close();
|
||||
}
|
||||
|
||||
PollResultType Socket::poll(int timeoutSecs)
|
||||
void Socket::poll(const OnPollCallback& onPollCallback, int timeoutSecs)
|
||||
{
|
||||
if (_sockfd == -1)
|
||||
{
|
||||
return PollResultType::Error;
|
||||
if (onPollCallback) onPollCallback(PollResultType::Error);
|
||||
return;
|
||||
}
|
||||
|
||||
return isReadyToRead(1000 * timeoutSecs);
|
||||
PollResultType pollResult = isReadyToRead(1000 * timeoutSecs);
|
||||
|
||||
if (onPollCallback) onPollCallback(pollResult);
|
||||
}
|
||||
|
||||
PollResultType Socket::select(bool readyToRead, int timeoutMs)
|
||||
@ -160,8 +163,6 @@ namespace ix
|
||||
|
||||
ssize_t Socket::send(char* buffer, size_t length)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_socketMutex);
|
||||
|
||||
int flags = 0;
|
||||
#ifdef MSG_NOSIGNAL
|
||||
flags = MSG_NOSIGNAL;
|
||||
@ -177,8 +178,6 @@ namespace ix
|
||||
|
||||
ssize_t Socket::recv(void* buffer, size_t length)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_socketMutex);
|
||||
|
||||
int flags = 0;
|
||||
#ifdef MSG_NOSIGNAL
|
||||
flags = MSG_NOSIGNAL;
|
||||
@ -189,27 +188,11 @@ namespace ix
|
||||
|
||||
int Socket::getErrno()
|
||||
{
|
||||
int err;
|
||||
|
||||
#ifdef _WIN32
|
||||
err = WSAGetLastError();
|
||||
return WSAGetLastError();
|
||||
#else
|
||||
err = errno;
|
||||
return errno;
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool Socket::isWaitNeeded()
|
||||
{
|
||||
int err = getErrno();
|
||||
|
||||
if (err == EWOULDBLOCK || err == EAGAIN || err == EINPROGRESS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Socket::closeSocket(int fd)
|
||||
@ -244,7 +227,8 @@ namespace ix
|
||||
return ret == len;
|
||||
}
|
||||
// There is possibly something to be writen, try again
|
||||
else if (ret < 0 && Socket::isWaitNeeded())
|
||||
else if (ret < 0 && (getErrno() == EWOULDBLOCK ||
|
||||
getErrno() == EAGAIN))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -272,7 +256,8 @@ namespace ix
|
||||
return true;
|
||||
}
|
||||
// There is possibly something to be read, try again
|
||||
else if (ret < 0 && Socket::isWaitNeeded())
|
||||
else if (ret < 0 && (getErrno() == EWOULDBLOCK ||
|
||||
getErrno() == EAGAIN))
|
||||
{
|
||||
// Wait with a 1ms timeout until the socket is ready to read.
|
||||
// This way we are not busy looping
|
||||
@ -331,12 +316,13 @@ namespace ix
|
||||
size_t size = std::min(kChunkSize, length - output.size());
|
||||
ssize_t ret = recv((char*)&_readBuffer[0], size);
|
||||
|
||||
if (ret <= 0 && !Socket::isWaitNeeded())
|
||||
if (ret <= 0 && (getErrno() != EWOULDBLOCK &&
|
||||
getErrno() != EAGAIN))
|
||||
{
|
||||
// Error
|
||||
return std::make_pair(false, std::string());
|
||||
}
|
||||
else
|
||||
else if (ret > 0)
|
||||
{
|
||||
output.insert(output.end(),
|
||||
_readBuffer.begin(),
|
||||
|
@ -16,20 +16,6 @@
|
||||
#ifdef _WIN32
|
||||
#include <BaseTsd.h>
|
||||
typedef SSIZE_T ssize_t;
|
||||
|
||||
#undef EWOULDBLOCK
|
||||
#undef EAGAIN
|
||||
#undef EINPROGRESS
|
||||
#undef EBADF
|
||||
#undef EINVAL
|
||||
|
||||
// map to WSA error codes
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define EAGAIN WSATRY_AGAIN
|
||||
#define EINPROGRESS WSAEINPROGRESS
|
||||
#define EBADF WSAEBADF
|
||||
#define EINVAL WSAEINVAL
|
||||
|
||||
#endif
|
||||
|
||||
#include "IXCancellationRequest.h"
|
||||
@ -51,12 +37,17 @@ namespace ix
|
||||
|
||||
class Socket {
|
||||
public:
|
||||
using OnPollCallback = std::function<void(PollResultType)>;
|
||||
|
||||
Socket(int fd = -1);
|
||||
virtual ~Socket();
|
||||
bool init(std::string& errorMsg);
|
||||
|
||||
void configure();
|
||||
|
||||
// Functions to check whether there is activity on the socket
|
||||
PollResultType poll(int timeoutSecs = kDefaultPollTimeout);
|
||||
void poll(const OnPollCallback& onPollCallback,
|
||||
int timeoutSecs = kDefaultPollTimeout);
|
||||
bool wakeUpFromPoll(uint8_t wakeUpCode);
|
||||
|
||||
PollResultType isReadyToWrite(int timeoutMs);
|
||||
@ -88,14 +79,14 @@ namespace ix
|
||||
const CancellationRequest& isCancellationRequested);
|
||||
|
||||
static int getErrno();
|
||||
static bool isWaitNeeded();
|
||||
static void closeSocket(int fd);
|
||||
|
||||
// Used as special codes for pipe communication
|
||||
static const uint64_t kSendRequest;
|
||||
static const uint64_t kCloseRequest;
|
||||
|
||||
protected:
|
||||
void closeSocket(int fd);
|
||||
|
||||
std::atomic<int> _sockfd;
|
||||
std::mutex _socketMutex;
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "IXSocketConnect.h"
|
||||
#include "IXDNSLookup.h"
|
||||
#include "IXNetSystem.h"
|
||||
#include "IXSocket.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
@ -19,6 +18,18 @@
|
||||
# include <linux/tcp.h>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
void closeSocket(int fd)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
closesocket(fd);
|
||||
#else
|
||||
::close(fd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
namespace ix
|
||||
{
|
||||
//
|
||||
@ -45,12 +56,11 @@ namespace ix
|
||||
// block us for too long
|
||||
SocketConnect::configure(fd);
|
||||
|
||||
int res = ::connect(fd, address->ai_addr, address->ai_addrlen);
|
||||
|
||||
if (res == -1 && !Socket::isWaitNeeded())
|
||||
if (::connect(fd, address->ai_addr, address->ai_addrlen) == -1
|
||||
&& errno != EINPROGRESS)
|
||||
{
|
||||
errMsg = strerror(Socket::getErrno());
|
||||
Socket::closeSocket(fd);
|
||||
closeSocket(fd);
|
||||
errMsg = strerror(errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -58,17 +68,15 @@ namespace ix
|
||||
{
|
||||
if (isCancellationRequested && isCancellationRequested()) // Must handle timeout as well
|
||||
{
|
||||
Socket::closeSocket(fd);
|
||||
closeSocket(fd);
|
||||
errMsg = "Cancelled";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// On Linux the timeout needs to be re-initialized everytime
|
||||
// http://man7.org/linux/man-pages/man2/select.2.html
|
||||
// Use select to check the status of the new connection
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 10 * 1000; // 10ms timeout
|
||||
|
||||
fd_set wfds;
|
||||
fd_set efds;
|
||||
|
||||
@ -77,13 +85,11 @@ namespace ix
|
||||
FD_ZERO(&efds);
|
||||
FD_SET(fd, &efds);
|
||||
|
||||
// Use select to check the status of the new connection
|
||||
res = select(fd + 1, nullptr, &wfds, &efds, &timeout);
|
||||
|
||||
if (res < 0 && (Socket::getErrno() == EBADF || Socket::getErrno() == EINVAL))
|
||||
if (select(fd + 1, nullptr, &wfds, &efds, &timeout) < 0 &&
|
||||
(errno == EBADF || errno == EINVAL))
|
||||
{
|
||||
Socket::closeSocket(fd);
|
||||
errMsg = std::string("Connect error, select error: ") + strerror(Socket::getErrno());
|
||||
closeSocket(fd);
|
||||
errMsg = std::string("Connect error, select error: ") + strerror(errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -104,7 +110,7 @@ namespace ix
|
||||
optval != 0)
|
||||
#endif
|
||||
{
|
||||
Socket::closeSocket(fd);
|
||||
closeSocket(fd);
|
||||
errMsg = strerror(optval);
|
||||
return -1;
|
||||
}
|
||||
@ -115,7 +121,7 @@ namespace ix
|
||||
}
|
||||
}
|
||||
|
||||
Socket::closeSocket(fd);
|
||||
closeSocket(fd);
|
||||
errMsg = "connect timed out after 60 seconds";
|
||||
return -1;
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ namespace ix
|
||||
|
||||
ERR_clear_error();
|
||||
ssize_t write_result = SSL_write(_ssl_connection, buf + sent, (int) nbyte);
|
||||
int reason = SSL_get_error(_ssl_connection, (int) write_result);
|
||||
int reason = SSL_get_error(_ssl_connection, write_result);
|
||||
|
||||
if (reason == SSL_ERROR_NONE) {
|
||||
nbyte -= write_result;
|
||||
@ -382,7 +382,7 @@ namespace ix
|
||||
return read_result;
|
||||
}
|
||||
|
||||
int reason = SSL_get_error(_ssl_connection, (int) read_result);
|
||||
int reason = SSL_get_error(_ssl_connection, read_result);
|
||||
|
||||
if (reason == SSL_ERROR_WANT_READ || reason == SSL_ERROR_WANT_WRITE)
|
||||
{
|
||||
|
@ -18,6 +18,7 @@
|
||||
# include <ws2def.h>
|
||||
# include <WS2tcpip.h>
|
||||
# include <schannel.h>
|
||||
//# include <sslsock.h>
|
||||
# include <io.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <sstream>
|
||||
#include <future>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
@ -77,7 +76,7 @@ namespace ix
|
||||
<< "at address " << _host << ":" << _port
|
||||
<< " : " << strerror(Socket::getErrno());
|
||||
|
||||
Socket::closeSocket(_serverFd);
|
||||
::close(_serverFd);
|
||||
return std::make_pair(false, ss.str());
|
||||
}
|
||||
|
||||
@ -101,7 +100,7 @@ namespace ix
|
||||
<< "at address " << _host << ":" << _port
|
||||
<< " : " << strerror(Socket::getErrno());
|
||||
|
||||
Socket::closeSocket(_serverFd);
|
||||
::close(_serverFd);
|
||||
return std::make_pair(false, ss.str());
|
||||
}
|
||||
|
||||
@ -115,7 +114,7 @@ namespace ix
|
||||
<< "at address " << _host << ":" << _port
|
||||
<< " : " << strerror(Socket::getErrno());
|
||||
|
||||
Socket::closeSocket(_serverFd);
|
||||
::close(_serverFd);
|
||||
return std::make_pair(false, ss.str());
|
||||
}
|
||||
|
||||
@ -135,22 +134,10 @@ namespace ix
|
||||
_conditionVariable.wait(lock);
|
||||
}
|
||||
|
||||
void SocketServer::stopAcceptingConnections()
|
||||
{
|
||||
_stop = true;
|
||||
}
|
||||
|
||||
void SocketServer::stop()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (closeTerminatedThreads()) break;
|
||||
|
||||
// wait 10ms and try again later.
|
||||
// we could have a timeout, but if we exit of here
|
||||
// we leaked threads, it is quite bad.
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
closeTerminatedThreads();
|
||||
assert(_connectionsThreads.empty());
|
||||
|
||||
if (!_thread.joinable()) return; // nothing to do
|
||||
|
||||
@ -159,7 +146,7 @@ namespace ix
|
||||
_stop = false;
|
||||
|
||||
_conditionVariable.notify_one();
|
||||
Socket::closeSocket(_serverFd);
|
||||
::close(_serverFd);
|
||||
}
|
||||
|
||||
void SocketServer::setConnectionStateFactory(
|
||||
@ -168,16 +155,9 @@ namespace ix
|
||||
_connectionStateFactory = connectionStateFactory;
|
||||
}
|
||||
|
||||
//
|
||||
// join the threads for connections that have been closed
|
||||
//
|
||||
// When a connection is closed by a client, the connection state terminated
|
||||
// field becomes true, and we can use that to know that we can join that thread
|
||||
// and remove it from our _connectionsThreads data structure (a list).
|
||||
//
|
||||
bool SocketServer::closeTerminatedThreads()
|
||||
void SocketServer::closeTerminatedThreads()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_connectionsThreadsMutex);
|
||||
auto it = _connectionsThreads.begin();
|
||||
auto itEnd = _connectionsThreads.end();
|
||||
|
||||
@ -186,17 +166,16 @@ namespace ix
|
||||
auto& connectionState = it->first;
|
||||
auto& thread = it->second;
|
||||
|
||||
if (!connectionState->isTerminated())
|
||||
if (!connectionState->isTerminated() ||
|
||||
!thread.joinable())
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thread.joinable()) thread.join();
|
||||
thread.join();
|
||||
it = _connectionsThreads.erase(it);
|
||||
}
|
||||
|
||||
return _connectionsThreads.empty();
|
||||
}
|
||||
|
||||
void SocketServer::run()
|
||||
@ -209,7 +188,7 @@ namespace ix
|
||||
if (_stop) return;
|
||||
|
||||
// Garbage collection to shutdown/join threads for closed connections.
|
||||
// We could run this in its own thread, so that we dont need to accept
|
||||
// We could run this in its own thread, so that we dont need to accept
|
||||
// a new connection to close a thread.
|
||||
// We could also use a condition variable to be notify when we need to do this
|
||||
closeTerminatedThreads();
|
||||
@ -242,18 +221,17 @@ namespace ix
|
||||
// Accept a connection.
|
||||
struct sockaddr_in client; // client address information
|
||||
int clientFd; // socket connected to client
|
||||
socklen_t addressLen = sizeof(client);
|
||||
socklen_t addressLen = sizeof(socklen_t);
|
||||
memset(&client, 0, sizeof(client));
|
||||
|
||||
if ((clientFd = accept(_serverFd, (struct sockaddr *)&client, &addressLen)) < 0)
|
||||
{
|
||||
if (!Socket::isWaitNeeded())
|
||||
if (Socket::getErrno() != EWOULDBLOCK)
|
||||
{
|
||||
// FIXME: that error should be propagated
|
||||
int err = Socket::getErrno();
|
||||
std::stringstream ss;
|
||||
ss << "SocketServer::run() error accepting connection: "
|
||||
<< err << ", " << strerror(err);
|
||||
<< strerror(Socket::getErrno());
|
||||
logError(ss.str());
|
||||
}
|
||||
continue;
|
||||
@ -267,7 +245,7 @@ namespace ix
|
||||
<< "Not accepting connection";
|
||||
logError(ss.str());
|
||||
|
||||
Socket::closeSocket(clientFd);
|
||||
::close(clientFd);
|
||||
|
||||
continue;
|
||||
}
|
||||
@ -278,10 +256,7 @@ namespace ix
|
||||
connectionState = _connectionStateFactory();
|
||||
}
|
||||
|
||||
if (_stop) return;
|
||||
|
||||
// Launch the handleConnection work asynchronously in its own thread.
|
||||
std::lock_guard<std::mutex> lock(_connectionsThreadsMutex);
|
||||
_connectionsThreads.push_back(std::make_pair(
|
||||
connectionState,
|
||||
std::thread(&SocketServer::handleConnection,
|
||||
|
@ -25,7 +25,6 @@ namespace ix
|
||||
public:
|
||||
using ConnectionStateFactory = std::function<std::shared_ptr<ConnectionState>()>;
|
||||
|
||||
// Each connection is handled by its own worker thread.
|
||||
// We use a list as we only care about remove and append operations.
|
||||
using ConnectionThreads = std::list<std::pair<std::shared_ptr<ConnectionState>,
|
||||
std::thread>>;
|
||||
@ -37,9 +36,6 @@ namespace ix
|
||||
virtual ~SocketServer();
|
||||
virtual void stop();
|
||||
|
||||
// It is possible to override ConnectionState through inheritance
|
||||
// this method allows user to change the factory by returning an object
|
||||
// that inherits from ConnectionState but has its own methods.
|
||||
void setConnectionStateFactory(const ConnectionStateFactory& connectionStateFactory);
|
||||
|
||||
const static int kDefaultPort;
|
||||
@ -57,8 +53,6 @@ namespace ix
|
||||
void logError(const std::string& str);
|
||||
void logInfo(const std::string& str);
|
||||
|
||||
void stopAcceptingConnections();
|
||||
|
||||
private:
|
||||
// Member variables
|
||||
int _port;
|
||||
@ -71,20 +65,15 @@ namespace ix
|
||||
|
||||
std::mutex _logMutex;
|
||||
|
||||
// background thread to wait for incoming connections
|
||||
std::atomic<bool> _stop;
|
||||
std::thread _thread;
|
||||
|
||||
// the list of (connectionState, threads) for each connections
|
||||
ConnectionThreads _connectionsThreads;
|
||||
std::mutex _connectionsThreadsMutex;
|
||||
|
||||
// used to have the main control thread for a server
|
||||
// wait for a 'terminate' notification without busy polling
|
||||
std::condition_variable _conditionVariable;
|
||||
std::mutex _conditionVariableMutex;
|
||||
|
||||
// the factory to create ConnectionState objects
|
||||
//
|
||||
ConnectionStateFactory _connectionStateFactory;
|
||||
|
||||
// Methods
|
||||
@ -93,7 +82,6 @@ namespace ix
|
||||
std::shared_ptr<ConnectionState> connectionState) = 0;
|
||||
virtual size_t getConnectedClientsCount() = 0;
|
||||
|
||||
// Returns true if all connection threads are joined
|
||||
bool closeTerminatedThreads();
|
||||
void closeTerminatedThreads();
|
||||
};
|
||||
}
|
||||
|
@ -5,32 +5,43 @@
|
||||
*/
|
||||
|
||||
#include "IXUrlParser.h"
|
||||
#include "LUrlParser.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace ix
|
||||
{
|
||||
//
|
||||
// The only difference between those 2 regex is the protocol
|
||||
//
|
||||
std::regex UrlParser::_httpRegex("(http|https)://([^/ :]+):?([^/ ]*)(/?[^ #?]*)\\x3f?([^ #]*)#?([^ ]*)");
|
||||
std::regex UrlParser::_webSocketRegex("(ws|wss)://([^/ :]+):?([^/ ]*)(/?[^ #?]*)\\x3f?([^ #]*)#?([^ ]*)");
|
||||
|
||||
bool UrlParser::parse(const std::string& url,
|
||||
std::string& protocol,
|
||||
std::string& host,
|
||||
std::string& path,
|
||||
std::string& query,
|
||||
int& port)
|
||||
int& port,
|
||||
bool websocket)
|
||||
{
|
||||
LUrlParser::clParseURL res = LUrlParser::clParseURL::ParseURL(url);
|
||||
|
||||
if (!res.IsValid())
|
||||
std::cmatch what;
|
||||
if (!regex_match(url.c_str(), what,
|
||||
websocket ? _webSocketRegex : _httpRegex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protocol = res.m_Scheme;
|
||||
host = res.m_Host;
|
||||
path = res.m_Path;
|
||||
query = res.m_Query;
|
||||
std::string portStr;
|
||||
|
||||
if (!res.GetPort(&port))
|
||||
protocol = std::string(what[1].first, what[1].second);
|
||||
host = std::string(what[2].first, what[2].second);
|
||||
portStr = std::string(what[3].first, what[3].second);
|
||||
path = std::string(what[4].first, what[4].second);
|
||||
query = std::string(what[5].first, what[5].second);
|
||||
|
||||
if (portStr.empty())
|
||||
{
|
||||
if (protocol == "ws" || protocol == "http")
|
||||
{
|
||||
@ -47,6 +58,12 @@ namespace ix
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << portStr;
|
||||
ss >> port;
|
||||
}
|
||||
|
||||
if (path.empty())
|
||||
{
|
||||
@ -66,12 +83,12 @@ namespace ix
|
||||
return true;
|
||||
}
|
||||
|
||||
void UrlParser::printUrl(const std::string& url)
|
||||
void UrlParser::printUrl(const std::string& url, bool websocket)
|
||||
{
|
||||
std::string protocol, host, path, query;
|
||||
int port {0};
|
||||
|
||||
if (!parse(url, protocol, host, path, query, port))
|
||||
if (!parse(url, protocol, host, path, query, port, websocket))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
namespace ix
|
||||
{
|
||||
@ -18,8 +19,13 @@ namespace ix
|
||||
std::string& host,
|
||||
std::string& path,
|
||||
std::string& query,
|
||||
int& port);
|
||||
int& port,
|
||||
bool websocket);
|
||||
|
||||
static void printUrl(const std::string& url);
|
||||
static void printUrl(const std::string& url, bool websocket);
|
||||
|
||||
private:
|
||||
static std::regex _httpRegex;
|
||||
static std::regex _webSocketRegex;
|
||||
};
|
||||
}
|
||||
|
@ -31,25 +31,21 @@ namespace ix
|
||||
{
|
||||
OnTrafficTrackerCallback WebSocket::_onTrafficTrackerCallback = nullptr;
|
||||
const int WebSocket::kDefaultHandShakeTimeoutSecs(60);
|
||||
const int WebSocket::kDefaultPingIntervalSecs(-1);
|
||||
const int WebSocket::kDefaultPingTimeoutSecs(-1);
|
||||
const bool WebSocket::kDefaultEnablePong(true);
|
||||
const int WebSocket::kDefaultHeartBeatPeriod(-1);
|
||||
|
||||
WebSocket::WebSocket() :
|
||||
_onMessageCallback(OnMessageCallback()),
|
||||
_stop(false),
|
||||
_automaticReconnection(true),
|
||||
_handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs),
|
||||
_enablePong(kDefaultEnablePong),
|
||||
_pingIntervalSecs(kDefaultPingIntervalSecs),
|
||||
_pingTimeoutSecs(kDefaultPingTimeoutSecs)
|
||||
_heartBeatPeriod(kDefaultHeartBeatPeriod)
|
||||
{
|
||||
_ws.setOnCloseCallback(
|
||||
[this](uint16_t code, const std::string& reason, size_t wireSize, bool remote)
|
||||
[this](uint16_t code, const std::string& reason, size_t wireSize)
|
||||
{
|
||||
_onMessageCallback(WebSocket_MessageType_Close, "", wireSize,
|
||||
WebSocketErrorInfo(), WebSocketOpenInfo(),
|
||||
WebSocketCloseInfo(code, reason, remote));
|
||||
WebSocketCloseInfo(code, reason));
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -83,52 +79,16 @@ namespace ix
|
||||
return _perMessageDeflateOptions;
|
||||
}
|
||||
|
||||
void WebSocket::setHeartBeatPeriod(int heartBeatPeriodSecs)
|
||||
void WebSocket::setHeartBeatPeriod(int heartBeatPeriod)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configMutex);
|
||||
_pingIntervalSecs = heartBeatPeriodSecs;
|
||||
_heartBeatPeriod = heartBeatPeriod;
|
||||
}
|
||||
|
||||
int WebSocket::getHeartBeatPeriod() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configMutex);
|
||||
return _pingIntervalSecs;
|
||||
}
|
||||
|
||||
void WebSocket::setPingInterval(int pingIntervalSecs)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configMutex);
|
||||
_pingIntervalSecs = pingIntervalSecs;
|
||||
}
|
||||
|
||||
int WebSocket::getPingInterval() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configMutex);
|
||||
return _pingIntervalSecs;
|
||||
}
|
||||
|
||||
void WebSocket::setPingTimeout(int pingTimeoutSecs)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configMutex);
|
||||
_pingTimeoutSecs = pingTimeoutSecs;
|
||||
}
|
||||
|
||||
int WebSocket::getPingTimeout() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configMutex);
|
||||
return _pingTimeoutSecs;
|
||||
}
|
||||
|
||||
void WebSocket::enablePong()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configMutex);
|
||||
_enablePong = true;
|
||||
}
|
||||
|
||||
void WebSocket::disablePong()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configMutex);
|
||||
_enablePong = false;
|
||||
return _heartBeatPeriod;
|
||||
}
|
||||
|
||||
void WebSocket::start()
|
||||
@ -165,9 +125,7 @@ namespace ix
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configMutex);
|
||||
_ws.configure(_perMessageDeflateOptions,
|
||||
_enablePong,
|
||||
_pingIntervalSecs,
|
||||
_pingTimeoutSecs);
|
||||
_heartBeatPeriod);
|
||||
}
|
||||
|
||||
WebSocketInitResult status = _ws.connectToUrl(_url, timeoutSecs);
|
||||
@ -187,10 +145,7 @@ namespace ix
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configMutex);
|
||||
_ws.configure(_perMessageDeflateOptions,
|
||||
_enablePong,
|
||||
_pingIntervalSecs,
|
||||
_pingTimeoutSecs);
|
||||
_ws.configure(_perMessageDeflateOptions, _heartBeatPeriod);
|
||||
}
|
||||
|
||||
WebSocketInitResult status = _ws.connectToSocket(fd, timeoutSecs);
|
||||
@ -229,12 +184,16 @@ namespace ix
|
||||
using millis = std::chrono::duration<double, std::milli>;
|
||||
millis duration;
|
||||
|
||||
// Try to connect only once when we don't have automaticReconnection setup
|
||||
if (!isConnected() && !isClosing() && !_stop && !_automaticReconnection)
|
||||
while (true)
|
||||
{
|
||||
if (isConnected() || isClosing() || _stop || !_automaticReconnection)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
status = connect(_handshakeTimeoutSecs);
|
||||
|
||||
if (!status.success)
|
||||
if (!status.success && !_stop)
|
||||
{
|
||||
duration = millis(calculateRetryWaitMilliseconds(retries++));
|
||||
|
||||
@ -245,45 +204,15 @@ namespace ix
|
||||
_onMessageCallback(WebSocket_MessageType_Error, "", 0,
|
||||
connectErr, WebSocketOpenInfo(),
|
||||
WebSocketCloseInfo());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise try to reconnect perpertually
|
||||
while (true)
|
||||
{
|
||||
if (isConnected() || isClosing() || _stop || !_automaticReconnection)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
status = connect(_handshakeTimeoutSecs);
|
||||
|
||||
if (!status.success)
|
||||
{
|
||||
duration = millis(calculateRetryWaitMilliseconds(retries++));
|
||||
|
||||
connectErr.retries = retries;
|
||||
connectErr.wait_time = duration.count();
|
||||
connectErr.reason = status.errorStr;
|
||||
connectErr.http_status = status.http_status;
|
||||
_onMessageCallback(WebSocket_MessageType_Error, "", 0,
|
||||
connectErr, WebSocketOpenInfo(),
|
||||
WebSocketCloseInfo());
|
||||
|
||||
// Only sleep if we aren't in the middle of stopping
|
||||
if (!_stop)
|
||||
{
|
||||
std::this_thread::sleep_for(duration);
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocket::run()
|
||||
{
|
||||
setThreadName(getUrl());
|
||||
setThreadName(_url);
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -340,8 +269,10 @@ namespace ix
|
||||
WebSocket::invokeTrafficTrackerCallback(msg.size(), true);
|
||||
});
|
||||
|
||||
// If we aren't trying to reconnect automatically, exit if we aren't connected
|
||||
if (!isConnected() && !_automaticReconnection) return;
|
||||
// 4. In blocking mode, getting out of this function is triggered by
|
||||
// an explicit disconnection from the callback, or by the remote end
|
||||
// closing the connection, ie isConnected() == false.
|
||||
if (!_thread.joinable() && !isConnected() && !_automaticReconnection) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,14 +61,11 @@ namespace ix
|
||||
{
|
||||
uint16_t code;
|
||||
std::string reason;
|
||||
bool remote;
|
||||
|
||||
WebSocketCloseInfo(uint16_t c = 0,
|
||||
const std::string& r = std::string(),
|
||||
bool rem = false)
|
||||
const std::string& r = std::string())
|
||||
: code(c)
|
||||
, reason(r)
|
||||
, remote(rem)
|
||||
{
|
||||
;
|
||||
}
|
||||
@ -92,11 +89,7 @@ namespace ix
|
||||
void setUrl(const std::string& url);
|
||||
void setPerMessageDeflateOptions(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
|
||||
void setHandshakeTimeout(int handshakeTimeoutSecs);
|
||||
void setHeartBeatPeriod(int heartBeatPeriodSecs);
|
||||
void setPingInterval(int pingIntervalSecs); // alias of setHeartBeatPeriod
|
||||
void setPingTimeout(int pingTimeoutSecs);
|
||||
void enablePong();
|
||||
void disablePong();
|
||||
void setHeartBeatPeriod(int heartBeatPeriod);
|
||||
|
||||
// Run asynchronously, by calling start and stop.
|
||||
void start();
|
||||
@ -121,8 +114,6 @@ namespace ix
|
||||
const std::string& getUrl() const;
|
||||
const WebSocketPerMessageDeflateOptions& getPerMessageDeflateOptions() const;
|
||||
int getHeartBeatPeriod() const;
|
||||
int getPingInterval() const;
|
||||
int getPingTimeout() const;
|
||||
size_t bufferedAmount() const;
|
||||
|
||||
void enableAutomaticReconnection();
|
||||
@ -161,15 +152,9 @@ namespace ix
|
||||
std::atomic<int> _handshakeTimeoutSecs;
|
||||
static const int kDefaultHandShakeTimeoutSecs;
|
||||
|
||||
// enable or disable PONG frame response to received PING frame
|
||||
bool _enablePong;
|
||||
static const bool kDefaultEnablePong;
|
||||
|
||||
// Optional ping and ping timeout
|
||||
int _pingIntervalSecs;
|
||||
int _pingTimeoutSecs;
|
||||
static const int kDefaultPingIntervalSecs;
|
||||
static const int kDefaultPingTimeoutSecs;
|
||||
// Optional Heartbeat
|
||||
int _heartBeatPeriod;
|
||||
static const int kDefaultHeartBeatPeriod;
|
||||
|
||||
friend class WebSocketServer;
|
||||
};
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -17,15 +17,13 @@
|
||||
namespace ix
|
||||
{
|
||||
const int WebSocketServer::kDefaultHandShakeTimeoutSecs(3); // 3 seconds
|
||||
const bool WebSocketServer::kDefaultEnablePong(true);
|
||||
|
||||
WebSocketServer::WebSocketServer(int port,
|
||||
const std::string& host,
|
||||
int backlog,
|
||||
size_t maxConnections,
|
||||
int handshakeTimeoutSecs) : SocketServer(port, host, backlog, maxConnections),
|
||||
_handshakeTimeoutSecs(handshakeTimeoutSecs),
|
||||
_enablePong(kDefaultEnablePong)
|
||||
_handshakeTimeoutSecs(handshakeTimeoutSecs)
|
||||
{
|
||||
|
||||
}
|
||||
@ -37,8 +35,6 @@ namespace ix
|
||||
|
||||
void WebSocketServer::stop()
|
||||
{
|
||||
stopAcceptingConnections();
|
||||
|
||||
auto clients = getClients();
|
||||
for (auto client : clients)
|
||||
{
|
||||
@ -48,16 +44,6 @@ namespace ix
|
||||
SocketServer::stop();
|
||||
}
|
||||
|
||||
void WebSocketServer::enablePong()
|
||||
{
|
||||
_enablePong = true;
|
||||
}
|
||||
|
||||
void WebSocketServer::disablePong()
|
||||
{
|
||||
_enablePong = false;
|
||||
}
|
||||
|
||||
void WebSocketServer::setOnConnectionCallback(const OnConnectionCallback& callback)
|
||||
{
|
||||
_onConnectionCallback = callback;
|
||||
@ -72,11 +58,6 @@ namespace ix
|
||||
|
||||
webSocket->disableAutomaticReconnection();
|
||||
|
||||
if (_enablePong)
|
||||
webSocket->enablePong();
|
||||
else
|
||||
webSocket->disablePong();
|
||||
|
||||
// Add this client to our client set
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_clientsMutex);
|
||||
|
@ -33,9 +33,6 @@ namespace ix
|
||||
virtual ~WebSocketServer();
|
||||
virtual void stop() final;
|
||||
|
||||
void enablePong();
|
||||
void disablePong();
|
||||
|
||||
void setOnConnectionCallback(const OnConnectionCallback& callback);
|
||||
|
||||
// Get all the connected clients
|
||||
@ -44,7 +41,6 @@ namespace ix
|
||||
private:
|
||||
// Member variables
|
||||
int _handshakeTimeoutSecs;
|
||||
bool _enablePong;
|
||||
|
||||
OnConnectionCallback _onConnectionCallback;
|
||||
|
||||
@ -52,7 +48,6 @@ namespace ix
|
||||
std::set<std::shared_ptr<WebSocket>> _clients;
|
||||
|
||||
const static int kDefaultHandShakeTimeoutSecs;
|
||||
const static bool kDefaultEnablePong;
|
||||
|
||||
// Methods
|
||||
virtual void handleConnection(int fd,
|
||||
|
@ -51,51 +51,21 @@
|
||||
#include <thread>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
int greatestCommonDivisor(int a, int b)
|
||||
{
|
||||
while (b != 0)
|
||||
{
|
||||
int t = b;
|
||||
b = a % b;
|
||||
a = t;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ix
|
||||
{
|
||||
const std::string WebSocketTransport::kPingMessage("ixwebsocket::heartbeat");
|
||||
const int WebSocketTransport::kDefaultPingIntervalSecs(-1);
|
||||
const int WebSocketTransport::kDefaultPingTimeoutSecs(-1);
|
||||
const bool WebSocketTransport::kDefaultEnablePong(true);
|
||||
const std::string WebSocketTransport::kHeartBeatPingMessage("ixwebsocket::heartbeat");
|
||||
const int WebSocketTransport::kDefaultHeartBeatPeriod(-1);
|
||||
constexpr size_t WebSocketTransport::kChunkSize;
|
||||
const uint16_t WebSocketTransport::kInternalErrorCode(1011);
|
||||
const uint16_t WebSocketTransport::kAbnormalCloseCode(1006);
|
||||
const uint16_t WebSocketTransport::kProtocolErrorCode(1002);
|
||||
const std::string WebSocketTransport::kInternalErrorMessage("Internal error");
|
||||
const std::string WebSocketTransport::kAbnormalCloseMessage("Abnormal closure");
|
||||
const std::string WebSocketTransport::kPingTimeoutMessage("Ping timeout");
|
||||
const std::string WebSocketTransport::kProtocolErrorMessage("Protocol error");
|
||||
|
||||
WebSocketTransport::WebSocketTransport() :
|
||||
_useMask(true),
|
||||
_readyState(CLOSED),
|
||||
_closeCode(kInternalErrorCode),
|
||||
_closeReason(kInternalErrorMessage),
|
||||
_closeCode(0),
|
||||
_closeWireSize(0),
|
||||
_closeRemote(false),
|
||||
_enablePerMessageDeflate(false),
|
||||
_requestInitCancellation(false),
|
||||
_enablePong(kDefaultEnablePong),
|
||||
_pingIntervalSecs(kDefaultPingIntervalSecs),
|
||||
_pingTimeoutSecs(kDefaultPingTimeoutSecs),
|
||||
_pingIntervalOrTimeoutGCDSecs(-1),
|
||||
_lastSendPingTimePoint(std::chrono::steady_clock::now()),
|
||||
_lastReceivePongTimePoint(std::chrono::steady_clock::now())
|
||||
_heartBeatPeriod(kDefaultHeartBeatPeriod),
|
||||
_lastSendTimePoint(std::chrono::steady_clock::now())
|
||||
{
|
||||
_readbuf.resize(kChunkSize);
|
||||
}
|
||||
@ -106,29 +76,11 @@ namespace ix
|
||||
}
|
||||
|
||||
void WebSocketTransport::configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
|
||||
bool enablePong,
|
||||
int pingIntervalSecs,
|
||||
int pingTimeoutSecs)
|
||||
int heartBeatPeriod)
|
||||
{
|
||||
_perMessageDeflateOptions = perMessageDeflateOptions;
|
||||
_enablePerMessageDeflate = _perMessageDeflateOptions.enabled();
|
||||
_enablePong = enablePong;
|
||||
_pingIntervalSecs = pingIntervalSecs;
|
||||
_pingTimeoutSecs = pingTimeoutSecs;
|
||||
|
||||
if (pingIntervalSecs > 0 && pingTimeoutSecs > 0)
|
||||
{
|
||||
_pingIntervalOrTimeoutGCDSecs = greatestCommonDivisor(pingIntervalSecs,
|
||||
pingTimeoutSecs);
|
||||
}
|
||||
else if (_pingTimeoutSecs > 0)
|
||||
{
|
||||
_pingIntervalOrTimeoutGCDSecs = pingTimeoutSecs;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pingIntervalOrTimeoutGCDSecs = pingIntervalSecs;
|
||||
}
|
||||
_heartBeatPeriod = heartBeatPeriod;
|
||||
}
|
||||
|
||||
// Client
|
||||
@ -137,8 +89,9 @@ namespace ix
|
||||
{
|
||||
std::string protocol, host, path, query;
|
||||
int port;
|
||||
bool websocket = true;
|
||||
|
||||
if (!UrlParser::parse(url, protocol, host, path, query, port))
|
||||
if (!UrlParser::parse(url, protocol, host, path, query, port, websocket))
|
||||
{
|
||||
return WebSocketInitResult(false, 0,
|
||||
std::string("Could not parse URL ") + url);
|
||||
@ -209,11 +162,10 @@ namespace ix
|
||||
if (readyStateValue == CLOSED)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_closeDataMutex);
|
||||
_onCloseCallback(_closeCode, _closeReason, _closeWireSize, _closeRemote);
|
||||
_closeCode = kInternalErrorCode;
|
||||
_closeReason = kInternalErrorMessage;
|
||||
_onCloseCallback(_closeCode, _closeReason, _closeWireSize);
|
||||
_closeCode = 0;
|
||||
_closeReason = std::string();
|
||||
_closeWireSize = 0;
|
||||
_closeRemote = false;
|
||||
}
|
||||
|
||||
_readyState = readyStateValue;
|
||||
@ -224,118 +176,95 @@ namespace ix
|
||||
_onCloseCallback = onCloseCallback;
|
||||
}
|
||||
|
||||
// Only consider send PING time points for that computation.
|
||||
bool WebSocketTransport::pingIntervalExceeded()
|
||||
// Only consider send time points for that computation.
|
||||
// The receive time points is taken into account in Socket::poll (second parameter).
|
||||
bool WebSocketTransport::heartBeatPeriodExceeded()
|
||||
{
|
||||
if (_pingIntervalSecs <= 0)
|
||||
return false;
|
||||
|
||||
std::lock_guard<std::mutex> lock(_lastSendPingTimePointMutex);
|
||||
std::lock_guard<std::mutex> lock(_lastSendTimePointMutex);
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
return now - _lastSendPingTimePoint > std::chrono::seconds(_pingIntervalSecs);
|
||||
}
|
||||
|
||||
bool WebSocketTransport::pingTimeoutExceeded()
|
||||
{
|
||||
if (_pingTimeoutSecs <= 0)
|
||||
return false;
|
||||
|
||||
std::lock_guard<std::mutex> lock(_lastReceivePongTimePointMutex);
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
return now - _lastReceivePongTimePoint > std::chrono::seconds(_pingTimeoutSecs);
|
||||
return now - _lastSendTimePoint > std::chrono::seconds(_heartBeatPeriod);
|
||||
}
|
||||
|
||||
void WebSocketTransport::poll()
|
||||
{
|
||||
PollResultType pollResult = _socket->poll(_pingIntervalOrTimeoutGCDSecs);
|
||||
|
||||
if (_readyState == OPEN)
|
||||
{
|
||||
// if (1) ping timeout is enabled and (2) duration since last received
|
||||
// ping response (PONG) exceeds the maximum delay, then close the connection
|
||||
if (pingTimeoutExceeded())
|
||||
_socket->poll(
|
||||
[this](PollResultType pollResult)
|
||||
{
|
||||
close(kInternalErrorCode, kPingTimeoutMessage);
|
||||
}
|
||||
// If ping is enabled and no ping has been sent for a duration
|
||||
// exceeding our ping interval, send a ping to the server.
|
||||
else if (pingIntervalExceeded())
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << kPingMessage << "::" << _pingIntervalSecs << "s";
|
||||
sendPing(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we send all the buffered data
|
||||
// there can be a lot of it for large messages.
|
||||
if (pollResult == PollResultType::SendRequest)
|
||||
{
|
||||
while (!isSendBufferEmpty() && !_requestInitCancellation)
|
||||
{
|
||||
// Wait with a 10ms timeout until the socket is ready to write.
|
||||
// This way we are not busy looping
|
||||
PollResultType result = _socket->isReadyToWrite(10);
|
||||
|
||||
if (result == PollResultType::Error)
|
||||
// If (1) heartbeat is enabled, and (2) no data was received or
|
||||
// send for a duration exceeding our heart-beat period, send a
|
||||
// ping to the server.
|
||||
if (pollResult == PollResultType::Timeout &&
|
||||
heartBeatPeriodExceeded())
|
||||
{
|
||||
_socket->close();
|
||||
setReadyState(CLOSED);
|
||||
break;
|
||||
std::stringstream ss;
|
||||
ss << kHeartBeatPingMessage << "::" << _heartBeatPeriod << "s";
|
||||
sendPing(ss.str());
|
||||
}
|
||||
else if (result == PollResultType::ReadyForWrite)
|
||||
// Make sure we send all the buffered data
|
||||
// there can be a lot of it for large messages.
|
||||
else if (pollResult == PollResultType::SendRequest)
|
||||
{
|
||||
sendOnSocket();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pollResult == PollResultType::ReadyForRead)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
ssize_t ret = _socket->recv((char*)&_readbuf[0], _readbuf.size());
|
||||
|
||||
if (ret < 0 && Socket::isWaitNeeded())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (ret <= 0)
|
||||
{
|
||||
_rxbuf.clear();
|
||||
_socket->close();
|
||||
while (!isSendBufferEmpty() && !_requestInitCancellation)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_closeDataMutex);
|
||||
_closeCode = kAbnormalCloseCode;
|
||||
_closeReason = kAbnormalCloseMessage;
|
||||
_closeWireSize = 0;
|
||||
_closeRemote = true;
|
||||
}
|
||||
setReadyState(CLOSED);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
_rxbuf.insert(_rxbuf.end(),
|
||||
_readbuf.begin(),
|
||||
_readbuf.begin() + ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pollResult == PollResultType::Error)
|
||||
{
|
||||
_socket->close();
|
||||
}
|
||||
else if (pollResult == PollResultType::CloseRequest)
|
||||
{
|
||||
_socket->close();
|
||||
}
|
||||
// Wait with a 10ms timeout until the socket is ready to write.
|
||||
// This way we are not busy looping
|
||||
PollResultType result = _socket->isReadyToWrite(10);
|
||||
|
||||
// Avoid a race condition where we get stuck in select
|
||||
// while closing.
|
||||
if (_readyState == CLOSING)
|
||||
{
|
||||
_socket->close();
|
||||
}
|
||||
if (result == PollResultType::Error)
|
||||
{
|
||||
_socket->close();
|
||||
setReadyState(CLOSED);
|
||||
break;
|
||||
}
|
||||
else if (result == PollResultType::ReadyForWrite)
|
||||
{
|
||||
sendOnSocket();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pollResult == PollResultType::ReadyForRead)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
ssize_t ret = _socket->recv((char*)&_readbuf[0], _readbuf.size());
|
||||
|
||||
if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK ||
|
||||
_socket->getErrno() == EAGAIN))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (ret <= 0)
|
||||
{
|
||||
_rxbuf.clear();
|
||||
_socket->close();
|
||||
setReadyState(CLOSED);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
_rxbuf.insert(_rxbuf.end(),
|
||||
_readbuf.begin(),
|
||||
_readbuf.begin() + ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pollResult == PollResultType::Error)
|
||||
{
|
||||
_socket->close();
|
||||
}
|
||||
else if (pollResult == PollResultType::CloseRequest)
|
||||
{
|
||||
_socket->close();
|
||||
}
|
||||
|
||||
// Avoid a race condition where we get stuck in select
|
||||
// while closing.
|
||||
if (_readyState == CLOSING)
|
||||
{
|
||||
_socket->close();
|
||||
}
|
||||
},
|
||||
_heartBeatPeriod);
|
||||
}
|
||||
|
||||
bool WebSocketTransport::isSendBufferEmpty() const
|
||||
@ -515,16 +444,12 @@ namespace ix
|
||||
else if (ws.opcode == wsheader_type::PING)
|
||||
{
|
||||
unmaskReceiveBuffer(ws);
|
||||
|
||||
std::string pingData(_rxbuf.begin()+ws.header_size,
|
||||
_rxbuf.begin()+ws.header_size + (size_t) ws.N);
|
||||
|
||||
if (_enablePong)
|
||||
{
|
||||
// Reply back right away
|
||||
bool compress = false;
|
||||
sendData(wsheader_type::PONG, pingData, compress);
|
||||
}
|
||||
// Reply back right away
|
||||
bool compress = false;
|
||||
sendData(wsheader_type::PONG, pingData, compress);
|
||||
|
||||
emitMessage(PING, pingData, ws, onMessageCallback);
|
||||
}
|
||||
@ -534,9 +459,6 @@ namespace ix
|
||||
std::string pongData(_rxbuf.begin()+ws.header_size,
|
||||
_rxbuf.begin()+ws.header_size + (size_t) ws.N);
|
||||
|
||||
std::lock_guard<std::mutex> lck(_lastReceivePongTimePointMutex);
|
||||
_lastReceivePongTimePoint = std::chrono::steady_clock::now();
|
||||
|
||||
emitMessage(PONG, pongData, ws, onMessageCallback);
|
||||
}
|
||||
else if (ws.opcode == wsheader_type::CLOSE)
|
||||
@ -550,17 +472,14 @@ namespace ix
|
||||
|
||||
// Get the reason.
|
||||
std::string reason(_rxbuf.begin()+ws.header_size + 2,
|
||||
_rxbuf.begin()+ws.header_size + (size_t) ws.N);
|
||||
_rxbuf.begin()+ws.header_size + 2 + (size_t) ws.N);
|
||||
|
||||
bool remote = true;
|
||||
|
||||
close(code, reason, _rxbuf.size(), remote);
|
||||
close(code, reason, _rxbuf.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unexpected frame type
|
||||
|
||||
close(kProtocolErrorCode, kProtocolErrorMessage, _rxbuf.size());
|
||||
close();
|
||||
}
|
||||
|
||||
// Erase the message that has been processed from the input/read buffer
|
||||
@ -805,15 +724,7 @@ namespace ix
|
||||
WebSocketSendInfo WebSocketTransport::sendPing(const std::string& message)
|
||||
{
|
||||
bool compress = false;
|
||||
WebSocketSendInfo info = sendData(wsheader_type::PING, message, compress);
|
||||
|
||||
if (info.success)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(_lastSendPingTimePointMutex);
|
||||
_lastSendPingTimePoint = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
return info;
|
||||
return sendData(wsheader_type::PING, message, compress);
|
||||
}
|
||||
|
||||
WebSocketSendInfo WebSocketTransport::sendBinary(
|
||||
@ -842,7 +753,8 @@ namespace ix
|
||||
{
|
||||
ssize_t ret = _socket->send((char*)&_txbuf[0], _txbuf.size());
|
||||
|
||||
if (ret < 0 && Socket::isWaitNeeded())
|
||||
if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK ||
|
||||
_socket->getErrno() == EAGAIN))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -858,9 +770,12 @@ namespace ix
|
||||
_txbuf.erase(_txbuf.begin(), _txbuf.begin() + ret);
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lck(_lastSendTimePointMutex);
|
||||
_lastSendTimePoint = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
void WebSocketTransport::close(uint16_t code, const std::string& reason, size_t closeWireSize, bool remote)
|
||||
void WebSocketTransport::close(uint16_t code, const std::string& reason, size_t closeWireSize)
|
||||
{
|
||||
_requestInitCancellation = true;
|
||||
|
||||
@ -868,13 +783,7 @@ namespace ix
|
||||
|
||||
// See list of close events here:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
||||
|
||||
int codeLength = 2;
|
||||
std::string closure{(char)(code >> 8), (char)(code & 0xff)};
|
||||
closure.resize(codeLength + reason.size());
|
||||
|
||||
// copy reason after code
|
||||
closure.replace(codeLength, reason.size(), reason);
|
||||
const std::string closure{(char)(code >> 8), (char)(code & 0xff)};
|
||||
|
||||
bool compress = false;
|
||||
sendData(wsheader_type::CLOSE, closure, compress);
|
||||
@ -888,9 +797,8 @@ namespace ix
|
||||
_closeCode = code;
|
||||
_closeReason = reason;
|
||||
_closeWireSize = closeWireSize;
|
||||
_closeRemote = remote;
|
||||
}
|
||||
|
||||
|
||||
setReadyState(CLOSED);
|
||||
}
|
||||
|
||||
|
@ -62,16 +62,13 @@ namespace ix
|
||||
MessageKind)>;
|
||||
using OnCloseCallback = std::function<void(uint16_t,
|
||||
const std::string&,
|
||||
size_t,
|
||||
bool)>;
|
||||
size_t)>;
|
||||
|
||||
WebSocketTransport();
|
||||
~WebSocketTransport();
|
||||
|
||||
void configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
|
||||
bool enablePong,
|
||||
int pingIntervalSecs,
|
||||
int pingTimeoutSecs);
|
||||
int heartBeatPeriod);
|
||||
|
||||
WebSocketInitResult connectToUrl(const std::string& url, // Client
|
||||
int timeoutSecs);
|
||||
@ -87,8 +84,7 @@ namespace ix
|
||||
|
||||
void close(uint16_t code = 1000,
|
||||
const std::string& reason = "Normal closure",
|
||||
size_t closeWireSize = 0,
|
||||
bool remote = false);
|
||||
size_t closeWireSize = 0);
|
||||
|
||||
ReadyStateValues getReadyState() const;
|
||||
void setReadyState(ReadyStateValues readyStateValue);
|
||||
@ -119,7 +115,7 @@ namespace ix
|
||||
|
||||
// Tells whether we should mask the data we send.
|
||||
// client should mask but server should not
|
||||
std::atomic<bool> _useMask;
|
||||
bool _useMask;
|
||||
|
||||
// Buffer for reading from our socket. That buffer is never resized.
|
||||
std::vector<uint8_t> _readbuf;
|
||||
@ -152,7 +148,6 @@ namespace ix
|
||||
uint16_t _closeCode;
|
||||
std::string _closeReason;
|
||||
size_t _closeWireSize;
|
||||
bool _closeRemote;
|
||||
mutable std::mutex _closeDataMutex;
|
||||
|
||||
// Data used for Per Message Deflate compression (with zlib)
|
||||
@ -163,43 +158,15 @@ namespace ix
|
||||
// Used to cancel dns lookup + socket connect + http upgrade
|
||||
std::atomic<bool> _requestInitCancellation;
|
||||
|
||||
// Constants for dealing with closing conneections
|
||||
static const uint16_t kInternalErrorCode;
|
||||
static const uint16_t kAbnormalCloseCode;
|
||||
static const uint16_t kProtocolErrorCode;
|
||||
static const std::string kInternalErrorMessage;
|
||||
static const std::string kAbnormalCloseMessage;
|
||||
static const std::string kPingTimeoutMessage;
|
||||
static const std::string kProtocolErrorMessage;
|
||||
// Optional Heartbeat
|
||||
int _heartBeatPeriod;
|
||||
static const int kDefaultHeartBeatPeriod;
|
||||
const static std::string kHeartBeatPingMessage;
|
||||
mutable std::mutex _lastSendTimePointMutex;
|
||||
std::chrono::time_point<std::chrono::steady_clock> _lastSendTimePoint;
|
||||
|
||||
// enable auto response to ping
|
||||
bool _enablePong;
|
||||
static const bool kDefaultEnablePong;
|
||||
|
||||
// Optional ping and pong timeout
|
||||
// if both ping interval and timeout are set (> 0),
|
||||
// then use GCD of these value to wait for the lowest time
|
||||
int _pingIntervalSecs;
|
||||
int _pingTimeoutSecs;
|
||||
int _pingIntervalOrTimeoutGCDSecs;
|
||||
|
||||
static const int kDefaultPingIntervalSecs;
|
||||
static const int kDefaultPingTimeoutSecs;
|
||||
static const std::string kPingMessage;
|
||||
|
||||
// We record when ping are being sent so that we can know when to send the next one
|
||||
// We also record when pong are being sent as a reply to pings, to close the connections
|
||||
// if no pong were received sufficiently fast.
|
||||
mutable std::mutex _lastSendPingTimePointMutex;
|
||||
mutable std::mutex _lastReceivePongTimePointMutex;
|
||||
std::chrono::time_point<std::chrono::steady_clock> _lastSendPingTimePoint;
|
||||
std::chrono::time_point<std::chrono::steady_clock> _lastReceivePongTimePoint;
|
||||
|
||||
// If this function returns true, it is time to send a new ping
|
||||
bool pingIntervalExceeded();
|
||||
|
||||
// No PONG data was received through the socket for longer than ping timeout delay
|
||||
bool pingTimeoutExceeded();
|
||||
// No data was send through the socket for longer than the heartbeat period
|
||||
bool heartBeatPeriodExceeded();
|
||||
|
||||
void sendOnSocket();
|
||||
WebSocketSendInfo sendData(wsheader_type::opcode_type type,
|
||||
|
@ -1,265 +0,0 @@
|
||||
/*
|
||||
* Lightweight URL & URI parser (RFC 1738, RFC 3986)
|
||||
* https://github.com/corporateshark/LUrlParser
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "LUrlParser.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
|
||||
// check if the scheme name is valid
|
||||
static bool IsSchemeValid( const std::string& SchemeName )
|
||||
{
|
||||
for ( auto c : SchemeName )
|
||||
{
|
||||
if ( !isalpha( c ) && c != '+' && c != '-' && c != '.' ) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LUrlParser::clParseURL::GetPort( int* OutPort ) const
|
||||
{
|
||||
if ( !IsValid() ) { return false; }
|
||||
|
||||
int Port = atoi( m_Port.c_str() );
|
||||
|
||||
if ( Port <= 0 || Port > 65535 ) { return false; }
|
||||
|
||||
if ( OutPort ) { *OutPort = Port; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// based on RFC 1738 and RFC 3986
|
||||
LUrlParser::clParseURL LUrlParser::clParseURL::ParseURL( const std::string& URL )
|
||||
{
|
||||
LUrlParser::clParseURL Result;
|
||||
|
||||
const char* CurrentString = URL.c_str();
|
||||
|
||||
/*
|
||||
* <scheme>:<scheme-specific-part>
|
||||
* <scheme> := [a-z\+\-\.]+
|
||||
* For resiliency, programs interpreting URLs should treat upper case letters as equivalent to lower case in scheme names
|
||||
*/
|
||||
|
||||
// try to read scheme
|
||||
{
|
||||
const char* LocalString = strchr( CurrentString, ':' );
|
||||
|
||||
if ( !LocalString )
|
||||
{
|
||||
return clParseURL( LUrlParserError_NoUrlCharacter );
|
||||
}
|
||||
|
||||
// save the scheme name
|
||||
Result.m_Scheme = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
if ( !IsSchemeValid( Result.m_Scheme ) )
|
||||
{
|
||||
return clParseURL( LUrlParserError_InvalidSchemeName );
|
||||
}
|
||||
|
||||
// scheme should be lowercase
|
||||
std::transform( Result.m_Scheme.begin(), Result.m_Scheme.end(), Result.m_Scheme.begin(), ::tolower );
|
||||
|
||||
// skip ':'
|
||||
CurrentString = LocalString+1;
|
||||
}
|
||||
|
||||
/*
|
||||
* //<user>:<password>@<host>:<port>/<url-path>
|
||||
* any ":", "@" and "/" must be normalized
|
||||
*/
|
||||
|
||||
// skip "//"
|
||||
if ( *CurrentString++ != '/' ) return clParseURL( LUrlParserError_NoDoubleSlash );
|
||||
if ( *CurrentString++ != '/' ) return clParseURL( LUrlParserError_NoDoubleSlash );
|
||||
|
||||
// check if the user name and password are specified
|
||||
bool bHasUserName = false;
|
||||
|
||||
const char* LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString )
|
||||
{
|
||||
if ( *LocalString == '@' )
|
||||
{
|
||||
// user name and password are specified
|
||||
bHasUserName = true;
|
||||
break;
|
||||
}
|
||||
else if ( *LocalString == '/' )
|
||||
{
|
||||
// end of <host>:<port> specification
|
||||
bHasUserName = false;
|
||||
break;
|
||||
}
|
||||
|
||||
LocalString++;
|
||||
}
|
||||
|
||||
// user name and password
|
||||
LocalString = CurrentString;
|
||||
|
||||
if ( bHasUserName )
|
||||
{
|
||||
// read user name
|
||||
while ( *LocalString && *LocalString != ':' && *LocalString != '@' ) LocalString++;
|
||||
|
||||
Result.m_UserName = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
// proceed with the current pointer
|
||||
CurrentString = LocalString;
|
||||
|
||||
if ( *CurrentString == ':' )
|
||||
{
|
||||
// skip ':'
|
||||
CurrentString++;
|
||||
|
||||
// read password
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString && *LocalString != '@' ) LocalString++;
|
||||
|
||||
Result.m_Password = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// skip '@'
|
||||
if ( *CurrentString != '@' )
|
||||
{
|
||||
return clParseURL( LUrlParserError_NoAtSign );
|
||||
}
|
||||
|
||||
CurrentString++;
|
||||
}
|
||||
|
||||
bool bHasBracket = ( *CurrentString == '[' );
|
||||
|
||||
// go ahead, read the host name
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString )
|
||||
{
|
||||
if ( bHasBracket && *LocalString == ']' )
|
||||
{
|
||||
// end of IPv6 address
|
||||
LocalString++;
|
||||
break;
|
||||
}
|
||||
else if ( !bHasBracket && ( *LocalString == ':' || *LocalString == '/' ) )
|
||||
{
|
||||
// port number is specified
|
||||
break;
|
||||
}
|
||||
|
||||
LocalString++;
|
||||
}
|
||||
|
||||
Result.m_Host = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
|
||||
// is port number specified?
|
||||
if ( *CurrentString == ':' )
|
||||
{
|
||||
CurrentString++;
|
||||
|
||||
// read port number
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString && *LocalString != '/' ) LocalString++;
|
||||
|
||||
Result.m_Port = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// end of string
|
||||
if ( !*CurrentString )
|
||||
{
|
||||
Result.m_ErrorCode = LUrlParserError_Ok;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
// skip '/'
|
||||
if ( *CurrentString != '/' )
|
||||
{
|
||||
return clParseURL( LUrlParserError_NoSlash );
|
||||
}
|
||||
|
||||
CurrentString++;
|
||||
|
||||
// parse the path
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString && *LocalString != '#' && *LocalString != '?' ) LocalString++;
|
||||
|
||||
Result.m_Path = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
|
||||
// check for query
|
||||
if ( *CurrentString == '?' )
|
||||
{
|
||||
// skip '?'
|
||||
CurrentString++;
|
||||
|
||||
// read query
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString && *LocalString != '#' ) LocalString++;
|
||||
|
||||
Result.m_Query = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
// check for fragment
|
||||
if ( *CurrentString == '#' )
|
||||
{
|
||||
// skip '#'
|
||||
CurrentString++;
|
||||
|
||||
// read fragment
|
||||
LocalString = CurrentString;
|
||||
|
||||
while ( *LocalString ) LocalString++;
|
||||
|
||||
Result.m_Fragment = std::string( CurrentString, LocalString - CurrentString );
|
||||
|
||||
CurrentString = LocalString;
|
||||
}
|
||||
|
||||
Result.m_ErrorCode = LUrlParserError_Ok;
|
||||
|
||||
return Result;
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Lightweight URL & URI parser (RFC 1738, RFC 3986)
|
||||
* https://github.com/corporateshark/LUrlParser
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (C) 2015 Sergey Kosarevsky (sk@linderdaum.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace LUrlParser
|
||||
{
|
||||
enum LUrlParserError
|
||||
{
|
||||
LUrlParserError_Ok = 0,
|
||||
LUrlParserError_Uninitialized = 1,
|
||||
LUrlParserError_NoUrlCharacter = 2,
|
||||
LUrlParserError_InvalidSchemeName = 3,
|
||||
LUrlParserError_NoDoubleSlash = 4,
|
||||
LUrlParserError_NoAtSign = 5,
|
||||
LUrlParserError_UnexpectedEndOfLine = 6,
|
||||
LUrlParserError_NoSlash = 7,
|
||||
};
|
||||
|
||||
class clParseURL
|
||||
{
|
||||
public:
|
||||
LUrlParserError m_ErrorCode;
|
||||
std::string m_Scheme;
|
||||
std::string m_Host;
|
||||
std::string m_Port;
|
||||
std::string m_Path;
|
||||
std::string m_Query;
|
||||
std::string m_Fragment;
|
||||
std::string m_UserName;
|
||||
std::string m_Password;
|
||||
|
||||
clParseURL()
|
||||
: m_ErrorCode( LUrlParserError_Uninitialized )
|
||||
{}
|
||||
|
||||
/// return 'true' if the parsing was successful
|
||||
bool IsValid() const { return m_ErrorCode == LUrlParserError_Ok; }
|
||||
|
||||
/// helper to convert the port number to int, return 'true' if the port is valid (within the 0..65535 range)
|
||||
bool GetPort( int* OutPort ) const;
|
||||
|
||||
/// parse the URL
|
||||
static clParseURL ParseURL( const std::string& URL );
|
||||
|
||||
private:
|
||||
explicit clParseURL( LUrlParserError ErrorCode )
|
||||
: m_ErrorCode( ErrorCode )
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace LUrlParser
|
22
makefile
22
makefile
@ -5,14 +5,8 @@ all: brew
|
||||
|
||||
install: brew
|
||||
|
||||
# Use -DCMAKE_INSTALL_PREFIX= to install into another location
|
||||
# on osx it is good practice to make /usr/local user writable
|
||||
# sudo chown -R `whoami`/staff /usr/local
|
||||
brew:
|
||||
mkdir -p build && (cd build ; cmake -DUSE_TLS=1 .. ; make -j install)
|
||||
|
||||
uninstall:
|
||||
xargs rm -fv < build/install_manifest.txt
|
||||
mkdir -p build && (cd build ; cmake .. ; make -j install)
|
||||
|
||||
.PHONY: docker
|
||||
|
||||
@ -31,12 +25,20 @@ docker_push:
|
||||
docker push ${LATEST}
|
||||
|
||||
run:
|
||||
docker run --cap-add sys_ptrace --entrypoint=bash -it bsergean/ws:build
|
||||
docker run --cap-add sys_ptrace -it ws:latest
|
||||
|
||||
# this is helpful to remove trailing whitespaces
|
||||
trail:
|
||||
sh third_party/remote_trailing_whitespaces.sh
|
||||
|
||||
build:
|
||||
(cd examples/satori_publisher ; mkdir -p build ; cd build ; cmake .. ; make)
|
||||
(cd examples/chat ; mkdir -p build ; cd build ; cmake .. ; make)
|
||||
(cd examples/ping_pong ; mkdir -p build ; cd build ; cmake .. ; make)
|
||||
(cd examples/ws_connect ; mkdir -p build ; cd build ; cmake .. ; make)
|
||||
(cd examples/echo_server ; mkdir -p build ; cd build ; cmake .. ; make)
|
||||
(cd examples/broadcast_server ; mkdir -p build ; cd build ; cmake .. ; make)
|
||||
|
||||
# That target is used to start a node server, but isn't required as we have
|
||||
# a builtin C++ server started in the unittest now
|
||||
test_server:
|
||||
@ -46,7 +48,7 @@ test_server:
|
||||
# env TEST=Websocket_chat make test
|
||||
# env TEST=heartbeat make test
|
||||
test:
|
||||
python2.7 test/run.py
|
||||
(cd test ; python2.7 run.py)
|
||||
|
||||
ws_test: all
|
||||
(cd ws ; bash test_ws.sh)
|
||||
@ -60,7 +62,7 @@ rebase_upstream:
|
||||
|
||||
install_cmake_for_linux:
|
||||
mkdir -p /tmp/cmake
|
||||
(cd /tmp/cmake ; curl -L -O https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0-Linux-x86_64.tar.gz ; tar zxf cmake-3.14.0-Linux-x86_64.tar.gz)
|
||||
(cd /tmp/cmake ; curl -L -O https://github.com/Kitware/CMake/releases/download/v3.14.0-rc4/cmake-3.14.0-rc4-Linux-x86_64.tar.gz ; tar zxf cmake-3.14.0-rc4-Linux-x86_64.tar.gz)
|
||||
|
||||
.PHONY: test
|
||||
.PHONY: build
|
||||
|
@ -11,8 +11,6 @@ find_package(Sanitizers)
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
|
||||
if (NOT WIN32)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
|
||||
set(CMAKE_LD_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
|
||||
option(USE_TLS "Add TLS support" ON)
|
||||
endif()
|
||||
|
||||
@ -32,17 +30,15 @@ set (SOURCES
|
||||
IXDNSLookupTest.cpp
|
||||
IXSocketTest.cpp
|
||||
IXSocketConnectTest.cpp
|
||||
IXWebSocketServerTest.cpp
|
||||
IXWebSocketPingTest.cpp
|
||||
IXWebSocketTestConnectionDisconnection.cpp
|
||||
IXUrlParserTest.cpp
|
||||
)
|
||||
|
||||
# Some unittest don't work on windows yet
|
||||
if (NOT WIN32)
|
||||
list(APPEND SOURCES
|
||||
IXWebSocketPingTimeoutTest.cpp
|
||||
list(APPEND SOURCES
|
||||
IXWebSocketServerTest.cpp
|
||||
IXWebSocketHeartBeatTest.cpp
|
||||
cmd_websocket_chat.cpp
|
||||
IXWebSocketTestConnectionDisconnection.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,8 +17,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stack>
|
||||
#include <iomanip>
|
||||
#include <random>
|
||||
|
||||
|
||||
namespace ix
|
||||
{
|
||||
@ -72,12 +70,10 @@ namespace ix
|
||||
Logger() << msg;
|
||||
}
|
||||
|
||||
int getAnyFreePortRandom()
|
||||
int getAnyFreePortSimple()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::uniform_int_distribution<int> dist(1024 + 1, 65535);
|
||||
|
||||
return dist(rd);
|
||||
static int defaultPort = 8090;
|
||||
return defaultPort++;
|
||||
}
|
||||
|
||||
int getAnyFreePort()
|
||||
@ -87,7 +83,7 @@ namespace ix
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
{
|
||||
log("Cannot compute a free port. socket error.");
|
||||
return getAnyFreePortRandom();
|
||||
return defaultPort;
|
||||
}
|
||||
|
||||
int enable = 1;
|
||||
@ -95,7 +91,7 @@ namespace ix
|
||||
(char*) &enable, sizeof(enable)) < 0)
|
||||
{
|
||||
log("Cannot compute a free port. setsockopt error.");
|
||||
return getAnyFreePortRandom();
|
||||
return defaultPort;
|
||||
}
|
||||
|
||||
// Bind to port 0. This is the standard way to get a free port.
|
||||
@ -108,22 +104,22 @@ namespace ix
|
||||
{
|
||||
log("Cannot compute a free port. bind error.");
|
||||
|
||||
Socket::closeSocket(sockfd);
|
||||
return getAnyFreePortRandom();
|
||||
::close(sockfd);
|
||||
return defaultPort;
|
||||
}
|
||||
|
||||
struct sockaddr_in sa; // server address information
|
||||
socklen_t len = sizeof(sa);
|
||||
socklen_t len;
|
||||
if (getsockname(sockfd, (struct sockaddr *) &sa, &len) < 0)
|
||||
{
|
||||
log("Cannot compute a free port. getsockname error.");
|
||||
|
||||
Socket::closeSocket(sockfd);
|
||||
return getAnyFreePortRandom();
|
||||
::close(sockfd);
|
||||
return defaultPort;
|
||||
}
|
||||
|
||||
int port = ntohs(sa.sin_port);
|
||||
Socket::closeSocket(sockfd);
|
||||
::close(sockfd);
|
||||
|
||||
return port;
|
||||
}
|
||||
@ -134,7 +130,7 @@ namespace ix
|
||||
{
|
||||
#if defined(__has_feature)
|
||||
# if __has_feature(address_sanitizer)
|
||||
int port = getAnyFreePortRandom();
|
||||
int port = getAnyFreePortSimple();
|
||||
# else
|
||||
int port = getAnyFreePort();
|
||||
# endif
|
||||
|
@ -52,5 +52,6 @@ namespace ix
|
||||
|
||||
void log(const std::string& msg);
|
||||
|
||||
bool computeFreePorts(int count);
|
||||
int getFreePort();
|
||||
}
|
||||
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* IXSocketTest.cpp
|
||||
* Author: Korchynskyi Dmytro
|
||||
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <ixwebsocket/IXUrlParser.h>
|
||||
|
||||
#include "IXTest.h"
|
||||
#include "catch.hpp"
|
||||
#include <string.h>
|
||||
|
||||
using namespace ix;
|
||||
|
||||
namespace ix
|
||||
{
|
||||
|
||||
TEST_CASE("urlParser", "[urlParser]")
|
||||
{
|
||||
SECTION("http://google.com")
|
||||
{
|
||||
std::string url = "http://google.com";
|
||||
std::string protocol, host, path, query;
|
||||
int port;
|
||||
bool res;
|
||||
|
||||
res = UrlParser::parse(url, protocol, host, path, query, port);
|
||||
|
||||
REQUIRE(res);
|
||||
REQUIRE(protocol == "http");
|
||||
REQUIRE(host == "google.com");
|
||||
REQUIRE(path == "/");
|
||||
REQUIRE(query == "");
|
||||
REQUIRE(port == 80); // default port for http
|
||||
}
|
||||
|
||||
SECTION("https://google.com")
|
||||
{
|
||||
std::string url = "https://google.com";
|
||||
std::string protocol, host, path, query;
|
||||
int port;
|
||||
bool res;
|
||||
|
||||
res = UrlParser::parse(url, protocol, host, path, query, port);
|
||||
|
||||
REQUIRE(res);
|
||||
REQUIRE(protocol == "https");
|
||||
REQUIRE(host == "google.com");
|
||||
REQUIRE(path == "/");
|
||||
REQUIRE(query == "");
|
||||
REQUIRE(port == 443); // default port for https
|
||||
}
|
||||
|
||||
SECTION("ws://google.com")
|
||||
{
|
||||
std::string url = "ws://google.com";
|
||||
std::string protocol, host, path, query;
|
||||
int port;
|
||||
bool res;
|
||||
|
||||
res = UrlParser::parse(url, protocol, host, path, query, port);
|
||||
|
||||
REQUIRE(res);
|
||||
REQUIRE(protocol == "ws");
|
||||
REQUIRE(host == "google.com");
|
||||
REQUIRE(path == "/");
|
||||
REQUIRE(query == "");
|
||||
REQUIRE(port == 80); // default port for ws
|
||||
}
|
||||
|
||||
SECTION("wss://google.com/ws?arg=value")
|
||||
{
|
||||
std::string url = "wss://google.com/ws?arg=value&arg2=value2";
|
||||
std::string protocol, host, path, query;
|
||||
int port;
|
||||
bool res;
|
||||
|
||||
res = UrlParser::parse(url, protocol, host, path, query, port);
|
||||
|
||||
REQUIRE(res);
|
||||
REQUIRE(protocol == "wss");
|
||||
REQUIRE(host == "google.com");
|
||||
REQUIRE(path == "/ws?arg=value&arg2=value2");
|
||||
REQUIRE(query == "arg=value&arg2=value2");
|
||||
REQUIRE(port == 443); // default port for wss
|
||||
}
|
||||
|
||||
SECTION("real test")
|
||||
{
|
||||
std::string url = "ws://127.0.0.1:7350/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status=true&format=protobuf";
|
||||
std::string protocol, host, path, query;
|
||||
int port;
|
||||
bool res;
|
||||
|
||||
res = UrlParser::parse(url, protocol, host, path, query, port);
|
||||
|
||||
REQUIRE(res);
|
||||
REQUIRE(protocol == "ws");
|
||||
REQUIRE(host == "127.0.0.1");
|
||||
REQUIRE(path == "/ws?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status=true&format=protobuf");
|
||||
REQUIRE(query == "token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTcxNzAwNzIsInVpZCI6ImMwZmZjOGE1LTk4OTktNDAwYi1hNGU5LTJjNWM3NjFmNWQxZiIsInVzbiI6InN2YmhOdlNJSmEifQ.5L8BUbpTA4XAHlSrdwhIVlrlIpRtjExepim7Yh5eEO4&status=true&format=protobuf");
|
||||
REQUIRE(port == 7350);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* IXWebSocketPingTest.cpp
|
||||
* IXWebSocketHeartBeatTest.cpp
|
||||
* Author: Benjamin Sergeant
|
||||
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||
*/
|
||||
@ -21,8 +21,9 @@ namespace
|
||||
class WebSocketClient
|
||||
{
|
||||
public:
|
||||
WebSocketClient(int port, bool useHeartBeatMethod);
|
||||
WebSocketClient(int port);
|
||||
|
||||
void subscribe(const std::string& channel);
|
||||
void start();
|
||||
void stop();
|
||||
bool isReady() const;
|
||||
@ -31,12 +32,10 @@ namespace
|
||||
private:
|
||||
ix::WebSocket _webSocket;
|
||||
int _port;
|
||||
bool _useHeartBeatMethod;
|
||||
};
|
||||
|
||||
WebSocketClient::WebSocketClient(int port, bool useHeartBeatMethod)
|
||||
: _port(port),
|
||||
_useHeartBeatMethod(useHeartBeatMethod)
|
||||
WebSocketClient::WebSocketClient(int port)
|
||||
: _port(port)
|
||||
{
|
||||
;
|
||||
}
|
||||
@ -56,7 +55,7 @@ namespace
|
||||
std::string url;
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "ws://127.0.0.1:"
|
||||
ss << "ws://localhost:"
|
||||
<< _port
|
||||
<< "/";
|
||||
|
||||
@ -66,11 +65,9 @@ namespace
|
||||
_webSocket.setUrl(url);
|
||||
|
||||
// The important bit for this test.
|
||||
// Set a 1 second heartbeat with the setter method to test
|
||||
if (_useHeartBeatMethod)
|
||||
_webSocket.setHeartBeatPeriod(1);
|
||||
else
|
||||
_webSocket.setPingInterval(1);
|
||||
// Set a 1 second heartbeat ; if no traffic is present on the connection for 1 second
|
||||
// a ping message will be sent by the client.
|
||||
_webSocket.setHeartBeatPeriod(1);
|
||||
|
||||
std::stringstream ss;
|
||||
log(std::string("Connecting to url: ") + url);
|
||||
@ -179,9 +176,9 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Websocket_ping_no_data_sent_setHeartBeatPeriod", "[setHeartBeatPeriod]")
|
||||
TEST_CASE("Websocket_heartbeat", "[heartbeat]")
|
||||
{
|
||||
SECTION("Make sure that ping messages are sent when no other data are sent.")
|
||||
SECTION("Make sure that ping messages are sent during heartbeat.")
|
||||
{
|
||||
ix::setupWebSocketTrafficTrackerCallback();
|
||||
|
||||
@ -191,168 +188,36 @@ TEST_CASE("Websocket_ping_no_data_sent_setHeartBeatPeriod", "[setHeartBeatPeriod
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
bool useSetHeartBeatPeriodMethod = true;
|
||||
WebSocketClient webSocketClient(port, useSetHeartBeatPeriodMethod);
|
||||
WebSocketClient webSocketClientA(port);
|
||||
WebSocketClient webSocketClientB(port);
|
||||
|
||||
webSocketClient.start();
|
||||
webSocketClientA.start();
|
||||
webSocketClientB.start();
|
||||
|
||||
// Wait for all chat instance to be ready
|
||||
while (true)
|
||||
{
|
||||
if (webSocketClient.isReady()) break;
|
||||
if (webSocketClientA.isReady() && webSocketClientB.isReady()) break;
|
||||
ix::msleep(10);
|
||||
}
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
REQUIRE(server.getClients().size() == 2);
|
||||
|
||||
ix::msleep(1900);
|
||||
ix::msleep(900);
|
||||
webSocketClientB.sendMessage("hello world");
|
||||
ix::msleep(900);
|
||||
webSocketClientB.sendMessage("hello world");
|
||||
ix::msleep(900);
|
||||
|
||||
webSocketClient.stop();
|
||||
webSocketClientA.stop();
|
||||
webSocketClientB.stop();
|
||||
|
||||
|
||||
// Here we test ping interval
|
||||
// -> expected ping messages == 1 as 1900 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 1);
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Websocket_ping_data_sent_setHeartBeatPeriod", "[setHeartBeatPeriod]")
|
||||
{
|
||||
SECTION("Make sure that ping messages are sent, even if other messages are sent")
|
||||
{
|
||||
ix::setupWebSocketTrafficTrackerCallback();
|
||||
|
||||
int port = getFreePort();
|
||||
ix::WebSocketServer server(port);
|
||||
std::atomic<int> serverReceivedPingMessages(0);
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
bool useSetHeartBeatPeriodMethod = true;
|
||||
WebSocketClient webSocketClient(port, useSetHeartBeatPeriodMethod);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
// Wait for all chat instance to be ready
|
||||
while (true)
|
||||
{
|
||||
if (webSocketClient.isReady()) break;
|
||||
ix::msleep(10);
|
||||
}
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(900);
|
||||
webSocketClient.sendMessage("hello world");
|
||||
ix::msleep(900);
|
||||
webSocketClient.sendMessage("hello world");
|
||||
ix::msleep(1100);
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
// Here we test ping interval
|
||||
// client has sent data, but ping should have been sent no matter what
|
||||
// -> expected ping messages == 2 as 900+900+1100 = 2900 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Websocket_ping_no_data_sent_setPingInterval", "[setPingInterval]")
|
||||
{
|
||||
SECTION("Make sure that ping messages are sent when no other data are sent.")
|
||||
{
|
||||
ix::setupWebSocketTrafficTrackerCallback();
|
||||
|
||||
int port = getFreePort();
|
||||
ix::WebSocketServer server(port);
|
||||
std::atomic<int> serverReceivedPingMessages(0);
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
bool useSetHeartBeatPeriodMethod = false; // so use setPingInterval
|
||||
WebSocketClient webSocketClient(port, useSetHeartBeatPeriodMethod);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
// Wait for all chat instance to be ready
|
||||
while (true)
|
||||
{
|
||||
if (webSocketClient.isReady()) break;
|
||||
ix::msleep(10);
|
||||
}
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(2100);
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
|
||||
// Here we test ping interval
|
||||
// -> expected ping messages == 2 as 2100 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Websocket_ping_data_sent_setPingInterval", "[setPingInterval]")
|
||||
{
|
||||
SECTION("Make sure that ping messages are sent, even if other messages are sent")
|
||||
{
|
||||
ix::setupWebSocketTrafficTrackerCallback();
|
||||
|
||||
int port = getFreePort();
|
||||
ix::WebSocketServer server(port);
|
||||
std::atomic<int> serverReceivedPingMessages(0);
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
bool useSetHeartBeatPeriodMethod = false; // so use setPingInterval
|
||||
WebSocketClient webSocketClient(port, useSetHeartBeatPeriodMethod);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
// Wait for all chat instance to be ready
|
||||
while (true)
|
||||
{
|
||||
if (webSocketClient.isReady()) break;
|
||||
ix::msleep(10);
|
||||
}
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(900);
|
||||
webSocketClient.sendMessage("hello world");
|
||||
ix::msleep(900);
|
||||
webSocketClient.sendMessage("hello world");
|
||||
ix::msleep(1300);
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
// without this sleep test fails on Windows
|
||||
ix::msleep(100);
|
||||
|
||||
// Here we test ping interval
|
||||
// client has sent data, but ping should have been sent no matter what
|
||||
// -> expected ping messages == 3 as 900+900+1300 = 3100 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 3);
|
||||
// Here we test heart beat period exceeded for clientA
|
||||
// but it should not be exceeded for clientB which has sent data.
|
||||
// -> expected ping messages == 2, but add a small buffer to make this more reliable.
|
||||
REQUIRE(serverReceivedPingMessages >= 2);
|
||||
REQUIRE(serverReceivedPingMessages <= 4);
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
@ -1,489 +0,0 @@
|
||||
/*
|
||||
* IXWebSocketHeartBeatNoResponseAutoDisconnectTest.cpp
|
||||
* Author: Alexandre Konieczny
|
||||
* Copyright (c) 2019 Machine Zone. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <queue>
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
#include <ixwebsocket/IXWebSocketServer.h>
|
||||
|
||||
#include "IXTest.h"
|
||||
|
||||
#include "catch.hpp"
|
||||
|
||||
using namespace ix;
|
||||
|
||||
namespace
|
||||
{
|
||||
class WebSocketClient
|
||||
{
|
||||
public:
|
||||
WebSocketClient(int port, int pingInterval, int pingTimeout);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
bool isReady() const;
|
||||
bool isClosed() const;
|
||||
void sendMessage(const std::string& text);
|
||||
int getReceivedPongMessages();
|
||||
bool closedDueToPingTimeout();
|
||||
|
||||
private:
|
||||
ix::WebSocket _webSocket;
|
||||
int _port;
|
||||
int _pingInterval;
|
||||
int _pingTimeout;
|
||||
std::atomic<int> _receivedPongMessages;
|
||||
std::atomic<bool> _closedDueToPingTimeout;
|
||||
};
|
||||
|
||||
WebSocketClient::WebSocketClient(int port, int pingInterval, int pingTimeout)
|
||||
: _port(port),
|
||||
_receivedPongMessages(0),
|
||||
_closedDueToPingTimeout(false),
|
||||
_pingInterval(pingInterval),
|
||||
_pingTimeout(pingTimeout)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
bool WebSocketClient::isReady() const
|
||||
{
|
||||
return _webSocket.getReadyState() == ix::WebSocket_ReadyState_Open;
|
||||
}
|
||||
|
||||
bool WebSocketClient::isClosed() const
|
||||
{
|
||||
return _webSocket.getReadyState() == ix::WebSocket_ReadyState_Closed;
|
||||
}
|
||||
|
||||
void WebSocketClient::stop()
|
||||
{
|
||||
_webSocket.stop();
|
||||
}
|
||||
|
||||
void WebSocketClient::start()
|
||||
{
|
||||
std::string url;
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "ws://127.0.0.1:"
|
||||
<< _port
|
||||
<< "/";
|
||||
|
||||
url = ss.str();
|
||||
}
|
||||
|
||||
_webSocket.setUrl(url);
|
||||
|
||||
// The important bit for this test.
|
||||
// Set a ping interval, and a ping timeout
|
||||
_webSocket.setPingInterval(_pingInterval);
|
||||
_webSocket.setPingTimeout(_pingTimeout);
|
||||
|
||||
std::stringstream ss;
|
||||
log(std::string("Connecting to url: ") + url);
|
||||
|
||||
_webSocket.setOnMessageCallback(
|
||||
[this](ix::WebSocketMessageType messageType,
|
||||
const std::string& str,
|
||||
size_t wireSize,
|
||||
const ix::WebSocketErrorInfo& error,
|
||||
const ix::WebSocketOpenInfo& openInfo,
|
||||
const ix::WebSocketCloseInfo& closeInfo)
|
||||
{
|
||||
std::stringstream ss;
|
||||
if (messageType == ix::WebSocket_MessageType_Open)
|
||||
{
|
||||
log("client connected");
|
||||
|
||||
_webSocket.disableAutomaticReconnection();
|
||||
}
|
||||
else if (messageType == ix::WebSocket_MessageType_Close)
|
||||
{
|
||||
log("client disconnected");
|
||||
|
||||
if (closeInfo.code == 1011)
|
||||
{
|
||||
_closedDueToPingTimeout = true;
|
||||
}
|
||||
|
||||
_webSocket.disableAutomaticReconnection();
|
||||
|
||||
}
|
||||
else if (messageType == ix::WebSocket_MessageType_Error)
|
||||
{
|
||||
ss << "Error ! " << error.reason;
|
||||
log(ss.str());
|
||||
|
||||
_webSocket.disableAutomaticReconnection();
|
||||
}
|
||||
else if (messageType == ix::WebSocket_MessageType_Pong)
|
||||
{
|
||||
_receivedPongMessages++;
|
||||
|
||||
ss << "Received pong message " << str;
|
||||
log(ss.str());
|
||||
}
|
||||
else if (messageType == ix::WebSocket_MessageType_Ping)
|
||||
{
|
||||
ss << "Received ping message " << str;
|
||||
log(ss.str());
|
||||
}
|
||||
else if (messageType == ix::WebSocket_MessageType_Message)
|
||||
{
|
||||
ss << "Received message " << str;
|
||||
log(ss.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << "Invalid ix::WebSocketMessageType";
|
||||
log(ss.str());
|
||||
}
|
||||
});
|
||||
|
||||
_webSocket.start();
|
||||
}
|
||||
|
||||
void WebSocketClient::sendMessage(const std::string& text)
|
||||
{
|
||||
_webSocket.send(text);
|
||||
}
|
||||
|
||||
int WebSocketClient::getReceivedPongMessages()
|
||||
{
|
||||
return _receivedPongMessages;
|
||||
}
|
||||
|
||||
bool WebSocketClient::closedDueToPingTimeout()
|
||||
{
|
||||
return _closedDueToPingTimeout;
|
||||
}
|
||||
|
||||
bool startServer(ix::WebSocketServer& server, std::atomic<int>& receivedPingMessages, bool enablePong)
|
||||
{
|
||||
// A dev/null server
|
||||
server.setOnConnectionCallback(
|
||||
[&server, &receivedPingMessages](std::shared_ptr<ix::WebSocket> webSocket,
|
||||
std::shared_ptr<ConnectionState> connectionState)
|
||||
{
|
||||
webSocket->setOnMessageCallback(
|
||||
[webSocket, connectionState, &server, &receivedPingMessages](ix::WebSocketMessageType messageType,
|
||||
const std::string& str,
|
||||
size_t wireSize,
|
||||
const ix::WebSocketErrorInfo& error,
|
||||
const ix::WebSocketOpenInfo& openInfo,
|
||||
const ix::WebSocketCloseInfo& closeInfo)
|
||||
{
|
||||
if (messageType == ix::WebSocket_MessageType_Open)
|
||||
{
|
||||
Logger() << "New server connection";
|
||||
Logger() << "id: " << connectionState->getId();
|
||||
Logger() << "Uri: " << openInfo.uri;
|
||||
Logger() << "Headers:";
|
||||
for (auto it : openInfo.headers)
|
||||
{
|
||||
Logger() << it.first << ": " << it.second;
|
||||
}
|
||||
}
|
||||
else if (messageType == ix::WebSocket_MessageType_Close)
|
||||
{
|
||||
log("Server closed connection");
|
||||
}
|
||||
else if (messageType == ix::WebSocket_MessageType_Ping)
|
||||
{
|
||||
log("Server received a ping");
|
||||
receivedPingMessages++;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
if (!enablePong)
|
||||
{
|
||||
// USE this to prevent a pong answer, so the ping timeout is raised on client
|
||||
server.disablePong();
|
||||
}
|
||||
|
||||
auto res = server.listen();
|
||||
if (!res.first)
|
||||
{
|
||||
log(res.second);
|
||||
return false;
|
||||
}
|
||||
|
||||
server.start();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Websocket_ping_timeout_not_checked", "[setPingTimeout]")
|
||||
{
|
||||
SECTION("Make sure that ping messages have a response (PONG).")
|
||||
{
|
||||
ix::setupWebSocketTrafficTrackerCallback();
|
||||
|
||||
int port = getFreePort();
|
||||
ix::WebSocketServer server(port);
|
||||
std::atomic<int> serverReceivedPingMessages(0);
|
||||
bool enablePong = false; // Pong is disabled on Server
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages, enablePong));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
int pingIntervalSecs = 1;
|
||||
int pingTimeoutSecs = -1; // ping timeout not checked
|
||||
WebSocketClient webSocketClient(port, pingIntervalSecs, pingTimeoutSecs);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
// Wait for all chat instance to be ready
|
||||
while (true)
|
||||
{
|
||||
if (webSocketClient.isReady()) break;
|
||||
ix::msleep(10);
|
||||
}
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(1100);
|
||||
|
||||
// Here we test ping timeout, no timeout
|
||||
REQUIRE(serverReceivedPingMessages == 1);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
|
||||
|
||||
ix::msleep(1000);
|
||||
|
||||
// Here we test ping timeout, no timeout
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
// Ensure client close was not by ping timeout
|
||||
REQUIRE(webSocketClient.closedDueToPingTimeout() == false);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Websocket_ping_no_timeout", "[setPingTimeout]")
|
||||
{
|
||||
SECTION("Make sure that ping messages have a response (PONG).")
|
||||
{
|
||||
ix::setupWebSocketTrafficTrackerCallback();
|
||||
|
||||
int port = getFreePort();
|
||||
ix::WebSocketServer server(port);
|
||||
std::atomic<int> serverReceivedPingMessages(0);
|
||||
bool enablePong = true; // Pong is enabled on Server
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages, enablePong));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
int pingIntervalSecs = 1;
|
||||
int pingTimeoutSecs = 2;
|
||||
WebSocketClient webSocketClient(port, pingIntervalSecs, pingTimeoutSecs);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
// Wait for all chat instance to be ready
|
||||
while (true)
|
||||
{
|
||||
if (webSocketClient.isReady()) break;
|
||||
ix::msleep(10);
|
||||
}
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(1100);
|
||||
|
||||
// Here we test ping timeout, no timeout
|
||||
REQUIRE(serverReceivedPingMessages == 1);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 1);
|
||||
|
||||
ix::msleep(1000);
|
||||
|
||||
// Here we test ping timeout, no timeout
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 2);
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
// Ensure client close was not by ping timeout
|
||||
REQUIRE(webSocketClient.closedDueToPingTimeout() == false);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Websocket_no_ping_but_timeout", "[setPingTimeout]")
|
||||
{
|
||||
SECTION("Make sure that ping messages don't have responses (no PONG).")
|
||||
{
|
||||
ix::setupWebSocketTrafficTrackerCallback();
|
||||
|
||||
int port = getFreePort();
|
||||
ix::WebSocketServer server(port);
|
||||
std::atomic<int> serverReceivedPingMessages(0);
|
||||
bool enablePong = false; // Pong is disabled on Server
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages, enablePong));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
int pingIntervalSecs = -1; // no ping set
|
||||
int pingTimeoutSecs = 3;
|
||||
WebSocketClient webSocketClient(port, pingIntervalSecs, pingTimeoutSecs);
|
||||
webSocketClient.start();
|
||||
|
||||
// Wait for all chat instance to be ready
|
||||
while (true)
|
||||
{
|
||||
if (webSocketClient.isReady()) break;
|
||||
ix::msleep(10);
|
||||
}
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(2900);
|
||||
|
||||
// Here we test ping timeout, no timeout yet
|
||||
REQUIRE(serverReceivedPingMessages == 0);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
|
||||
|
||||
REQUIRE(webSocketClient.isClosed() == false);
|
||||
REQUIRE(webSocketClient.closedDueToPingTimeout() == false);
|
||||
|
||||
ix::msleep(200);
|
||||
|
||||
// Here we test ping timeout, timeout
|
||||
REQUIRE(serverReceivedPingMessages == 0);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
|
||||
// Ensure client close was not by ping timeout
|
||||
REQUIRE(webSocketClient.isClosed() == true);
|
||||
REQUIRE(webSocketClient.closedDueToPingTimeout() == true);
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Websocket_ping_timeout", "[setPingTimeout]")
|
||||
{
|
||||
SECTION("Make sure that ping messages don't have responses (no PONG).")
|
||||
{
|
||||
ix::setupWebSocketTrafficTrackerCallback();
|
||||
|
||||
int port = getFreePort();
|
||||
ix::WebSocketServer server(port);
|
||||
std::atomic<int> serverReceivedPingMessages(0);
|
||||
bool enablePong = false; // Pong is disabled on Server
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages, enablePong));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
int pingIntervalSecs = 1;
|
||||
int pingTimeoutSecs = 2;
|
||||
WebSocketClient webSocketClient(port, pingIntervalSecs, pingTimeoutSecs);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
// Wait for all chat instance to be ready
|
||||
while (true)
|
||||
{
|
||||
if (webSocketClient.isReady()) break;
|
||||
ix::msleep(10);
|
||||
}
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(1100);
|
||||
|
||||
// Here we test ping timeout, no timeout yet
|
||||
REQUIRE(serverReceivedPingMessages == 1);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
|
||||
|
||||
ix::msleep(1000);
|
||||
|
||||
// Here we test ping timeout, timeout
|
||||
REQUIRE(serverReceivedPingMessages == 1);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
|
||||
// Ensure client close was not by ping timeout
|
||||
REQUIRE(webSocketClient.isClosed() == true);
|
||||
REQUIRE(webSocketClient.closedDueToPingTimeout() == true);
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // this test fails on travis / commenting it out for now to get back to a green travis state
|
||||
TEST_CASE("Websocket_ping_long_timeout", "[setPingTimeout]")
|
||||
{
|
||||
SECTION("Make sure that ping messages don't have responses (no PONG).")
|
||||
{
|
||||
ix::setupWebSocketTrafficTrackerCallback();
|
||||
|
||||
int port = getFreePort();
|
||||
ix::WebSocketServer server(port);
|
||||
std::atomic<int> serverReceivedPingMessages(0);
|
||||
bool enablePong = false; // Pong is disabled on Server
|
||||
REQUIRE(startServer(server, serverReceivedPingMessages, enablePong));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
int pingIntervalSecs = 2;
|
||||
int pingTimeoutSecs = 6;
|
||||
WebSocketClient webSocketClient(port, pingIntervalSecs, pingTimeoutSecs);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
// Wait for all chat instance to be ready
|
||||
while (true)
|
||||
{
|
||||
if (webSocketClient.isReady()) break;
|
||||
ix::msleep(10);
|
||||
}
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(5900);
|
||||
|
||||
// Here we test ping timeout, no timeout yet (2 ping sent at 2s and 4s)
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
|
||||
|
||||
// Ensure client not closed
|
||||
REQUIRE(webSocketClient.isClosed() == false);
|
||||
REQUIRE(webSocketClient.closedDueToPingTimeout() == false);
|
||||
|
||||
ix::msleep(200);
|
||||
|
||||
// Here we test ping timeout, timeout (at 6 seconds)
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
|
||||
// Ensure client close was not by ping timeout
|
||||
REQUIRE(webSocketClient.isClosed() == true);
|
||||
REQUIRE(webSocketClient.closedDueToPingTimeout() == true);
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
#endif
|
@ -107,7 +107,7 @@ TEST_CASE("Websocket_server", "[websocket_server]")
|
||||
std::string errMsg;
|
||||
bool tls = false;
|
||||
std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
|
||||
std::string host("127.0.0.1");
|
||||
std::string host("localhost");
|
||||
auto isCancellationRequested = []() -> bool
|
||||
{
|
||||
return false;
|
||||
@ -141,7 +141,7 @@ TEST_CASE("Websocket_server", "[websocket_server]")
|
||||
std::string errMsg;
|
||||
bool tls = false;
|
||||
std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
|
||||
std::string host("127.0.0.1");
|
||||
std::string host("localhost");
|
||||
auto isCancellationRequested = []() -> bool
|
||||
{
|
||||
return false;
|
||||
@ -178,7 +178,7 @@ TEST_CASE("Websocket_server", "[websocket_server]")
|
||||
std::string errMsg;
|
||||
bool tls = false;
|
||||
std::shared_ptr<Socket> socket = createSocket(tls, errMsg);
|
||||
std::string host("127.0.0.1");
|
||||
std::string host("localhost");
|
||||
auto isCancellationRequested = []() -> bool
|
||||
{
|
||||
return false;
|
||||
@ -204,8 +204,9 @@ TEST_CASE("Websocket_server", "[websocket_server]")
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
|
||||
server.stop();
|
||||
REQUIRE(connectionId == "foobarConnectionId");
|
||||
|
||||
server.stop();
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ namespace
|
||||
std::string url;
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "ws://127.0.0.1:"
|
||||
ss << "ws://localhost:"
|
||||
<< _port
|
||||
<< "/"
|
||||
<< _user;
|
||||
|
42
test/run.py
42
test/run.py
@ -1,9 +1,5 @@
|
||||
#!/usr/bin/env python2.7
|
||||
'''
|
||||
Windows notes:
|
||||
generator = '-G"NMake Makefiles"'
|
||||
make = 'nmake'
|
||||
testBinary ='ixwebsocket_unittest.exe'
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
@ -103,25 +99,19 @@ def runCMake(sanitizer, buildDir):
|
||||
'tsan': '-DSANITIZE_THREAD=On',
|
||||
'none': ''
|
||||
}
|
||||
sanitizerFlag = sanitizersFlags.get(sanitizer, '')
|
||||
sanitizerFlag = sanitizersFlags[sanitizer]
|
||||
|
||||
# CMake installed via Self Service ends up here.
|
||||
cmakeExecutable = '/Applications/CMake.app/Contents/bin/cmake'
|
||||
if not os.path.exists(cmakeExecutable):
|
||||
cmakeExecutable = 'cmake'
|
||||
|
||||
generator = '"Unix Makefiles"'
|
||||
if platform.system() == 'Windows':
|
||||
generator = '"NMake Makefiles"'
|
||||
|
||||
fmt = '''
|
||||
{cmakeExecutable} -H. \
|
||||
{sanitizerFlag} \
|
||||
-B{buildDir} \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DUSE_TLS=1 \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||
-G{generator}
|
||||
'''
|
||||
cmakeCmd = fmt.format(**locals())
|
||||
runCommand(cmakeCmd)
|
||||
@ -249,7 +239,6 @@ def executeJob(job):
|
||||
start = time.time()
|
||||
|
||||
sys.stderr.write('.')
|
||||
# print('Executing ' + job['cmd'] + '...')
|
||||
|
||||
# 2 minutes of timeout for a single test
|
||||
timeout = 2 * 60
|
||||
@ -361,20 +350,8 @@ def generateXmlOutput(results, xmlOutput, testRunName, runTime):
|
||||
def run(testName, buildDir, sanitizer, xmlOutput, testRunName, buildOnly, useLLDB):
|
||||
'''Main driver. Run cmake, compiles, execute and validate the testsuite.'''
|
||||
|
||||
# gen build files with CMake
|
||||
runCMake(sanitizer, buildDir)
|
||||
|
||||
# build with make
|
||||
makeCmd = 'make'
|
||||
jobs = '-j8'
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
makeCmd = 'nmake'
|
||||
|
||||
# nmake does not have a -j option
|
||||
jobs = ''
|
||||
|
||||
runCommand('{} -C {} {}'.format(makeCmd, buildDir, jobs))
|
||||
runCommand('make -C {} -j8'.format(buildDir))
|
||||
|
||||
if buildOnly:
|
||||
return
|
||||
@ -411,10 +388,7 @@ def run(testName, buildDir, sanitizer, xmlOutput, testRunName, buildOnly, useLLD
|
||||
# testName can contains spaces, so we enclose them in double quotes
|
||||
executable = os.path.join(buildDir, DEFAULT_EXE)
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
executable += '.exe'
|
||||
|
||||
cmd = '{} "{}" "{}" > "{}" 2>&1'.format(lldb, executable, testName, outputPath)
|
||||
cmd = '{} "{}" "{}" >& "{}"'.format(lldb, executable, testName, outputPath)
|
||||
|
||||
jobs.append({
|
||||
'name': testName,
|
||||
@ -447,10 +421,7 @@ def run(testName, buildDir, sanitizer, xmlOutput, testRunName, buildOnly, useLLD
|
||||
|
||||
|
||||
def main():
|
||||
root = os.path.dirname(os.path.realpath(__file__))
|
||||
os.chdir(root)
|
||||
|
||||
buildDir = os.path.join(root, 'build', platform.system())
|
||||
buildDir = 'build/' + platform.system()
|
||||
if not os.path.exists(buildDir):
|
||||
os.makedirs(buildDir)
|
||||
|
||||
@ -505,11 +476,6 @@ def main():
|
||||
print('LLDB is only supported on Apple at this point')
|
||||
args.lldb = False
|
||||
|
||||
# Sanitizers display lots of strange errors on Linux on CI,
|
||||
# which looks like false positives
|
||||
if platform.system() != 'Darwin':
|
||||
sanitizer = 'none'
|
||||
|
||||
return run(args.test, buildDir, sanitizer, xmlOutput,
|
||||
testRunName, args.build_only, args.lldb)
|
||||
|
||||
|
@ -7,14 +7,8 @@
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <ixwebsocket/IXNetSystem.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
ix::initNetSystem();
|
||||
|
||||
int result = Catch::Session().run(argc, argv);
|
||||
|
||||
ix::uninitNetSystem();
|
||||
return result;
|
||||
}
|
||||
|
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.dll
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.dll
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.pdb
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.pdb
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.exp
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.exp
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.ilk
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.ilk
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.lib
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.lib
vendored
Normal file
Binary file not shown.
@ -7,8 +7,8 @@
|
||||
|
||||
#ifndef ZCONF_H
|
||||
#define ZCONF_H
|
||||
#cmakedefine Z_PREFIX
|
||||
#cmakedefine Z_HAVE_UNISTD_H
|
||||
/* #undef Z_PREFIX */
|
||||
/* #undef Z_HAVE_UNISTD_H */
|
||||
|
||||
/*
|
||||
* If you *really* need a unique prefix for all types and library functions,
|
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/bin/zlib.dll
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/bin/zlib.dll
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.exp
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.exp
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.lib
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.lib
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.dll
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.dll
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.pdb
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.pdb
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.exp
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.exp
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.ilk
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.ilk
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.lib
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.lib
vendored
Normal file
Binary file not shown.
@ -7,6 +7,8 @@
|
||||
|
||||
#ifndef ZCONF_H
|
||||
#define ZCONF_H
|
||||
/* #undef Z_PREFIX */
|
||||
/* #undef Z_HAVE_UNISTD_H */
|
||||
|
||||
/*
|
||||
* If you *really* need a unique prefix for all types and library functions,
|
1913
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/include/zlib.h
vendored
Normal file
1913
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/include/zlib.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/bin/zlib.dll
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/bin/zlib.dll
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.exp
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.exp
vendored
Normal file
Binary file not shown.
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.lib
vendored
Normal file
BIN
third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.lib
vendored
Normal file
Binary file not shown.
@ -49,7 +49,7 @@ StatsdClient::StatsdClient(const string& host,
|
||||
d = new _StatsdClientData;
|
||||
d->sock = -1;
|
||||
config(host, port, ns);
|
||||
srandom((unsigned) time(NULL));
|
||||
srandom(time(NULL));
|
||||
|
||||
if (batching_) {
|
||||
pthread_mutex_init(&batching_mutex_lock_, nullptr);
|
||||
@ -227,7 +227,7 @@ int StatsdClient::send_to_daemon(const string &message) {
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
ret = (int) sendto(d->sock, message.data(), message.size(), 0, (struct sockaddr *) &d->server, sizeof(d->server));
|
||||
ret = sendto(d->sock, message.data(), message.size(), 0, (struct sockaddr *) &d->server, sizeof(d->server));
|
||||
if ( ret == -1) {
|
||||
snprintf(d->errmsg, sizeof(d->errmsg),
|
||||
"sendto server fail, host=%s:%d, err=%m", d->host.c_str(), d->port);
|
||||
|
@ -61,6 +61,6 @@ protected:
|
||||
const uint64_t max_batching_size = 32768;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
}; // end namespace
|
||||
|
||||
#endif
|
||||
|
26
third_party/zlib/.gitignore
vendored
26
third_party/zlib/.gitignore
vendored
@ -1,26 +0,0 @@
|
||||
*.diff
|
||||
*.patch
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
*~
|
||||
*.a
|
||||
*.lo
|
||||
*.o
|
||||
*.dylib
|
||||
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.gcov
|
||||
|
||||
/example
|
||||
/example64
|
||||
/examplesh
|
||||
/libz.so*
|
||||
/minigzip
|
||||
/minigzip64
|
||||
/minigzipsh
|
||||
/zlib.pc
|
||||
/configure.log
|
||||
|
||||
.DS_Store
|
249
third_party/zlib/CMakeLists.txt
vendored
249
third_party/zlib/CMakeLists.txt
vendored
@ -1,249 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.4.4)
|
||||
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
|
||||
|
||||
project(zlib C)
|
||||
|
||||
set(VERSION "1.2.11")
|
||||
|
||||
option(ASM686 "Enable building i686 assembly implementation")
|
||||
option(AMD64 "Enable building amd64 assembly implementation")
|
||||
|
||||
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
|
||||
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
|
||||
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
|
||||
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
|
||||
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
|
||||
|
||||
include(CheckTypeSize)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckCSourceCompiles)
|
||||
enable_testing()
|
||||
|
||||
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
|
||||
check_include_file(stdint.h HAVE_STDINT_H)
|
||||
check_include_file(stddef.h HAVE_STDDEF_H)
|
||||
|
||||
#
|
||||
# Check to see if we have large file support
|
||||
#
|
||||
set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1)
|
||||
# We add these other definitions here because CheckTypeSize.cmake
|
||||
# in CMake 2.4.x does not automatically do so and we want
|
||||
# compatibility with CMake 2.4.x.
|
||||
if(HAVE_SYS_TYPES_H)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
|
||||
endif()
|
||||
if(HAVE_STDINT_H)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
|
||||
endif()
|
||||
if(HAVE_STDDEF_H)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
|
||||
endif()
|
||||
check_type_size(off64_t OFF64_T)
|
||||
if(HAVE_OFF64_T)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE=1)
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
|
||||
|
||||
#
|
||||
# Check for fseeko
|
||||
#
|
||||
check_function_exists(fseeko HAVE_FSEEKO)
|
||||
if(NOT HAVE_FSEEKO)
|
||||
add_definitions(-DNO_FSEEKO)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Check for unistd.h
|
||||
#
|
||||
check_include_file(unistd.h Z_HAVE_UNISTD_H)
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||
# If we're doing an out of source build and the user has a zconf.h
|
||||
# in their source tree...
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h)
|
||||
message(STATUS "Renaming")
|
||||
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h")
|
||||
message(STATUS "to 'zconf.h.included' because this file is included with zlib")
|
||||
message(STATUS "but CMake generates it automatically in the build directory.")
|
||||
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
|
||||
${ZLIB_PC} @ONLY)
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
|
||||
|
||||
|
||||
#============================================================================
|
||||
# zlib
|
||||
#============================================================================
|
||||
|
||||
set(ZLIB_PUBLIC_HDRS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zconf.h
|
||||
zlib.h
|
||||
)
|
||||
set(ZLIB_PRIVATE_HDRS
|
||||
crc32.h
|
||||
deflate.h
|
||||
gzguts.h
|
||||
inffast.h
|
||||
inffixed.h
|
||||
inflate.h
|
||||
inftrees.h
|
||||
trees.h
|
||||
zutil.h
|
||||
)
|
||||
set(ZLIB_SRCS
|
||||
adler32.c
|
||||
compress.c
|
||||
crc32.c
|
||||
deflate.c
|
||||
gzclose.c
|
||||
gzlib.c
|
||||
gzread.c
|
||||
gzwrite.c
|
||||
inflate.c
|
||||
infback.c
|
||||
inftrees.c
|
||||
inffast.c
|
||||
trees.c
|
||||
uncompr.c
|
||||
zutil.c
|
||||
)
|
||||
|
||||
if(NOT MINGW)
|
||||
set(ZLIB_DLL_SRCS
|
||||
win32/zlib1.rc # If present will override custom build rule below.
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
if(ASM686)
|
||||
set(ZLIB_ASMS contrib/asm686/match.S)
|
||||
elseif (AMD64)
|
||||
set(ZLIB_ASMS contrib/amd64/amd64-match.S)
|
||||
endif ()
|
||||
|
||||
if(ZLIB_ASMS)
|
||||
add_definitions(-DASMV)
|
||||
set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
if(ASM686)
|
||||
ENABLE_LANGUAGE(ASM_MASM)
|
||||
set(ZLIB_ASMS
|
||||
contrib/masmx86/inffas32.asm
|
||||
contrib/masmx86/match686.asm
|
||||
)
|
||||
elseif (AMD64)
|
||||
ENABLE_LANGUAGE(ASM_MASM)
|
||||
set(ZLIB_ASMS
|
||||
contrib/masmx64/gvmat64.asm
|
||||
contrib/masmx64/inffasx64.asm
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ZLIB_ASMS)
|
||||
add_definitions(-DASMV -DASMINF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents)
|
||||
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
|
||||
"\\1" ZLIB_FULL_VERSION ${_zlib_h_contents})
|
||||
|
||||
if(MINGW)
|
||||
# This gets us DLL resource information when compiling on MinGW.
|
||||
if(NOT CMAKE_RC_COMPILER)
|
||||
set(CMAKE_RC_COMPILER windres.exe)
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
||||
COMMAND ${CMAKE_RC_COMPILER}
|
||||
-D GCC_WINDRES
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-I ${CMAKE_CURRENT_BINARY_DIR}
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
|
||||
-i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc)
|
||||
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
|
||||
endif(MINGW)
|
||||
|
||||
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
|
||||
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
|
||||
set_target_properties(zlib PROPERTIES SOVERSION 1)
|
||||
|
||||
if(NOT CYGWIN)
|
||||
# This property causes shared libraries on Linux to have the full version
|
||||
# encoded into their final filename. We disable this on Cygwin because
|
||||
# it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
|
||||
# seems to be the default.
|
||||
#
|
||||
# This has no effect with MSVC, on that platform the version info for
|
||||
# the DLL comes from the resource file win32/zlib1.rc
|
||||
set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
# On unix-like platforms the library is almost always called libz
|
||||
set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
|
||||
if(NOT APPLE)
|
||||
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
|
||||
endif()
|
||||
elseif(BUILD_SHARED_LIBS AND WIN32)
|
||||
# Creates zlib1.dll when building shared library version
|
||||
set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
|
||||
endif()
|
||||
|
||||
if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
|
||||
install(TARGETS zlib zlibstatic
|
||||
RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
|
||||
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}")
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3")
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
|
||||
endif()
|
||||
|
||||
#============================================================================
|
||||
# Example binaries
|
||||
#============================================================================
|
||||
|
||||
add_executable(example test/example.c)
|
||||
target_link_libraries(example zlib)
|
||||
add_test(example example)
|
||||
|
||||
add_executable(minigzip test/minigzip.c)
|
||||
target_link_libraries(minigzip zlib)
|
||||
|
||||
if(HAVE_OFF64_T)
|
||||
add_executable(example64 test/example.c)
|
||||
target_link_libraries(example64 zlib)
|
||||
set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||
add_test(example64 example64)
|
||||
|
||||
add_executable(minigzip64 test/minigzip.c)
|
||||
target_link_libraries(minigzip64 zlib)
|
||||
set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||
endif()
|
1515
third_party/zlib/ChangeLog
vendored
1515
third_party/zlib/ChangeLog
vendored
File diff suppressed because it is too large
Load Diff
368
third_party/zlib/FAQ
vendored
368
third_party/zlib/FAQ
vendored
@ -1,368 +0,0 @@
|
||||
|
||||
Frequently Asked Questions about zlib
|
||||
|
||||
|
||||
If your question is not there, please check the zlib home page
|
||||
http://zlib.net/ which may have more recent information.
|
||||
The lastest zlib FAQ is at http://zlib.net/zlib_faq.html
|
||||
|
||||
|
||||
1. Is zlib Y2K-compliant?
|
||||
|
||||
Yes. zlib doesn't handle dates.
|
||||
|
||||
2. Where can I get a Windows DLL version?
|
||||
|
||||
The zlib sources can be compiled without change to produce a DLL. See the
|
||||
file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the
|
||||
precompiled DLL are found in the zlib web site at http://zlib.net/ .
|
||||
|
||||
3. Where can I get a Visual Basic interface to zlib?
|
||||
|
||||
See
|
||||
* http://marknelson.us/1997/01/01/zlib-engine/
|
||||
* win32/DLL_FAQ.txt in the zlib distribution
|
||||
|
||||
4. compress() returns Z_BUF_ERROR.
|
||||
|
||||
Make sure that before the call of compress(), the length of the compressed
|
||||
buffer is equal to the available size of the compressed buffer and not
|
||||
zero. For Visual Basic, check that this parameter is passed by reference
|
||||
("as any"), not by value ("as long").
|
||||
|
||||
5. deflate() or inflate() returns Z_BUF_ERROR.
|
||||
|
||||
Before making the call, make sure that avail_in and avail_out are not zero.
|
||||
When setting the parameter flush equal to Z_FINISH, also make sure that
|
||||
avail_out is big enough to allow processing all pending input. Note that a
|
||||
Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be
|
||||
made with more input or output space. A Z_BUF_ERROR may in fact be
|
||||
unavoidable depending on how the functions are used, since it is not
|
||||
possible to tell whether or not there is more output pending when
|
||||
strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a
|
||||
heavily annotated example.
|
||||
|
||||
6. Where's the zlib documentation (man pages, etc.)?
|
||||
|
||||
It's in zlib.h . Examples of zlib usage are in the files test/example.c
|
||||
and test/minigzip.c, with more in examples/ .
|
||||
|
||||
7. Why don't you use GNU autoconf or libtool or ...?
|
||||
|
||||
Because we would like to keep zlib as a very small and simple package.
|
||||
zlib is rather portable and doesn't need much configuration.
|
||||
|
||||
8. I found a bug in zlib.
|
||||
|
||||
Most of the time, such problems are due to an incorrect usage of zlib.
|
||||
Please try to reproduce the problem with a small program and send the
|
||||
corresponding source to us at zlib@gzip.org . Do not send multi-megabyte
|
||||
data files without prior agreement.
|
||||
|
||||
9. Why do I get "undefined reference to gzputc"?
|
||||
|
||||
If "make test" produces something like
|
||||
|
||||
example.o(.text+0x154): undefined reference to `gzputc'
|
||||
|
||||
check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
|
||||
/usr/X11R6/lib. Remove any old versions, then do "make install".
|
||||
|
||||
10. I need a Delphi interface to zlib.
|
||||
|
||||
See the contrib/delphi directory in the zlib distribution.
|
||||
|
||||
11. Can zlib handle .zip archives?
|
||||
|
||||
Not by itself, no. See the directory contrib/minizip in the zlib
|
||||
distribution.
|
||||
|
||||
12. Can zlib handle .Z files?
|
||||
|
||||
No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
|
||||
the code of uncompress on your own.
|
||||
|
||||
13. How can I make a Unix shared library?
|
||||
|
||||
By default a shared (and a static) library is built for Unix. So:
|
||||
|
||||
make distclean
|
||||
./configure
|
||||
make
|
||||
|
||||
14. How do I install a shared zlib library on Unix?
|
||||
|
||||
After the above, then:
|
||||
|
||||
make install
|
||||
|
||||
However, many flavors of Unix come with a shared zlib already installed.
|
||||
Before going to the trouble of compiling a shared version of zlib and
|
||||
trying to install it, you may want to check if it's already there! If you
|
||||
can #include <zlib.h>, it's there. The -lz option will probably link to
|
||||
it. You can check the version at the top of zlib.h or with the
|
||||
ZLIB_VERSION symbol defined in zlib.h .
|
||||
|
||||
15. I have a question about OttoPDF.
|
||||
|
||||
We are not the authors of OttoPDF. The real author is on the OttoPDF web
|
||||
site: Joel Hainley, jhainley@myndkryme.com.
|
||||
|
||||
16. Can zlib decode Flate data in an Adobe PDF file?
|
||||
|
||||
Yes. See http://www.pdflib.com/ . To modify PDF forms, see
|
||||
http://sourceforge.net/projects/acroformtool/ .
|
||||
|
||||
17. Why am I getting this "register_frame_info not found" error on Solaris?
|
||||
|
||||
After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
|
||||
generates an error such as:
|
||||
|
||||
ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
|
||||
symbol __register_frame_info: referenced symbol not found
|
||||
|
||||
The symbol __register_frame_info is not part of zlib, it is generated by
|
||||
the C compiler (cc or gcc). You must recompile applications using zlib
|
||||
which have this problem. This problem is specific to Solaris. See
|
||||
http://www.sunfreeware.com for Solaris versions of zlib and applications
|
||||
using zlib.
|
||||
|
||||
18. Why does gzip give an error on a file I make with compress/deflate?
|
||||
|
||||
The compress and deflate functions produce data in the zlib format, which
|
||||
is different and incompatible with the gzip format. The gz* functions in
|
||||
zlib on the other hand use the gzip format. Both the zlib and gzip formats
|
||||
use the same compressed data format internally, but have different headers
|
||||
and trailers around the compressed data.
|
||||
|
||||
19. Ok, so why are there two different formats?
|
||||
|
||||
The gzip format was designed to retain the directory information about a
|
||||
single file, such as the name and last modification date. The zlib format
|
||||
on the other hand was designed for in-memory and communication channel
|
||||
applications, and has a much more compact header and trailer and uses a
|
||||
faster integrity check than gzip.
|
||||
|
||||
20. Well that's nice, but how do I make a gzip file in memory?
|
||||
|
||||
You can request that deflate write the gzip format instead of the zlib
|
||||
format using deflateInit2(). You can also request that inflate decode the
|
||||
gzip format using inflateInit2(). Read zlib.h for more details.
|
||||
|
||||
21. Is zlib thread-safe?
|
||||
|
||||
Yes. However any library routines that zlib uses and any application-
|
||||
provided memory allocation routines must also be thread-safe. zlib's gz*
|
||||
functions use stdio library routines, and most of zlib's functions use the
|
||||
library memory allocation routines by default. zlib's *Init* functions
|
||||
allow for the application to provide custom memory allocation routines.
|
||||
|
||||
Of course, you should only operate on any given zlib or gzip stream from a
|
||||
single thread at a time.
|
||||
|
||||
22. Can I use zlib in my commercial application?
|
||||
|
||||
Yes. Please read the license in zlib.h.
|
||||
|
||||
23. Is zlib under the GNU license?
|
||||
|
||||
No. Please read the license in zlib.h.
|
||||
|
||||
24. The license says that altered source versions must be "plainly marked". So
|
||||
what exactly do I need to do to meet that requirement?
|
||||
|
||||
You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
|
||||
particular, the final version number needs to be changed to "f", and an
|
||||
identification string should be appended to ZLIB_VERSION. Version numbers
|
||||
x.x.x.f are reserved for modifications to zlib by others than the zlib
|
||||
maintainers. For example, if the version of the base zlib you are altering
|
||||
is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
|
||||
ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
|
||||
update the version strings in deflate.c and inftrees.c.
|
||||
|
||||
For altered source distributions, you should also note the origin and
|
||||
nature of the changes in zlib.h, as well as in ChangeLog and README, along
|
||||
with the dates of the alterations. The origin should include at least your
|
||||
name (or your company's name), and an email address to contact for help or
|
||||
issues with the library.
|
||||
|
||||
Note that distributing a compiled zlib library along with zlib.h and
|
||||
zconf.h is also a source distribution, and so you should change
|
||||
ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
|
||||
in zlib.h as you would for a full source distribution.
|
||||
|
||||
25. Will zlib work on a big-endian or little-endian architecture, and can I
|
||||
exchange compressed data between them?
|
||||
|
||||
Yes and yes.
|
||||
|
||||
26. Will zlib work on a 64-bit machine?
|
||||
|
||||
Yes. It has been tested on 64-bit machines, and has no dependence on any
|
||||
data types being limited to 32-bits in length. If you have any
|
||||
difficulties, please provide a complete problem report to zlib@gzip.org
|
||||
|
||||
27. Will zlib decompress data from the PKWare Data Compression Library?
|
||||
|
||||
No. The PKWare DCL uses a completely different compressed data format than
|
||||
does PKZIP and zlib. However, you can look in zlib's contrib/blast
|
||||
directory for a possible solution to your problem.
|
||||
|
||||
28. Can I access data randomly in a compressed stream?
|
||||
|
||||
No, not without some preparation. If when compressing you periodically use
|
||||
Z_FULL_FLUSH, carefully write all the pending data at those points, and
|
||||
keep an index of those locations, then you can start decompression at those
|
||||
points. You have to be careful to not use Z_FULL_FLUSH too often, since it
|
||||
can significantly degrade compression. Alternatively, you can scan a
|
||||
deflate stream once to generate an index, and then use that index for
|
||||
random access. See examples/zran.c .
|
||||
|
||||
29. Does zlib work on MVS, OS/390, CICS, etc.?
|
||||
|
||||
It has in the past, but we have not heard of any recent evidence. There
|
||||
were working ports of zlib 1.1.4 to MVS, but those links no longer work.
|
||||
If you know of recent, successful applications of zlib on these operating
|
||||
systems, please let us know. Thanks.
|
||||
|
||||
30. Is there some simpler, easier to read version of inflate I can look at to
|
||||
understand the deflate format?
|
||||
|
||||
First off, you should read RFC 1951. Second, yes. Look in zlib's
|
||||
contrib/puff directory.
|
||||
|
||||
31. Does zlib infringe on any patents?
|
||||
|
||||
As far as we know, no. In fact, that was originally the whole point behind
|
||||
zlib. Look here for some more information:
|
||||
|
||||
http://www.gzip.org/#faq11
|
||||
|
||||
32. Can zlib work with greater than 4 GB of data?
|
||||
|
||||
Yes. inflate() and deflate() will process any amount of data correctly.
|
||||
Each call of inflate() or deflate() is limited to input and output chunks
|
||||
of the maximum value that can be stored in the compiler's "unsigned int"
|
||||
type, but there is no limit to the number of chunks. Note however that the
|
||||
strm.total_in and strm_total_out counters may be limited to 4 GB. These
|
||||
counters are provided as a convenience and are not used internally by
|
||||
inflate() or deflate(). The application can easily set up its own counters
|
||||
updated after each call of inflate() or deflate() to count beyond 4 GB.
|
||||
compress() and uncompress() may be limited to 4 GB, since they operate in a
|
||||
single call. gzseek() and gztell() may be limited to 4 GB depending on how
|
||||
zlib is compiled. See the zlibCompileFlags() function in zlib.h.
|
||||
|
||||
The word "may" appears several times above since there is a 4 GB limit only
|
||||
if the compiler's "long" type is 32 bits. If the compiler's "long" type is
|
||||
64 bits, then the limit is 16 exabytes.
|
||||
|
||||
33. Does zlib have any security vulnerabilities?
|
||||
|
||||
The only one that we are aware of is potentially in gzprintf(). If zlib is
|
||||
compiled to use sprintf() or vsprintf(), then there is no protection
|
||||
against a buffer overflow of an 8K string space (or other value as set by
|
||||
gzbuffer()), other than the caller of gzprintf() assuring that the output
|
||||
will not exceed 8K. On the other hand, if zlib is compiled to use
|
||||
snprintf() or vsnprintf(), which should normally be the case, then there is
|
||||
no vulnerability. The ./configure script will display warnings if an
|
||||
insecure variation of sprintf() will be used by gzprintf(). Also the
|
||||
zlibCompileFlags() function will return information on what variant of
|
||||
sprintf() is used by gzprintf().
|
||||
|
||||
If you don't have snprintf() or vsnprintf() and would like one, you can
|
||||
find a portable implementation here:
|
||||
|
||||
http://www.ijs.si/software/snprintf/
|
||||
|
||||
Note that you should be using the most recent version of zlib. Versions
|
||||
1.1.3 and before were subject to a double-free vulnerability, and versions
|
||||
1.2.1 and 1.2.2 were subject to an access exception when decompressing
|
||||
invalid compressed data.
|
||||
|
||||
34. Is there a Java version of zlib?
|
||||
|
||||
Probably what you want is to use zlib in Java. zlib is already included
|
||||
as part of the Java SDK in the java.util.zip package. If you really want
|
||||
a version of zlib written in the Java language, look on the zlib home
|
||||
page for links: http://zlib.net/ .
|
||||
|
||||
35. I get this or that compiler or source-code scanner warning when I crank it
|
||||
up to maximally-pedantic. Can't you guys write proper code?
|
||||
|
||||
Many years ago, we gave up attempting to avoid warnings on every compiler
|
||||
in the universe. It just got to be a waste of time, and some compilers
|
||||
were downright silly as well as contradicted each other. So now, we simply
|
||||
make sure that the code always works.
|
||||
|
||||
36. Valgrind (or some similar memory access checker) says that deflate is
|
||||
performing a conditional jump that depends on an uninitialized value.
|
||||
Isn't that a bug?
|
||||
|
||||
No. That is intentional for performance reasons, and the output of deflate
|
||||
is not affected. This only started showing up recently since zlib 1.2.x
|
||||
uses malloc() by default for allocations, whereas earlier versions used
|
||||
calloc(), which zeros out the allocated memory. Even though the code was
|
||||
correct, versions 1.2.4 and later was changed to not stimulate these
|
||||
checkers.
|
||||
|
||||
37. Will zlib read the (insert any ancient or arcane format here) compressed
|
||||
data format?
|
||||
|
||||
Probably not. Look in the comp.compression FAQ for pointers to various
|
||||
formats and associated software.
|
||||
|
||||
38. How can I encrypt/decrypt zip files with zlib?
|
||||
|
||||
zlib doesn't support encryption. The original PKZIP encryption is very
|
||||
weak and can be broken with freely available programs. To get strong
|
||||
encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib
|
||||
compression. For PKZIP compatible "encryption", look at
|
||||
http://www.info-zip.org/
|
||||
|
||||
39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
|
||||
|
||||
"gzip" is the gzip format, and "deflate" is the zlib format. They should
|
||||
probably have called the second one "zlib" instead to avoid confusion with
|
||||
the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
|
||||
correctly points to the zlib specification in RFC 1950 for the "deflate"
|
||||
transfer encoding, there have been reports of servers and browsers that
|
||||
incorrectly produce or expect raw deflate data per the deflate
|
||||
specification in RFC 1951, most notably Microsoft. So even though the
|
||||
"deflate" transfer encoding using the zlib format would be the more
|
||||
efficient approach (and in fact exactly what the zlib format was designed
|
||||
for), using the "gzip" transfer encoding is probably more reliable due to
|
||||
an unfortunate choice of name on the part of the HTTP 1.1 authors.
|
||||
|
||||
Bottom line: use the gzip format for HTTP 1.1 encoding.
|
||||
|
||||
40. Does zlib support the new "Deflate64" format introduced by PKWare?
|
||||
|
||||
No. PKWare has apparently decided to keep that format proprietary, since
|
||||
they have not documented it as they have previous compression formats. In
|
||||
any case, the compression improvements are so modest compared to other more
|
||||
modern approaches, that it's not worth the effort to implement.
|
||||
|
||||
41. I'm having a problem with the zip functions in zlib, can you help?
|
||||
|
||||
There are no zip functions in zlib. You are probably using minizip by
|
||||
Giles Vollant, which is found in the contrib directory of zlib. It is not
|
||||
part of zlib. In fact none of the stuff in contrib is part of zlib. The
|
||||
files in there are not supported by the zlib authors. You need to contact
|
||||
the authors of the respective contribution for help.
|
||||
|
||||
42. The match.asm code in contrib is under the GNU General Public License.
|
||||
Since it's part of zlib, doesn't that mean that all of zlib falls under the
|
||||
GNU GPL?
|
||||
|
||||
No. The files in contrib are not part of zlib. They were contributed by
|
||||
other authors and are provided as a convenience to the user within the zlib
|
||||
distribution. Each item in contrib has its own license.
|
||||
|
||||
43. Is zlib subject to export controls? What is its ECCN?
|
||||
|
||||
zlib is not subject to export controls, and so is classified as EAR99.
|
||||
|
||||
44. Can you please sign these lengthy legal documents and fax them back to us
|
||||
so that we can use your software in our product?
|
||||
|
||||
No. Go away. Shoo.
|
68
third_party/zlib/INDEX
vendored
68
third_party/zlib/INDEX
vendored
@ -1,68 +0,0 @@
|
||||
CMakeLists.txt cmake build file
|
||||
ChangeLog history of changes
|
||||
FAQ Frequently Asked Questions about zlib
|
||||
INDEX this file
|
||||
Makefile dummy Makefile that tells you to ./configure
|
||||
Makefile.in template for Unix Makefile
|
||||
README guess what
|
||||
configure configure script for Unix
|
||||
make_vms.com makefile for VMS
|
||||
test/example.c zlib usages examples for build testing
|
||||
test/minigzip.c minimal gzip-like functionality for build testing
|
||||
test/infcover.c inf*.c code coverage for build coverage testing
|
||||
treebuild.xml XML description of source file dependencies
|
||||
zconf.h.cmakein zconf.h template for cmake
|
||||
zconf.h.in zconf.h template for configure
|
||||
zlib.3 Man page for zlib
|
||||
zlib.3.pdf Man page in PDF format
|
||||
zlib.map Linux symbol information
|
||||
zlib.pc.in Template for pkg-config descriptor
|
||||
zlib.pc.cmakein zlib.pc template for cmake
|
||||
zlib2ansi perl script to convert source files for C++ compilation
|
||||
|
||||
amiga/ makefiles for Amiga SAS C
|
||||
as400/ makefiles for AS/400
|
||||
doc/ documentation for formats and algorithms
|
||||
msdos/ makefiles for MSDOS
|
||||
nintendods/ makefile for Nintendo DS
|
||||
old/ makefiles for various architectures and zlib documentation
|
||||
files that have not yet been updated for zlib 1.2.x
|
||||
qnx/ makefiles for QNX
|
||||
watcom/ makefiles for OpenWatcom
|
||||
win32/ makefiles for Windows
|
||||
|
||||
zlib public header files (required for library use):
|
||||
zconf.h
|
||||
zlib.h
|
||||
|
||||
private source files used to build the zlib library:
|
||||
adler32.c
|
||||
compress.c
|
||||
crc32.c
|
||||
crc32.h
|
||||
deflate.c
|
||||
deflate.h
|
||||
gzclose.c
|
||||
gzguts.h
|
||||
gzlib.c
|
||||
gzread.c
|
||||
gzwrite.c
|
||||
infback.c
|
||||
inffast.c
|
||||
inffast.h
|
||||
inffixed.h
|
||||
inflate.c
|
||||
inflate.h
|
||||
inftrees.c
|
||||
inftrees.h
|
||||
trees.c
|
||||
trees.h
|
||||
uncompr.c
|
||||
zutil.c
|
||||
zutil.h
|
||||
|
||||
source files for sample programs
|
||||
See examples/README.examples
|
||||
|
||||
unsupported contributions by third parties
|
||||
See contrib/README.contrib
|
5
third_party/zlib/Makefile
vendored
5
third_party/zlib/Makefile
vendored
@ -1,5 +0,0 @@
|
||||
all:
|
||||
-@echo "Please use ./configure first. Thank you."
|
||||
|
||||
distclean:
|
||||
make -f Makefile.in distclean
|
410
third_party/zlib/Makefile.in
vendored
410
third_party/zlib/Makefile.in
vendored
@ -1,410 +0,0 @@
|
||||
# Makefile for zlib
|
||||
# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler
|
||||
# For conditions of distribution and use, see copyright notice in zlib.h
|
||||
|
||||
# To compile and test, type:
|
||||
# ./configure; make test
|
||||
# Normally configure builds both a static and a shared library.
|
||||
# If you want to build just a static library, use: ./configure --static
|
||||
|
||||
# To use the asm code, type:
|
||||
# cp contrib/asm?86/match.S ./match.S
|
||||
# make LOC=-DASMV OBJA=match.o
|
||||
|
||||
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
|
||||
# make install
|
||||
# To install in $HOME instead of /usr/local, use:
|
||||
# make install prefix=$HOME
|
||||
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-O
|
||||
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
|
||||
#CFLAGS=-g -DZLIB_DEBUG
|
||||
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
||||
# -Wstrict-prototypes -Wmissing-prototypes
|
||||
|
||||
SFLAGS=-O
|
||||
LDFLAGS=
|
||||
TEST_LDFLAGS=-L. libz.a
|
||||
LDSHARED=$(CC)
|
||||
CPP=$(CC) -E
|
||||
|
||||
STATICLIB=libz.a
|
||||
SHAREDLIB=libz.so
|
||||
SHAREDLIBV=libz.so.1.2.11
|
||||
SHAREDLIBM=libz.so.1
|
||||
LIBS=$(STATICLIB) $(SHAREDLIBV)
|
||||
|
||||
AR=ar
|
||||
ARFLAGS=rc
|
||||
RANLIB=ranlib
|
||||
LDCONFIG=ldconfig
|
||||
LDSHAREDLIBC=-lc
|
||||
TAR=tar
|
||||
SHELL=/bin/sh
|
||||
EXE=
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = ${prefix}
|
||||
libdir = ${exec_prefix}/lib
|
||||
sharedlibdir = ${libdir}
|
||||
includedir = ${prefix}/include
|
||||
mandir = ${prefix}/share/man
|
||||
man3dir = ${mandir}/man3
|
||||
pkgconfigdir = ${libdir}/pkgconfig
|
||||
SRCDIR=
|
||||
ZINC=
|
||||
ZINCOUT=-I.
|
||||
|
||||
OBJZ = adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o
|
||||
OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o
|
||||
OBJC = $(OBJZ) $(OBJG)
|
||||
|
||||
PIC_OBJZ = adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo
|
||||
PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo
|
||||
PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG)
|
||||
|
||||
# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo
|
||||
OBJA =
|
||||
PIC_OBJA =
|
||||
|
||||
OBJS = $(OBJC) $(OBJA)
|
||||
|
||||
PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA)
|
||||
|
||||
all: static shared
|
||||
|
||||
static: example$(EXE) minigzip$(EXE)
|
||||
|
||||
shared: examplesh$(EXE) minigzipsh$(EXE)
|
||||
|
||||
all64: example64$(EXE) minigzip64$(EXE)
|
||||
|
||||
check: test
|
||||
|
||||
test: all teststatic testshared
|
||||
|
||||
teststatic: static
|
||||
@TMPST=tmpst_$$; \
|
||||
if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \
|
||||
echo ' *** zlib test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib test FAILED ***'; false; \
|
||||
fi; \
|
||||
rm -f $$TMPST
|
||||
|
||||
testshared: shared
|
||||
@LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
|
||||
LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \
|
||||
DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \
|
||||
SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \
|
||||
TMPSH=tmpsh_$$; \
|
||||
if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \
|
||||
echo ' *** zlib shared test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib shared test FAILED ***'; false; \
|
||||
fi; \
|
||||
rm -f $$TMPSH
|
||||
|
||||
test64: all64
|
||||
@TMP64=tmp64_$$; \
|
||||
if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \
|
||||
echo ' *** zlib 64-bit test OK ***'; \
|
||||
else \
|
||||
echo ' *** zlib 64-bit test FAILED ***'; false; \
|
||||
fi; \
|
||||
rm -f $$TMP64
|
||||
|
||||
infcover.o: $(SRCDIR)test/infcover.c $(SRCDIR)zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/infcover.c
|
||||
|
||||
infcover: infcover.o libz.a
|
||||
$(CC) $(CFLAGS) -o $@ infcover.o libz.a
|
||||
|
||||
cover: infcover
|
||||
rm -f *.gcda
|
||||
./infcover
|
||||
gcov inf*.c
|
||||
|
||||
libz.a: $(OBJS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS)
|
||||
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
|
||||
|
||||
match.o: match.S
|
||||
$(CPP) match.S > _match.s
|
||||
$(CC) -c _match.s
|
||||
mv _match.o match.o
|
||||
rm -f _match.s
|
||||
|
||||
match.lo: match.S
|
||||
$(CPP) match.S > _match.s
|
||||
$(CC) -c -fPIC _match.s
|
||||
mv _match.o match.lo
|
||||
rm -f _match.s
|
||||
|
||||
example.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/example.c
|
||||
|
||||
minigzip.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/minigzip.c
|
||||
|
||||
example64.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/example.c
|
||||
|
||||
minigzip64.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h
|
||||
$(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/minigzip.c
|
||||
|
||||
|
||||
adler32.o: $(SRCDIR)adler32.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)adler32.c
|
||||
|
||||
crc32.o: $(SRCDIR)crc32.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)crc32.c
|
||||
|
||||
deflate.o: $(SRCDIR)deflate.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)deflate.c
|
||||
|
||||
infback.o: $(SRCDIR)infback.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)infback.c
|
||||
|
||||
inffast.o: $(SRCDIR)inffast.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inffast.c
|
||||
|
||||
inflate.o: $(SRCDIR)inflate.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inflate.c
|
||||
|
||||
inftrees.o: $(SRCDIR)inftrees.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inftrees.c
|
||||
|
||||
trees.o: $(SRCDIR)trees.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)trees.c
|
||||
|
||||
zutil.o: $(SRCDIR)zutil.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)zutil.c
|
||||
|
||||
compress.o: $(SRCDIR)compress.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)compress.c
|
||||
|
||||
uncompr.o: $(SRCDIR)uncompr.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)uncompr.c
|
||||
|
||||
gzclose.o: $(SRCDIR)gzclose.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzclose.c
|
||||
|
||||
gzlib.o: $(SRCDIR)gzlib.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzlib.c
|
||||
|
||||
gzread.o: $(SRCDIR)gzread.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzread.c
|
||||
|
||||
gzwrite.o: $(SRCDIR)gzwrite.c
|
||||
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzwrite.c
|
||||
|
||||
|
||||
adler32.lo: $(SRCDIR)adler32.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/adler32.o $(SRCDIR)adler32.c
|
||||
-@mv objs/adler32.o $@
|
||||
|
||||
crc32.lo: $(SRCDIR)crc32.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32.o $(SRCDIR)crc32.c
|
||||
-@mv objs/crc32.o $@
|
||||
|
||||
deflate.lo: $(SRCDIR)deflate.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/deflate.o $(SRCDIR)deflate.c
|
||||
-@mv objs/deflate.o $@
|
||||
|
||||
infback.lo: $(SRCDIR)infback.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/infback.o $(SRCDIR)infback.c
|
||||
-@mv objs/infback.o $@
|
||||
|
||||
inffast.lo: $(SRCDIR)inffast.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inffast.o $(SRCDIR)inffast.c
|
||||
-@mv objs/inffast.o $@
|
||||
|
||||
inflate.lo: $(SRCDIR)inflate.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inflate.o $(SRCDIR)inflate.c
|
||||
-@mv objs/inflate.o $@
|
||||
|
||||
inftrees.lo: $(SRCDIR)inftrees.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inftrees.o $(SRCDIR)inftrees.c
|
||||
-@mv objs/inftrees.o $@
|
||||
|
||||
trees.lo: $(SRCDIR)trees.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/trees.o $(SRCDIR)trees.c
|
||||
-@mv objs/trees.o $@
|
||||
|
||||
zutil.lo: $(SRCDIR)zutil.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/zutil.o $(SRCDIR)zutil.c
|
||||
-@mv objs/zutil.o $@
|
||||
|
||||
compress.lo: $(SRCDIR)compress.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/compress.o $(SRCDIR)compress.c
|
||||
-@mv objs/compress.o $@
|
||||
|
||||
uncompr.lo: $(SRCDIR)uncompr.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/uncompr.o $(SRCDIR)uncompr.c
|
||||
-@mv objs/uncompr.o $@
|
||||
|
||||
gzclose.lo: $(SRCDIR)gzclose.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzclose.o $(SRCDIR)gzclose.c
|
||||
-@mv objs/gzclose.o $@
|
||||
|
||||
gzlib.lo: $(SRCDIR)gzlib.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzlib.o $(SRCDIR)gzlib.c
|
||||
-@mv objs/gzlib.o $@
|
||||
|
||||
gzread.lo: $(SRCDIR)gzread.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzread.o $(SRCDIR)gzread.c
|
||||
-@mv objs/gzread.o $@
|
||||
|
||||
gzwrite.lo: $(SRCDIR)gzwrite.c
|
||||
-@mkdir objs 2>/dev/null || test -d objs
|
||||
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzwrite.o $(SRCDIR)gzwrite.c
|
||||
-@mv objs/gzwrite.o $@
|
||||
|
||||
|
||||
placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a
|
||||
$(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS)
|
||||
rm -f $(SHAREDLIB) $(SHAREDLIBM)
|
||||
ln -s $@ $(SHAREDLIB)
|
||||
ln -s $@ $(SHAREDLIBM)
|
||||
-@rmdir objs
|
||||
|
||||
example$(EXE): example.o $(STATICLIB)
|
||||
$(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS)
|
||||
|
||||
minigzip$(EXE): minigzip.o $(STATICLIB)
|
||||
$(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS)
|
||||
|
||||
examplesh$(EXE): example.o $(SHAREDLIBV)
|
||||
$(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV)
|
||||
|
||||
minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
|
||||
$(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV)
|
||||
|
||||
example64$(EXE): example64.o $(STATICLIB)
|
||||
$(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS)
|
||||
|
||||
minigzip64$(EXE): minigzip64.o $(STATICLIB)
|
||||
$(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS)
|
||||
|
||||
install-libs: $(LIBS)
|
||||
-@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi
|
||||
-@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi
|
||||
-@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi
|
||||
-@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi
|
||||
-@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi
|
||||
rm -f $(DESTDIR)$(libdir)/$(STATICLIB)
|
||||
cp $(STATICLIB) $(DESTDIR)$(libdir)
|
||||
chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB)
|
||||
-@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1
|
||||
-@if test -n "$(SHAREDLIBV)"; then \
|
||||
rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \
|
||||
cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \
|
||||
echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \
|
||||
chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \
|
||||
echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \
|
||||
rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \
|
||||
ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \
|
||||
ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \
|
||||
($(LDCONFIG) || true) >/dev/null 2>&1; \
|
||||
fi
|
||||
rm -f $(DESTDIR)$(man3dir)/zlib.3
|
||||
cp $(SRCDIR)zlib.3 $(DESTDIR)$(man3dir)
|
||||
chmod 644 $(DESTDIR)$(man3dir)/zlib.3
|
||||
rm -f $(DESTDIR)$(pkgconfigdir)/zlib.pc
|
||||
cp zlib.pc $(DESTDIR)$(pkgconfigdir)
|
||||
chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc
|
||||
# The ranlib in install is needed on NeXTSTEP which checks file times
|
||||
# ldconfig is for Linux
|
||||
|
||||
install: install-libs
|
||||
-@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi
|
||||
rm -f $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h
|
||||
cp $(SRCDIR)zlib.h zconf.h $(DESTDIR)$(includedir)
|
||||
chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h
|
||||
|
||||
uninstall:
|
||||
cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h
|
||||
cd $(DESTDIR)$(libdir) && rm -f libz.a; \
|
||||
if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \
|
||||
rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
|
||||
fi
|
||||
cd $(DESTDIR)$(man3dir) && rm -f zlib.3
|
||||
cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc
|
||||
|
||||
docs: zlib.3.pdf
|
||||
|
||||
zlib.3.pdf: $(SRCDIR)zlib.3
|
||||
groff -mandoc -f H -T ps $(SRCDIR)zlib.3 | ps2pdf - $@
|
||||
|
||||
zconf.h.cmakein: $(SRCDIR)zconf.h.in
|
||||
-@ TEMPFILE=zconfh_$$; \
|
||||
echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\
|
||||
sed -f $$TEMPFILE $(SRCDIR)zconf.h.in > $@ &&\
|
||||
touch -r $(SRCDIR)zconf.h.in $@ &&\
|
||||
rm $$TEMPFILE
|
||||
|
||||
zconf: $(SRCDIR)zconf.h.in
|
||||
cp -p $(SRCDIR)zconf.h.in zconf.h
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
rm -f *.o *.lo *~ \
|
||||
example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \
|
||||
example64$(EXE) minigzip64$(EXE) \
|
||||
infcover \
|
||||
libz.* foo.gz so_locations \
|
||||
_match.s maketree contrib/infback9/*.o
|
||||
rm -rf objs
|
||||
rm -f *.gcda *.gcno *.gcov
|
||||
rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov
|
||||
|
||||
maintainer-clean: distclean
|
||||
distclean: clean zconf zconf.h.cmakein docs
|
||||
rm -f Makefile zlib.pc configure.log
|
||||
-@rm -f .DS_Store
|
||||
@if [ -f Makefile.in ]; then \
|
||||
printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \
|
||||
printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \
|
||||
touch -r $(SRCDIR)Makefile.in Makefile ; fi
|
||||
@if [ ! -f zconf.h.in ]; then rm -f zconf.h zconf.h.cmakein ; fi
|
||||
@if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf ; fi
|
||||
|
||||
tags:
|
||||
etags $(SRCDIR)*.[ch]
|
||||
|
||||
adler32.o zutil.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
|
||||
gzclose.o gzlib.o gzread.o gzwrite.o: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h
|
||||
compress.o example.o minigzip.o uncompr.o: $(SRCDIR)zlib.h zconf.h
|
||||
crc32.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h
|
||||
deflate.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
|
||||
infback.o inflate.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h
|
||||
inffast.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h
|
||||
inftrees.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h
|
||||
trees.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h
|
||||
|
||||
adler32.lo zutil.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
|
||||
gzclose.lo gzlib.lo gzread.lo gzwrite.lo: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h
|
||||
compress.lo example.lo minigzip.lo uncompr.lo: $(SRCDIR)zlib.h zconf.h
|
||||
crc32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h
|
||||
deflate.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
|
||||
infback.lo inflate.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h
|
||||
inffast.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h
|
||||
inftrees.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h
|
||||
trees.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h
|
186
third_party/zlib/adler32.c
vendored
186
third_party/zlib/adler32.c
vendored
@ -1,186 +0,0 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
|
||||
|
||||
#define BASE 65521U /* 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_z(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
z_size_t 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);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
return adler32_z(adler, buf, len);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
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 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)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);
|
||||
}
|
69
third_party/zlib/amiga/Makefile.pup
vendored
69
third_party/zlib/amiga/Makefile.pup
vendored
@ -1,69 +0,0 @@
|
||||
# Amiga powerUP (TM) Makefile
|
||||
# makefile for libpng and SAS C V6.58/7.00 PPC compiler
|
||||
# Copyright (C) 1998 by Andreas R. Kleinert
|
||||
|
||||
LIBNAME = libzip.a
|
||||
|
||||
CC = scppc
|
||||
CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \
|
||||
OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER
|
||||
AR = ppc-amigaos-ar cr
|
||||
RANLIB = ppc-amigaos-ranlib
|
||||
LD = ppc-amigaos-ld -r
|
||||
LDFLAGS = -o
|
||||
LDLIBS = LIB:scppc.a LIB:end.o
|
||||
RM = delete quiet
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
|
||||
uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: example minigzip
|
||||
|
||||
check: test
|
||||
test: all
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
$(LIBNAME): $(OBJS)
|
||||
$(AR) $@ $(OBJS)
|
||||
-$(RANLIB) $@
|
||||
|
||||
example: example.o $(LIBNAME)
|
||||
$(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
|
||||
|
||||
minigzip: minigzip.o $(LIBNAME)
|
||||
$(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS)
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
$(RM) *.o example minigzip $(LIBNAME) foo.gz
|
||||
|
||||
zip:
|
||||
zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \
|
||||
descrip.mms *.[ch]
|
||||
|
||||
tgz:
|
||||
cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \
|
||||
zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch]
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzclose.o: zlib.h zconf.h gzguts.h
|
||||
gzlib.o: zlib.h zconf.h gzguts.h
|
||||
gzread.o: zlib.h zconf.h gzguts.h
|
||||
gzwrite.o: zlib.h zconf.h gzguts.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
68
third_party/zlib/amiga/Makefile.sas
vendored
68
third_party/zlib/amiga/Makefile.sas
vendored
@ -1,68 +0,0 @@
|
||||
# SMakefile for zlib
|
||||
# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly
|
||||
# Osma Ahvenlampi <Osma.Ahvenlampi@hut.fi>
|
||||
# Amiga, SAS/C 6.56 & Smake
|
||||
|
||||
CC=sc
|
||||
CFLAGS=OPT
|
||||
#CFLAGS=OPT CPU=68030
|
||||
#CFLAGS=DEBUG=LINE
|
||||
LDFLAGS=LIB z.lib
|
||||
|
||||
SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \
|
||||
NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \
|
||||
DEF=POSTINC
|
||||
|
||||
OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \
|
||||
uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
|
||||
|
||||
TEST_OBJS = example.o minigzip.o
|
||||
|
||||
all: SCOPTIONS example minigzip
|
||||
|
||||
check: test
|
||||
test: all
|
||||
example
|
||||
echo hello world | minigzip | minigzip -d
|
||||
|
||||
install: z.lib
|
||||
copy clone zlib.h zconf.h INCLUDE:
|
||||
copy clone z.lib LIB:
|
||||
|
||||
z.lib: $(OBJS)
|
||||
oml z.lib r $(OBJS)
|
||||
|
||||
example: example.o z.lib
|
||||
$(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS)
|
||||
|
||||
minigzip: minigzip.o z.lib
|
||||
$(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS)
|
||||
|
||||
mostlyclean: clean
|
||||
clean:
|
||||
-delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS
|
||||
|
||||
SCOPTIONS: Makefile.sas
|
||||
copy to $@ <from <
|
||||
$(SCOPTIONS)
|
||||
<
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
adler32.o: zlib.h zconf.h
|
||||
compress.o: zlib.h zconf.h
|
||||
crc32.o: crc32.h zlib.h zconf.h
|
||||
deflate.o: deflate.h zutil.h zlib.h zconf.h
|
||||
example.o: zlib.h zconf.h
|
||||
gzclose.o: zlib.h zconf.h gzguts.h
|
||||
gzlib.o: zlib.h zconf.h gzguts.h
|
||||
gzread.o: zlib.h zconf.h gzguts.h
|
||||
gzwrite.o: zlib.h zconf.h gzguts.h
|
||||
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
|
||||
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
|
||||
minigzip.o: zlib.h zconf.h
|
||||
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
|
||||
uncompr.o: zlib.h zconf.h
|
||||
zutil.o: zutil.h zlib.h zconf.h
|
86
third_party/zlib/compress.c
vendored
86
third_party/zlib/compress.c
vendored
@ -1,86 +0,0 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
|
||||
* 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;
|
||||
const uInt max = (uInt)-1;
|
||||
uLong left;
|
||||
|
||||
left = *destLen;
|
||||
*destLen = 0;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = 0;
|
||||
stream.next_in = (z_const Bytef *)source;
|
||||
stream.avail_in = 0;
|
||||
|
||||
do {
|
||||
if (stream.avail_out == 0) {
|
||||
stream.avail_out = left > (uLong)max ? max : (uInt)left;
|
||||
left -= stream.avail_out;
|
||||
}
|
||||
if (stream.avail_in == 0) {
|
||||
stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
|
||||
sourceLen -= stream.avail_in;
|
||||
}
|
||||
err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
|
||||
} while (err == Z_OK);
|
||||
|
||||
*destLen = stream.total_out;
|
||||
deflateEnd(&stream);
|
||||
return err == Z_STREAM_END ? Z_OK : 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;
|
||||
}
|
921
third_party/zlib/configure
vendored
921
third_party/zlib/configure
vendored
@ -1,921 +0,0 @@
|
||||
#!/bin/sh
|
||||
# configure script for zlib.
|
||||
#
|
||||
# Normally configure builds both a static and a shared library.
|
||||
# If you want to build just a static library, use: ./configure --static
|
||||
#
|
||||
# To impose specific compiler or flags or install directory, use for example:
|
||||
# prefix=$HOME CC=cc CFLAGS="-O4" ./configure
|
||||
# or for csh/tcsh users:
|
||||
# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure)
|
||||
|
||||
# Incorrect settings of CC or CFLAGS may prevent creating a shared library.
|
||||
# If you have problems, try without defining CC and CFLAGS before reporting
|
||||
# an error.
|
||||
|
||||
# start off configure.log
|
||||
echo -------------------- >> configure.log
|
||||
echo $0 $* >> configure.log
|
||||
date >> configure.log
|
||||
|
||||
# get source directory
|
||||
SRCDIR=`dirname $0`
|
||||
if test $SRCDIR = "."; then
|
||||
ZINC=""
|
||||
ZINCOUT="-I."
|
||||
SRCDIR=""
|
||||
else
|
||||
ZINC='-include zconf.h'
|
||||
ZINCOUT='-I. -I$(SRCDIR)'
|
||||
SRCDIR="$SRCDIR/"
|
||||
fi
|
||||
|
||||
# set command prefix for cross-compilation
|
||||
if [ -n "${CHOST}" ]; then
|
||||
uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`"
|
||||
CROSS_PREFIX="${CHOST}-"
|
||||
fi
|
||||
|
||||
# destination name for static library
|
||||
STATICLIB=libz.a
|
||||
|
||||
# extract zlib version numbers from zlib.h
|
||||
VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h`
|
||||
VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}zlib.h`
|
||||
VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h`
|
||||
VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h`
|
||||
|
||||
# establish commands for library building
|
||||
if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then
|
||||
AR=${AR-"${CROSS_PREFIX}ar"}
|
||||
test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
|
||||
else
|
||||
AR=${AR-"ar"}
|
||||
test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log
|
||||
fi
|
||||
ARFLAGS=${ARFLAGS-"rc"}
|
||||
if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then
|
||||
RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"}
|
||||
test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} | tee -a configure.log
|
||||
else
|
||||
RANLIB=${RANLIB-"ranlib"}
|
||||
fi
|
||||
if "${CROSS_PREFIX}nm" --version >/dev/null 2>/dev/null || test $? -lt 126; then
|
||||
NM=${NM-"${CROSS_PREFIX}nm"}
|
||||
test -n "${CROSS_PREFIX}" && echo Using ${NM} | tee -a configure.log
|
||||
else
|
||||
NM=${NM-"nm"}
|
||||
fi
|
||||
|
||||
# set defaults before processing command line options
|
||||
LDCONFIG=${LDCONFIG-"ldconfig"}
|
||||
LDSHAREDLIBC="${LDSHAREDLIBC--lc}"
|
||||
ARCHS=
|
||||
prefix=${prefix-/usr/local}
|
||||
exec_prefix=${exec_prefix-'${prefix}'}
|
||||
libdir=${libdir-'${exec_prefix}/lib'}
|
||||
sharedlibdir=${sharedlibdir-'${libdir}'}
|
||||
includedir=${includedir-'${prefix}/include'}
|
||||
mandir=${mandir-'${prefix}/share/man'}
|
||||
shared_ext='.so'
|
||||
shared=1
|
||||
solo=0
|
||||
cover=0
|
||||
zprefix=0
|
||||
zconst=0
|
||||
build64=0
|
||||
gcc=0
|
||||
warn=0
|
||||
debug=0
|
||||
old_cc="$CC"
|
||||
old_cflags="$CFLAGS"
|
||||
OBJC='$(OBJZ) $(OBJG)'
|
||||
PIC_OBJC='$(PIC_OBJZ) $(PIC_OBJG)'
|
||||
|
||||
# leave this script, optionally in a bad way
|
||||
leave()
|
||||
{
|
||||
if test "$*" != "0"; then
|
||||
echo "** $0 aborting." | tee -a configure.log
|
||||
fi
|
||||
rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version
|
||||
echo -------------------- >> configure.log
|
||||
echo >> configure.log
|
||||
echo >> configure.log
|
||||
exit $1
|
||||
}
|
||||
|
||||
# process command line options
|
||||
while test $# -ge 1
|
||||
do
|
||||
case "$1" in
|
||||
-h* | --help)
|
||||
echo 'usage:' | tee -a configure.log
|
||||
echo ' configure [--const] [--zprefix] [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log
|
||||
echo ' [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log
|
||||
echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log
|
||||
exit 0 ;;
|
||||
-p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;;
|
||||
-e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;;
|
||||
-l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;;
|
||||
--sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;;
|
||||
-i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;;
|
||||
-u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;;
|
||||
-p* | --prefix) prefix="$2"; shift; shift ;;
|
||||
-e* | --eprefix) exec_prefix="$2"; shift; shift ;;
|
||||
-l* | --libdir) libdir="$2"; shift; shift ;;
|
||||
-i* | --includedir) includedir="$2"; shift; shift ;;
|
||||
-s* | --shared | --enable-shared) shared=1; shift ;;
|
||||
-t | --static) shared=0; shift ;;
|
||||
--solo) solo=1; shift ;;
|
||||
--cover) cover=1; shift ;;
|
||||
-z* | --zprefix) zprefix=1; shift ;;
|
||||
-6* | --64) build64=1; shift ;;
|
||||
-a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;;
|
||||
--sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;;
|
||||
--localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;;
|
||||
-c* | --const) zconst=1; shift ;;
|
||||
-w* | --warn) warn=1; shift ;;
|
||||
-d* | --debug) debug=1; shift ;;
|
||||
*)
|
||||
echo "unknown option: $1" | tee -a configure.log
|
||||
echo "$0 --help for help" | tee -a configure.log
|
||||
leave 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
# temporary file name
|
||||
test=ztest$$
|
||||
|
||||
# put arguments in log, also put test file in log if used in arguments
|
||||
show()
|
||||
{
|
||||
case "$*" in
|
||||
*$test.c*)
|
||||
echo === $test.c === >> configure.log
|
||||
cat $test.c >> configure.log
|
||||
echo === >> configure.log;;
|
||||
esac
|
||||
echo $* >> configure.log
|
||||
}
|
||||
|
||||
# check for gcc vs. cc and set compile and link flags based on the system identified by uname
|
||||
cat > $test.c <<EOF
|
||||
extern int getchar();
|
||||
int hello() {return getchar();}
|
||||
EOF
|
||||
|
||||
test -z "$CC" && echo Checking for ${CROSS_PREFIX}gcc... | tee -a configure.log
|
||||
cc=${CC-${CROSS_PREFIX}gcc}
|
||||
cflags=${CFLAGS-"-O3"}
|
||||
# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure
|
||||
case "$cc" in
|
||||
*gcc*) gcc=1 ;;
|
||||
*clang*) gcc=1 ;;
|
||||
esac
|
||||
case `$cc -v 2>&1` in
|
||||
*gcc*) gcc=1 ;;
|
||||
*clang*) gcc=1 ;;
|
||||
esac
|
||||
|
||||
show $cc -c $test.c
|
||||
if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then
|
||||
echo ... using gcc >> configure.log
|
||||
CC="$cc"
|
||||
CFLAGS="${CFLAGS--O3}"
|
||||
SFLAGS="${CFLAGS--O3} -fPIC"
|
||||
if test "$ARCHS"; then
|
||||
CFLAGS="${CFLAGS} ${ARCHS}"
|
||||
LDFLAGS="${LDFLAGS} ${ARCHS}"
|
||||
fi
|
||||
if test $build64 -eq 1; then
|
||||
CFLAGS="${CFLAGS} -m64"
|
||||
SFLAGS="${SFLAGS} -m64"
|
||||
fi
|
||||
if test "$warn" -eq 1; then
|
||||
if test "$zconst" -eq 1; then
|
||||
CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST"
|
||||
else
|
||||
CFLAGS="${CFLAGS} -Wall -Wextra -pedantic"
|
||||
fi
|
||||
fi
|
||||
if test $debug -eq 1; then
|
||||
CFLAGS="${CFLAGS} -DZLIB_DEBUG"
|
||||
SFLAGS="${SFLAGS} -DZLIB_DEBUG"
|
||||
fi
|
||||
if test -z "$uname"; then
|
||||
uname=`(uname -s || echo unknown) 2>/dev/null`
|
||||
fi
|
||||
case "$uname" in
|
||||
Linux* | linux* | GNU | GNU/* | solaris*)
|
||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} ;;
|
||||
*BSD | *bsd* | DragonFly)
|
||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"}
|
||||
LDCONFIG="ldconfig -m" ;;
|
||||
CYGWIN* | Cygwin* | cygwin* | OS/2*)
|
||||
EXE='.exe' ;;
|
||||
MINGW* | mingw*)
|
||||
# temporary bypass
|
||||
rm -f $test.[co] $test $test$shared_ext
|
||||
echo "Please use win32/Makefile.gcc instead." | tee -a configure.log
|
||||
leave 1
|
||||
LDSHARED=${LDSHARED-"$cc -shared"}
|
||||
LDSHAREDLIBC=""
|
||||
EXE='.exe' ;;
|
||||
QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
|
||||
# (alain.bonnefoy@icbt.com)
|
||||
LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;;
|
||||
HP-UX*)
|
||||
LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
|
||||
case `(uname -m || echo unknown) 2>/dev/null` in
|
||||
ia64)
|
||||
shared_ext='.so'
|
||||
SHAREDLIB='libz.so' ;;
|
||||
*)
|
||||
shared_ext='.sl'
|
||||
SHAREDLIB='libz.sl' ;;
|
||||
esac ;;
|
||||
Darwin* | darwin*)
|
||||
shared_ext='.dylib'
|
||||
SHAREDLIB=libz$shared_ext
|
||||
SHAREDLIBV=libz.$VER$shared_ext
|
||||
SHAREDLIBM=libz.$VER1$shared_ext
|
||||
LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"}
|
||||
if libtool -V 2>&1 | grep Apple > /dev/null; then
|
||||
AR="libtool"
|
||||
else
|
||||
AR="/usr/bin/libtool"
|
||||
fi
|
||||
ARFLAGS="-o" ;;
|
||||
*) LDSHARED=${LDSHARED-"$cc -shared"} ;;
|
||||
esac
|
||||
else
|
||||
# find system name and corresponding cc options
|
||||
CC=${CC-cc}
|
||||
gcc=0
|
||||
echo ... using $CC >> configure.log
|
||||
if test -z "$uname"; then
|
||||
uname=`(uname -sr || echo unknown) 2>/dev/null`
|
||||
fi
|
||||
case "$uname" in
|
||||
HP-UX*) SFLAGS=${CFLAGS-"-O +z"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"}
|
||||
LDSHARED=${LDSHARED-"ld -b"}
|
||||
case `(uname -m || echo unknown) 2>/dev/null` in
|
||||
ia64)
|
||||
shared_ext='.so'
|
||||
SHAREDLIB='libz.so' ;;
|
||||
*)
|
||||
shared_ext='.sl'
|
||||
SHAREDLIB='libz.sl' ;;
|
||||
esac ;;
|
||||
IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."}
|
||||
CFLAGS=${CFLAGS-"-ansi -O2"}
|
||||
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;;
|
||||
OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"}
|
||||
CFLAGS=${CFLAGS-"-O -std1"}
|
||||
LDFLAGS="${LDFLAGS} -Wl,-rpath,."
|
||||
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;;
|
||||
OSF1*) SFLAGS=${CFLAGS-"-O -std1"}
|
||||
CFLAGS=${CFLAGS-"-O -std1"}
|
||||
LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;;
|
||||
QNX*) SFLAGS=${CFLAGS-"-4 -O"}
|
||||
CFLAGS=${CFLAGS-"-4 -O"}
|
||||
LDSHARED=${LDSHARED-"cc"}
|
||||
RANLIB=${RANLIB-"true"}
|
||||
AR="cc"
|
||||
ARFLAGS="-A" ;;
|
||||
SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "}
|
||||
CFLAGS=${CFLAGS-"-O3"}
|
||||
LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;;
|
||||
SunOS\ 5* | solaris*)
|
||||
LDSHARED=${LDSHARED-"cc -G -h libz$shared_ext.$VER1"}
|
||||
SFLAGS=${CFLAGS-"-fast -KPIC"}
|
||||
CFLAGS=${CFLAGS-"-fast"}
|
||||
if test $build64 -eq 1; then
|
||||
# old versions of SunPRO/Workshop/Studio don't support -m64,
|
||||
# but newer ones do. Check for it.
|
||||
flag64=`$CC -flags | egrep -- '^-m64'`
|
||||
if test x"$flag64" != x"" ; then
|
||||
CFLAGS="${CFLAGS} -m64"
|
||||
SFLAGS="${SFLAGS} -m64"
|
||||
else
|
||||
case `(uname -m || echo unknown) 2>/dev/null` in
|
||||
i86*)
|
||||
SFLAGS="$SFLAGS -xarch=amd64"
|
||||
CFLAGS="$CFLAGS -xarch=amd64" ;;
|
||||
*)
|
||||
SFLAGS="$SFLAGS -xarch=v9"
|
||||
CFLAGS="$CFLAGS -xarch=v9" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
if test -n "$ZINC"; then
|
||||
ZINC='-I- -I. -I$(SRCDIR)'
|
||||
fi
|
||||
;;
|
||||
SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
|
||||
CFLAGS=${CFLAGS-"-O2"}
|
||||
LDSHARED=${LDSHARED-"ld"} ;;
|
||||
SunStudio\ 9*) SFLAGS=${CFLAGS-"-fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"}
|
||||
CFLAGS=${CFLAGS-"-fast -xtarget=ultra3 -xarch=v9b"}
|
||||
LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;;
|
||||
UNIX_System_V\ 4.2.0)
|
||||
SFLAGS=${CFLAGS-"-KPIC -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"} ;;
|
||||
UNIX_SV\ 4.2MP)
|
||||
SFLAGS=${CFLAGS-"-Kconform_pic -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"} ;;
|
||||
OpenUNIX\ 5)
|
||||
SFLAGS=${CFLAGS-"-KPIC -O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -G"} ;;
|
||||
AIX*) # Courtesy of dbakker@arrayasolutions.com
|
||||
SFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
|
||||
CFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
|
||||
LDSHARED=${LDSHARED-"xlc -G"} ;;
|
||||
# send working options for other systems to zlib@gzip.org
|
||||
*) SFLAGS=${CFLAGS-"-O"}
|
||||
CFLAGS=${CFLAGS-"-O"}
|
||||
LDSHARED=${LDSHARED-"cc -shared"} ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# destination names for shared library if not defined above
|
||||
SHAREDLIB=${SHAREDLIB-"libz$shared_ext"}
|
||||
SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"}
|
||||
SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"}
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# define functions for testing compiler and library characteristics and logging the results
|
||||
|
||||
cat > $test.c <<EOF
|
||||
#error error
|
||||
EOF
|
||||
if ($CC -c $CFLAGS $test.c) 2>/dev/null; then
|
||||
try()
|
||||
{
|
||||
show $*
|
||||
test "`( $* ) 2>&1 | tee -a configure.log`" = ""
|
||||
}
|
||||
echo - using any output from compiler to indicate an error >> configure.log
|
||||
else
|
||||
try()
|
||||
{
|
||||
show $*
|
||||
( $* ) >> configure.log 2>&1
|
||||
ret=$?
|
||||
if test $ret -ne 0; then
|
||||
echo "(exit code "$ret")" >> configure.log
|
||||
fi
|
||||
return $ret
|
||||
}
|
||||
fi
|
||||
|
||||
tryboth()
|
||||
{
|
||||
show $*
|
||||
got=`( $* ) 2>&1`
|
||||
ret=$?
|
||||
printf %s "$got" >> configure.log
|
||||
if test $ret -ne 0; then
|
||||
return $ret
|
||||
fi
|
||||
test "$got" = ""
|
||||
}
|
||||
|
||||
cat > $test.c << EOF
|
||||
int foo() { return 0; }
|
||||
EOF
|
||||
echo "Checking for obsessive-compulsive compiler options..." >> configure.log
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
:
|
||||
else
|
||||
echo "Compiler error reporting is too harsh for $0 (perhaps remove -Werror)." | tee -a configure.log
|
||||
leave 1
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# see if shared library build supported
|
||||
cat > $test.c <<EOF
|
||||
extern int getchar();
|
||||
int hello() {return getchar();}
|
||||
EOF
|
||||
if test $shared -eq 1; then
|
||||
echo Checking for shared library support... | tee -a configure.log
|
||||
# we must test in two steps (cc then ld), required at least on SunOS 4.x
|
||||
if try $CC -w -c $SFLAGS $test.c &&
|
||||
try $LDSHARED $SFLAGS -o $test$shared_ext $test.o; then
|
||||
echo Building shared library $SHAREDLIBV with $CC. | tee -a configure.log
|
||||
elif test -z "$old_cc" -a -z "$old_cflags"; then
|
||||
echo No shared library support. | tee -a configure.log
|
||||
shared=0;
|
||||
else
|
||||
echo 'No shared library support; try without defining CC and CFLAGS' | tee -a configure.log
|
||||
shared=0;
|
||||
fi
|
||||
fi
|
||||
if test $shared -eq 0; then
|
||||
LDSHARED="$CC"
|
||||
ALL="static"
|
||||
TEST="all teststatic"
|
||||
SHAREDLIB=""
|
||||
SHAREDLIBV=""
|
||||
SHAREDLIBM=""
|
||||
echo Building static library $STATICLIB version $VER with $CC. | tee -a configure.log
|
||||
else
|
||||
ALL="static shared"
|
||||
TEST="all teststatic testshared"
|
||||
fi
|
||||
|
||||
# check for underscores in external names for use by assembler code
|
||||
CPP=${CPP-"$CC -E"}
|
||||
case $CFLAGS in
|
||||
*ASMV*)
|
||||
echo >> configure.log
|
||||
show "$NM $test.o | grep _hello"
|
||||
if test "`$NM $test.o | grep _hello | tee -a configure.log`" = ""; then
|
||||
CPP="$CPP -DNO_UNDERLINE"
|
||||
echo Checking for underline in external names... No. | tee -a configure.log
|
||||
else
|
||||
echo Checking for underline in external names... Yes. | tee -a configure.log
|
||||
fi ;;
|
||||
esac
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# check for size_t
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
size_t dummy = 0;
|
||||
EOF
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for size_t... Yes." | tee -a configure.log
|
||||
need_sizet=0
|
||||
else
|
||||
echo "Checking for size_t... No." | tee -a configure.log
|
||||
need_sizet=1
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# find the size_t integer type, if needed
|
||||
if test $need_sizet -eq 1; then
|
||||
cat > $test.c <<EOF
|
||||
long long dummy = 0;
|
||||
EOF
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for long long... Yes." | tee -a configure.log
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int main(void) {
|
||||
if (sizeof(void *) <= sizeof(int)) puts("int");
|
||||
else if (sizeof(void *) <= sizeof(long)) puts("long");
|
||||
else puts("z_longlong");
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
else
|
||||
echo "Checking for long long... No." | tee -a configure.log
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int main(void) {
|
||||
if (sizeof(void *) <= sizeof(int)) puts("int");
|
||||
else puts("long");
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
if try $CC $CFLAGS -o $test $test.c; then
|
||||
sizet=`./$test`
|
||||
echo "Checking for a pointer-size integer type..." $sizet"." | tee -a configure.log
|
||||
else
|
||||
echo "Failed to find a pointer-size integer type." | tee -a configure.log
|
||||
leave 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $need_sizet -eq 1; then
|
||||
CFLAGS="${CFLAGS} -DNO_SIZE_T=${sizet}"
|
||||
SFLAGS="${SFLAGS} -DNO_SIZE_T=${sizet}"
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# check for large file support, and if none, check for fseeko()
|
||||
cat > $test.c <<EOF
|
||||
#include <sys/types.h>
|
||||
off64_t dummy = 0;
|
||||
EOF
|
||||
if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then
|
||||
CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1"
|
||||
SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1"
|
||||
ALL="${ALL} all64"
|
||||
TEST="${TEST} test64"
|
||||
echo "Checking for off64_t... Yes." | tee -a configure.log
|
||||
echo "Checking for fseeko... Yes." | tee -a configure.log
|
||||
else
|
||||
echo "Checking for off64_t... No." | tee -a configure.log
|
||||
echo >> configure.log
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int main(void) {
|
||||
fseeko(NULL, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if try $CC $CFLAGS -o $test $test.c; then
|
||||
echo "Checking for fseeko... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="${CFLAGS} -DNO_FSEEKO"
|
||||
SFLAGS="${SFLAGS} -DNO_FSEEKO"
|
||||
echo "Checking for fseeko... No." | tee -a configure.log
|
||||
fi
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# check for strerror() for use by gz* functions
|
||||
cat > $test.c <<EOF
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
int main() { return strlen(strerror(errno)); }
|
||||
EOF
|
||||
if try $CC $CFLAGS -o $test $test.c; then
|
||||
echo "Checking for strerror... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="${CFLAGS} -DNO_STRERROR"
|
||||
SFLAGS="${SFLAGS} -DNO_STRERROR"
|
||||
echo "Checking for strerror... No." | tee -a configure.log
|
||||
fi
|
||||
|
||||
# copy clean zconf.h for subsequent edits
|
||||
cp -p ${SRCDIR}zconf.h.in zconf.h
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# check for unistd.h and save result in zconf.h
|
||||
cat > $test.c <<EOF
|
||||
#include <unistd.h>
|
||||
int main() { return 0; }
|
||||
EOF
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
sed < zconf.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf.temp.h
|
||||
mv zconf.temp.h zconf.h
|
||||
echo "Checking for unistd.h... Yes." | tee -a configure.log
|
||||
else
|
||||
echo "Checking for unistd.h... No." | tee -a configure.log
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# check for stdarg.h and save result in zconf.h
|
||||
cat > $test.c <<EOF
|
||||
#include <stdarg.h>
|
||||
int main() { return 0; }
|
||||
EOF
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
sed < zconf.h "/^#ifdef HAVE_STDARG_H.* may be/s/def HAVE_STDARG_H\(.*\) may be/ 1\1 was/" > zconf.temp.h
|
||||
mv zconf.temp.h zconf.h
|
||||
echo "Checking for stdarg.h... Yes." | tee -a configure.log
|
||||
else
|
||||
echo "Checking for stdarg.h... No." | tee -a configure.log
|
||||
fi
|
||||
|
||||
# if the z_ prefix was requested, save that in zconf.h
|
||||
if test $zprefix -eq 1; then
|
||||
sed < zconf.h "/#ifdef Z_PREFIX.* may be/s/def Z_PREFIX\(.*\) may be/ 1\1 was/" > zconf.temp.h
|
||||
mv zconf.temp.h zconf.h
|
||||
echo >> configure.log
|
||||
echo "Using z_ prefix on all symbols." | tee -a configure.log
|
||||
fi
|
||||
|
||||
# if --solo compilation was requested, save that in zconf.h and remove gz stuff from object lists
|
||||
if test $solo -eq 1; then
|
||||
sed '/#define ZCONF_H/a\
|
||||
#define Z_SOLO
|
||||
|
||||
' < zconf.h > zconf.temp.h
|
||||
mv zconf.temp.h zconf.h
|
||||
OBJC='$(OBJZ)'
|
||||
PIC_OBJC='$(PIC_OBJZ)'
|
||||
fi
|
||||
|
||||
# if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X
|
||||
if test $cover -eq 1; then
|
||||
CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage"
|
||||
if test -n "$GCC_CLASSIC"; then
|
||||
CC=$GCC_CLASSIC
|
||||
fi
|
||||
fi
|
||||
|
||||
echo >> configure.log
|
||||
|
||||
# conduct a series of tests to resolve eight possible cases of using "vs" or "s" printf functions
|
||||
# (using stdarg or not), with or without "n" (proving size of buffer), and with or without a
|
||||
# return value. The most secure result is vsnprintf() with a return value. snprintf() with a
|
||||
# return value is secure as well, but then gzprintf() will be limited to 20 arguments.
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "zconf.h"
|
||||
int main()
|
||||
{
|
||||
#ifndef STDC
|
||||
choke me
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat > $test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
int mytest(const char *fmt, ...)
|
||||
{
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
return 0;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
if try $CC $CFLAGS -o $test $test.c; then
|
||||
echo "Checking for vsnprintf() in stdio.h... Yes." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
int mytest(const char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for return value of vsnprintf()... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_vsnprintf_void"
|
||||
SFLAGS="$SFLAGS -DHAS_vsnprintf_void"
|
||||
echo "Checking for return value of vsnprintf()... No." | tee -a configure.log
|
||||
echo " WARNING: apparently vsnprintf() does not return a value. zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible string-format security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
fi
|
||||
else
|
||||
CFLAGS="$CFLAGS -DNO_vsnprintf"
|
||||
SFLAGS="$SFLAGS -DNO_vsnprintf"
|
||||
echo "Checking for vsnprintf() in stdio.h... No." | tee -a configure.log
|
||||
echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
int mytest(const char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
char buf[20];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
n = vsprintf(buf, fmt, ap);
|
||||
va_end(ap);
|
||||
return n;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest("Hello%d\n", 1));
|
||||
}
|
||||
EOF
|
||||
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for return value of vsprintf()... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_vsprintf_void"
|
||||
SFLAGS="$SFLAGS -DHAS_vsprintf_void"
|
||||
echo "Checking for return value of vsprintf()... No." | tee -a configure.log
|
||||
echo " WARNING: apparently vsprintf() does not return a value. zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible string-format security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "%s", "foo");
|
||||
return 0;
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if try $CC $CFLAGS -o $test $test.c; then
|
||||
echo "Checking for snprintf() in stdio.h... Yes." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
return snprintf(buf, sizeof(buf), "%s", "foo");
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for return value of snprintf()... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_snprintf_void"
|
||||
SFLAGS="$SFLAGS -DHAS_snprintf_void"
|
||||
echo "Checking for return value of snprintf()... No." | tee -a configure.log
|
||||
echo " WARNING: apparently snprintf() does not return a value. zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible string-format security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
fi
|
||||
else
|
||||
CFLAGS="$CFLAGS -DNO_snprintf"
|
||||
SFLAGS="$SFLAGS -DNO_snprintf"
|
||||
echo "Checking for snprintf() in stdio.h... No." | tee -a configure.log
|
||||
echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
|
||||
echo >> configure.log
|
||||
cat >$test.c <<EOF
|
||||
#include <stdio.h>
|
||||
int mytest()
|
||||
{
|
||||
char buf[20];
|
||||
return sprintf(buf, "%s", "foo");
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return (mytest());
|
||||
}
|
||||
EOF
|
||||
|
||||
if try $CC -c $CFLAGS $test.c; then
|
||||
echo "Checking for return value of sprintf()... Yes." | tee -a configure.log
|
||||
else
|
||||
CFLAGS="$CFLAGS -DHAS_sprintf_void"
|
||||
SFLAGS="$SFLAGS -DHAS_sprintf_void"
|
||||
echo "Checking for return value of sprintf()... No." | tee -a configure.log
|
||||
echo " WARNING: apparently sprintf() does not return a value. zlib" | tee -a configure.log
|
||||
echo " can build but will be open to possible string-format security" | tee -a configure.log
|
||||
echo " vulnerabilities." | tee -a configure.log
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# see if we can hide zlib internal symbols that are linked between separate source files
|
||||
if test "$gcc" -eq 1; then
|
||||
echo >> configure.log
|
||||
cat > $test.c <<EOF
|
||||
#define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
int ZLIB_INTERNAL foo;
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if tryboth $CC -c $CFLAGS $test.c; then
|
||||
CFLAGS="$CFLAGS -DHAVE_HIDDEN"
|
||||
SFLAGS="$SFLAGS -DHAVE_HIDDEN"
|
||||
echo "Checking for attribute(visibility) support... Yes." | tee -a configure.log
|
||||
else
|
||||
echo "Checking for attribute(visibility) support... No." | tee -a configure.log
|
||||
fi
|
||||
fi
|
||||
|
||||
# show the results in the log
|
||||
echo >> configure.log
|
||||
echo ALL = $ALL >> configure.log
|
||||
echo AR = $AR >> configure.log
|
||||
echo ARFLAGS = $ARFLAGS >> configure.log
|
||||
echo CC = $CC >> configure.log
|
||||
echo CFLAGS = $CFLAGS >> configure.log
|
||||
echo CPP = $CPP >> configure.log
|
||||
echo EXE = $EXE >> configure.log
|
||||
echo LDCONFIG = $LDCONFIG >> configure.log
|
||||
echo LDFLAGS = $LDFLAGS >> configure.log
|
||||
echo LDSHARED = $LDSHARED >> configure.log
|
||||
echo LDSHAREDLIBC = $LDSHAREDLIBC >> configure.log
|
||||
echo OBJC = $OBJC >> configure.log
|
||||
echo PIC_OBJC = $PIC_OBJC >> configure.log
|
||||
echo RANLIB = $RANLIB >> configure.log
|
||||
echo SFLAGS = $SFLAGS >> configure.log
|
||||
echo SHAREDLIB = $SHAREDLIB >> configure.log
|
||||
echo SHAREDLIBM = $SHAREDLIBM >> configure.log
|
||||
echo SHAREDLIBV = $SHAREDLIBV >> configure.log
|
||||
echo STATICLIB = $STATICLIB >> configure.log
|
||||
echo TEST = $TEST >> configure.log
|
||||
echo VER = $VER >> configure.log
|
||||
echo Z_U4 = $Z_U4 >> configure.log
|
||||
echo SRCDIR = $SRCDIR >> configure.log
|
||||
echo exec_prefix = $exec_prefix >> configure.log
|
||||
echo includedir = $includedir >> configure.log
|
||||
echo libdir = $libdir >> configure.log
|
||||
echo mandir = $mandir >> configure.log
|
||||
echo prefix = $prefix >> configure.log
|
||||
echo sharedlibdir = $sharedlibdir >> configure.log
|
||||
echo uname = $uname >> configure.log
|
||||
|
||||
# udpate Makefile with the configure results
|
||||
sed < ${SRCDIR}Makefile.in "
|
||||
/^CC *=/s#=.*#=$CC#
|
||||
/^CFLAGS *=/s#=.*#=$CFLAGS#
|
||||
/^SFLAGS *=/s#=.*#=$SFLAGS#
|
||||
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
|
||||
/^LDSHARED *=/s#=.*#=$LDSHARED#
|
||||
/^CPP *=/s#=.*#=$CPP#
|
||||
/^STATICLIB *=/s#=.*#=$STATICLIB#
|
||||
/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
|
||||
/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
|
||||
/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
|
||||
/^AR *=/s#=.*#=$AR#
|
||||
/^ARFLAGS *=/s#=.*#=$ARFLAGS#
|
||||
/^RANLIB *=/s#=.*#=$RANLIB#
|
||||
/^LDCONFIG *=/s#=.*#=$LDCONFIG#
|
||||
/^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC#
|
||||
/^EXE *=/s#=.*#=$EXE#
|
||||
/^SRCDIR *=/s#=.*#=$SRCDIR#
|
||||
/^ZINC *=/s#=.*#=$ZINC#
|
||||
/^ZINCOUT *=/s#=.*#=$ZINCOUT#
|
||||
/^prefix *=/s#=.*#=$prefix#
|
||||
/^exec_prefix *=/s#=.*#=$exec_prefix#
|
||||
/^libdir *=/s#=.*#=$libdir#
|
||||
/^sharedlibdir *=/s#=.*#=$sharedlibdir#
|
||||
/^includedir *=/s#=.*#=$includedir#
|
||||
/^mandir *=/s#=.*#=$mandir#
|
||||
/^OBJC *=/s#=.*#= $OBJC#
|
||||
/^PIC_OBJC *=/s#=.*#= $PIC_OBJC#
|
||||
/^all: */s#:.*#: $ALL#
|
||||
/^test: */s#:.*#: $TEST#
|
||||
" > Makefile
|
||||
|
||||
# create zlib.pc with the configure results
|
||||
sed < ${SRCDIR}zlib.pc.in "
|
||||
/^CC *=/s#=.*#=$CC#
|
||||
/^CFLAGS *=/s#=.*#=$CFLAGS#
|
||||
/^CPP *=/s#=.*#=$CPP#
|
||||
/^LDSHARED *=/s#=.*#=$LDSHARED#
|
||||
/^STATICLIB *=/s#=.*#=$STATICLIB#
|
||||
/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
|
||||
/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
|
||||
/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
|
||||
/^AR *=/s#=.*#=$AR#
|
||||
/^ARFLAGS *=/s#=.*#=$ARFLAGS#
|
||||
/^RANLIB *=/s#=.*#=$RANLIB#
|
||||
/^EXE *=/s#=.*#=$EXE#
|
||||
/^prefix *=/s#=.*#=$prefix#
|
||||
/^exec_prefix *=/s#=.*#=$exec_prefix#
|
||||
/^libdir *=/s#=.*#=$libdir#
|
||||
/^sharedlibdir *=/s#=.*#=$sharedlibdir#
|
||||
/^includedir *=/s#=.*#=$includedir#
|
||||
/^mandir *=/s#=.*#=$mandir#
|
||||
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
|
||||
" | sed -e "
|
||||
s/\@VERSION\@/$VER/g;
|
||||
" > zlib.pc
|
||||
|
||||
# done
|
||||
leave 0
|
78
third_party/zlib/contrib/README.contrib
vendored
78
third_party/zlib/contrib/README.contrib
vendored
@ -1,78 +0,0 @@
|
||||
All files under this contrib directory are UNSUPPORTED. There were
|
||||
provided by users of zlib and were not tested by the authors of zlib.
|
||||
Use at your own risk. Please contact the authors of the contributions
|
||||
for help about these, not the zlib authors. Thanks.
|
||||
|
||||
|
||||
ada/ by Dmitriy Anisimkov <anisimkov@yahoo.com>
|
||||
Support for Ada
|
||||
See http://zlib-ada.sourceforge.net/
|
||||
|
||||
amd64/ by Mikhail Teterin <mi@ALDAN.algebra.com>
|
||||
asm code for AMD64
|
||||
See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393
|
||||
|
||||
asm686/ by Brian Raiter <breadbox@muppetlabs.com>
|
||||
asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax
|
||||
See http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
blast/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Decompressor for output of PKWare Data Compression Library (DCL)
|
||||
|
||||
delphi/ by Cosmin Truta <cosmint@cs.ubbcluj.ro>
|
||||
Support for Delphi and C++ Builder
|
||||
|
||||
dotzlib/ by Henrik Ravn <henrik@ravn.com>
|
||||
Support for Microsoft .Net and Visual C++ .Net
|
||||
|
||||
gcc_gvmat64/by Gilles Vollant <info@winimage.com>
|
||||
GCC Version of x86 64-bit (AMD64 and Intel EM64t) code for x64
|
||||
assembler to replace longest_match() and inflate_fast()
|
||||
|
||||
infback9/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Unsupported diffs to infback to decode the deflate64 format
|
||||
|
||||
inflate86/ by Chris Anderson <christop@charm.net>
|
||||
Tuned x86 gcc asm code to replace inflate_fast()
|
||||
|
||||
iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
A C++ I/O streams interface to the zlib gz* functions
|
||||
|
||||
iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
|
||||
Another C++ I/O streams interface
|
||||
|
||||
iostream3/ by Ludwig Schwardt <schwardt@sun.ac.za>
|
||||
and Kevin Ruland <kevin@rodin.wustl.edu>
|
||||
Yet another C++ I/O streams interface
|
||||
|
||||
masmx64/ by Gilles Vollant <info@winimage.com>
|
||||
x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to
|
||||
replace longest_match() and inflate_fast(), also masm x86
|
||||
64-bits translation of Chris Anderson inflate_fast()
|
||||
|
||||
masmx86/ by Gilles Vollant <info@winimage.com>
|
||||
x86 asm code to replace longest_match() and inflate_fast(),
|
||||
for Visual C++ and MASM (32 bits).
|
||||
Based on Brian Raiter (asm686) and Chris Anderson (inflate86)
|
||||
|
||||
minizip/ by Gilles Vollant <info@winimage.com>
|
||||
Mini zip and unzip based on zlib
|
||||
Includes Zip64 support by Mathias Svensson <mathias@result42.com>
|
||||
See http://www.winimage.com/zLibDll/minizip.html
|
||||
|
||||
pascal/ by Bob Dellaca <bobdl@xtra.co.nz> et al.
|
||||
Support for Pascal
|
||||
|
||||
puff/ by Mark Adler <madler@alumni.caltech.edu>
|
||||
Small, low memory usage inflate. Also serves to provide an
|
||||
unambiguous description of the deflate format.
|
||||
|
||||
testzlib/ by Gilles Vollant <info@winimage.com>
|
||||
Example of the use of zlib
|
||||
|
||||
untgz/ by Pedro A. Aranda Gutierrez <paag@tid.es>
|
||||
A very simple tar.gz file extractor using zlib
|
||||
|
||||
vstudio/ by Gilles Vollant <info@winimage.com>
|
||||
Building a minizip-enhanced zlib with Microsoft Visual Studio
|
||||
Includes vc11 from kreuzerkrieg and vc12 from davispuh
|
106
third_party/zlib/contrib/ada/buffer_demo.adb
vendored
106
third_party/zlib/contrib/ada/buffer_demo.adb
vendored
@ -1,106 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2004 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
--
|
||||
-- $Id: buffer_demo.adb,v 1.3 2004/09/06 06:55:35 vagul Exp $
|
||||
|
||||
-- This demo program provided by Dr Steve Sangwine <sjs@essex.ac.uk>
|
||||
--
|
||||
-- Demonstration of a problem with Zlib-Ada (already fixed) when a buffer
|
||||
-- of exactly the correct size is used for decompressed data, and the last
|
||||
-- few bytes passed in to Zlib are checksum bytes.
|
||||
|
||||
-- This program compresses a string of text, and then decompresses the
|
||||
-- compressed text into a buffer of the same size as the original text.
|
||||
|
||||
with Ada.Streams; use Ada.Streams;
|
||||
with Ada.Text_IO;
|
||||
|
||||
with ZLib; use ZLib;
|
||||
|
||||
procedure Buffer_Demo is
|
||||
EOL : Character renames ASCII.LF;
|
||||
Text : constant String
|
||||
:= "Four score and seven years ago our fathers brought forth," & EOL &
|
||||
"upon this continent, a new nation, conceived in liberty," & EOL &
|
||||
"and dedicated to the proposition that `all men are created equal'.";
|
||||
|
||||
Source : Stream_Element_Array (1 .. Text'Length);
|
||||
for Source'Address use Text'Address;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put (Text);
|
||||
Ada.Text_IO.New_Line;
|
||||
Ada.Text_IO.Put_Line
|
||||
("Uncompressed size : " & Positive'Image (Text'Length) & " bytes");
|
||||
|
||||
declare
|
||||
Compressed_Data : Stream_Element_Array (1 .. Text'Length);
|
||||
L : Stream_Element_Offset;
|
||||
begin
|
||||
Compress : declare
|
||||
Compressor : Filter_Type;
|
||||
I : Stream_Element_Offset;
|
||||
begin
|
||||
Deflate_Init (Compressor);
|
||||
|
||||
-- Compress the whole of T at once.
|
||||
|
||||
Translate (Compressor, Source, I, Compressed_Data, L, Finish);
|
||||
pragma Assert (I = Source'Last);
|
||||
|
||||
Close (Compressor);
|
||||
|
||||
Ada.Text_IO.Put_Line
|
||||
("Compressed size : "
|
||||
& Stream_Element_Offset'Image (L) & " bytes");
|
||||
end Compress;
|
||||
|
||||
-- Now we decompress the data, passing short blocks of data to Zlib
|
||||
-- (because this demonstrates the problem - the last block passed will
|
||||
-- contain checksum information and there will be no output, only a
|
||||
-- check inside Zlib that the checksum is correct).
|
||||
|
||||
Decompress : declare
|
||||
Decompressor : Filter_Type;
|
||||
|
||||
Uncompressed_Data : Stream_Element_Array (1 .. Text'Length);
|
||||
|
||||
Block_Size : constant := 4;
|
||||
-- This makes sure that the last block contains
|
||||
-- only Adler checksum data.
|
||||
|
||||
P : Stream_Element_Offset := Compressed_Data'First - 1;
|
||||
O : Stream_Element_Offset;
|
||||
begin
|
||||
Inflate_Init (Decompressor);
|
||||
|
||||
loop
|
||||
Translate
|
||||
(Decompressor,
|
||||
Compressed_Data
|
||||
(P + 1 .. Stream_Element_Offset'Min (P + Block_Size, L)),
|
||||
P,
|
||||
Uncompressed_Data
|
||||
(Total_Out (Decompressor) + 1 .. Uncompressed_Data'Last),
|
||||
O,
|
||||
No_Flush);
|
||||
|
||||
Ada.Text_IO.Put_Line
|
||||
("Total in : " & Count'Image (Total_In (Decompressor)) &
|
||||
", out : " & Count'Image (Total_Out (Decompressor)));
|
||||
|
||||
exit when P = L;
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.New_Line;
|
||||
Ada.Text_IO.Put_Line
|
||||
("Decompressed text matches original text : "
|
||||
& Boolean'Image (Uncompressed_Data = Source));
|
||||
end Decompress;
|
||||
end;
|
||||
end Buffer_Demo;
|
156
third_party/zlib/contrib/ada/mtest.adb
vendored
156
third_party/zlib/contrib/ada/mtest.adb
vendored
@ -1,156 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
-- Continuous test for ZLib multithreading. If the test would fail
|
||||
-- we should provide thread safe allocation routines for the Z_Stream.
|
||||
--
|
||||
-- $Id: mtest.adb,v 1.4 2004/07/23 07:49:54 vagul Exp $
|
||||
|
||||
with ZLib;
|
||||
with Ada.Streams;
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
with Ada.Text_IO;
|
||||
with Ada.Exceptions;
|
||||
with Ada.Task_Identification;
|
||||
|
||||
procedure MTest is
|
||||
use Ada.Streams;
|
||||
use ZLib;
|
||||
|
||||
Stop : Boolean := False;
|
||||
|
||||
pragma Atomic (Stop);
|
||||
|
||||
subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is
|
||||
new Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
task type Test_Task;
|
||||
|
||||
task body Test_Task is
|
||||
Buffer : Stream_Element_Array (1 .. 100_000);
|
||||
Gen : Random_Elements.Generator;
|
||||
|
||||
Buffer_First : Stream_Element_Offset;
|
||||
Compare_First : Stream_Element_Offset;
|
||||
|
||||
Deflate : Filter_Type;
|
||||
Inflate : Filter_Type;
|
||||
|
||||
procedure Further (Item : in Stream_Element_Array);
|
||||
|
||||
procedure Read_Buffer
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
|
||||
-------------
|
||||
-- Further --
|
||||
-------------
|
||||
|
||||
procedure Further (Item : in Stream_Element_Array) is
|
||||
|
||||
procedure Compare (Item : in Stream_Element_Array);
|
||||
|
||||
-------------
|
||||
-- Compare --
|
||||
-------------
|
||||
|
||||
procedure Compare (Item : in Stream_Element_Array) is
|
||||
Next_First : Stream_Element_Offset := Compare_First + Item'Length;
|
||||
begin
|
||||
if Buffer (Compare_First .. Next_First - 1) /= Item then
|
||||
raise Program_Error;
|
||||
end if;
|
||||
|
||||
Compare_First := Next_First;
|
||||
end Compare;
|
||||
|
||||
procedure Compare_Write is new ZLib.Write (Write => Compare);
|
||||
begin
|
||||
Compare_Write (Inflate, Item, No_Flush);
|
||||
end Further;
|
||||
|
||||
-----------------
|
||||
-- Read_Buffer --
|
||||
-----------------
|
||||
|
||||
procedure Read_Buffer
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset)
|
||||
is
|
||||
Buff_Diff : Stream_Element_Offset := Buffer'Last - Buffer_First;
|
||||
Next_First : Stream_Element_Offset;
|
||||
begin
|
||||
if Item'Length <= Buff_Diff then
|
||||
Last := Item'Last;
|
||||
|
||||
Next_First := Buffer_First + Item'Length;
|
||||
|
||||
Item := Buffer (Buffer_First .. Next_First - 1);
|
||||
|
||||
Buffer_First := Next_First;
|
||||
else
|
||||
Last := Item'First + Buff_Diff;
|
||||
Item (Item'First .. Last) := Buffer (Buffer_First .. Buffer'Last);
|
||||
Buffer_First := Buffer'Last + 1;
|
||||
end if;
|
||||
end Read_Buffer;
|
||||
|
||||
procedure Translate is new Generic_Translate
|
||||
(Data_In => Read_Buffer,
|
||||
Data_Out => Further);
|
||||
|
||||
begin
|
||||
Random_Elements.Reset (Gen);
|
||||
|
||||
Buffer := (others => 20);
|
||||
|
||||
Main : loop
|
||||
for J in Buffer'Range loop
|
||||
Buffer (J) := Random_Elements.Random (Gen);
|
||||
|
||||
Deflate_Init (Deflate);
|
||||
Inflate_Init (Inflate);
|
||||
|
||||
Buffer_First := Buffer'First;
|
||||
Compare_First := Buffer'First;
|
||||
|
||||
Translate (Deflate);
|
||||
|
||||
if Compare_First /= Buffer'Last + 1 then
|
||||
raise Program_Error;
|
||||
end if;
|
||||
|
||||
Ada.Text_IO.Put_Line
|
||||
(Ada.Task_Identification.Image
|
||||
(Ada.Task_Identification.Current_Task)
|
||||
& Stream_Element_Offset'Image (J)
|
||||
& ZLib.Count'Image (Total_Out (Deflate)));
|
||||
|
||||
Close (Deflate);
|
||||
Close (Inflate);
|
||||
|
||||
exit Main when Stop;
|
||||
end loop;
|
||||
end loop Main;
|
||||
exception
|
||||
when E : others =>
|
||||
Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E));
|
||||
Stop := True;
|
||||
end Test_Task;
|
||||
|
||||
Test : array (1 .. 4) of Test_Task;
|
||||
|
||||
pragma Unreferenced (Test);
|
||||
|
||||
Dummy : Character;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Get_Immediate (Dummy);
|
||||
Stop := True;
|
||||
end MTest;
|
156
third_party/zlib/contrib/ada/read.adb
vendored
156
third_party/zlib/contrib/ada/read.adb
vendored
@ -1,156 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: read.adb,v 1.8 2004/05/31 10:53:40 vagul Exp $
|
||||
|
||||
-- Test/demo program for the generic read interface.
|
||||
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
with Ada.Streams;
|
||||
with Ada.Text_IO;
|
||||
|
||||
with ZLib;
|
||||
|
||||
procedure Read is
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
------------------------------------
|
||||
-- Test configuration parameters --
|
||||
------------------------------------
|
||||
|
||||
File_Size : Stream_Element_Offset := 100_000;
|
||||
|
||||
Continuous : constant Boolean := False;
|
||||
-- If this constant is True, the test would be repeated again and again,
|
||||
-- with increment File_Size for every iteration.
|
||||
|
||||
Header : constant ZLib.Header_Type := ZLib.Default;
|
||||
-- Do not use Header other than Default in ZLib versions 1.1.4 and older.
|
||||
|
||||
Init_Random : constant := 8;
|
||||
-- We are using the same random sequence, in case of we catch bug,
|
||||
-- so we would be able to reproduce it.
|
||||
|
||||
-- End --
|
||||
|
||||
Pack_Size : Stream_Element_Offset;
|
||||
Offset : Stream_Element_Offset;
|
||||
|
||||
Filter : ZLib.Filter_Type;
|
||||
|
||||
subtype Visible_Symbols
|
||||
is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is new
|
||||
Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
Gen : Random_Elements.Generator;
|
||||
Period : constant Stream_Element_Offset := 200;
|
||||
-- Period constant variable for random generator not to be very random.
|
||||
-- Bigger period, harder random.
|
||||
|
||||
Read_Buffer : Stream_Element_Array (1 .. 2048);
|
||||
Read_First : Stream_Element_Offset;
|
||||
Read_Last : Stream_Element_Offset;
|
||||
|
||||
procedure Reset;
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Read
|
||||
-- reading data from the File_In.
|
||||
|
||||
procedure Read is new ZLib.Read
|
||||
(Read,
|
||||
Read_Buffer,
|
||||
Rest_First => Read_First,
|
||||
Rest_Last => Read_Last);
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Last := Stream_Element_Offset'Min
|
||||
(Item'Last,
|
||||
Item'First + File_Size - Offset);
|
||||
|
||||
for J in Item'First .. Last loop
|
||||
if J < Item'First + Period then
|
||||
Item (J) := Random_Elements.Random (Gen);
|
||||
else
|
||||
Item (J) := Item (J - Period);
|
||||
end if;
|
||||
|
||||
Offset := Offset + 1;
|
||||
end loop;
|
||||
end Read;
|
||||
|
||||
-----------
|
||||
-- Reset --
|
||||
-----------
|
||||
|
||||
procedure Reset is
|
||||
begin
|
||||
Random_Elements.Reset (Gen, Init_Random);
|
||||
Pack_Size := 0;
|
||||
Offset := 1;
|
||||
Read_First := Read_Buffer'Last + 1;
|
||||
Read_Last := Read_Buffer'Last;
|
||||
end Reset;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
|
||||
|
||||
loop
|
||||
for Level in ZLib.Compression_Level'Range loop
|
||||
|
||||
Ada.Text_IO.Put ("Level ="
|
||||
& ZLib.Compression_Level'Image (Level));
|
||||
|
||||
-- Deflate using generic instantiation.
|
||||
|
||||
ZLib.Deflate_Init
|
||||
(Filter,
|
||||
Level,
|
||||
Header => Header);
|
||||
|
||||
Reset;
|
||||
|
||||
Ada.Text_IO.Put
|
||||
(Stream_Element_Offset'Image (File_Size) & " ->");
|
||||
|
||||
loop
|
||||
declare
|
||||
Buffer : Stream_Element_Array (1 .. 1024);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
Read (Filter, Buffer, Last);
|
||||
|
||||
Pack_Size := Pack_Size + Last - Buffer'First + 1;
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end;
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.Put_Line (Stream_Element_Offset'Image (Pack_Size));
|
||||
|
||||
ZLib.Close (Filter);
|
||||
end loop;
|
||||
|
||||
exit when not Continuous;
|
||||
|
||||
File_Size := File_Size + 1;
|
||||
end loop;
|
||||
end Read;
|
65
third_party/zlib/contrib/ada/readme.txt
vendored
65
third_party/zlib/contrib/ada/readme.txt
vendored
@ -1,65 +0,0 @@
|
||||
ZLib for Ada thick binding (ZLib.Ada)
|
||||
Release 1.3
|
||||
|
||||
ZLib.Ada is a thick binding interface to the popular ZLib data
|
||||
compression library, available at http://www.gzip.org/zlib/.
|
||||
It provides Ada-style access to the ZLib C library.
|
||||
|
||||
|
||||
Here are the main changes since ZLib.Ada 1.2:
|
||||
|
||||
- Attension: ZLib.Read generic routine have a initialization requirement
|
||||
for Read_Last parameter now. It is a bit incompartible with previous version,
|
||||
but extends functionality, we could use new parameters Allow_Read_Some and
|
||||
Flush now.
|
||||
|
||||
- Added Is_Open routines to ZLib and ZLib.Streams packages.
|
||||
|
||||
- Add pragma Assert to check Stream_Element is 8 bit.
|
||||
|
||||
- Fix extraction to buffer with exact known decompressed size. Error reported by
|
||||
Steve Sangwine.
|
||||
|
||||
- Fix definition of ULong (changed to unsigned_long), fix regression on 64 bits
|
||||
computers. Patch provided by Pascal Obry.
|
||||
|
||||
- Add Status_Error exception definition.
|
||||
|
||||
- Add pragma Assertion that Ada.Streams.Stream_Element size is 8 bit.
|
||||
|
||||
|
||||
How to build ZLib.Ada under GNAT
|
||||
|
||||
You should have the ZLib library already build on your computer, before
|
||||
building ZLib.Ada. Make the directory of ZLib.Ada sources current and
|
||||
issue the command:
|
||||
|
||||
gnatmake test -largs -L<directory where libz.a is> -lz
|
||||
|
||||
Or use the GNAT project file build for GNAT 3.15 or later:
|
||||
|
||||
gnatmake -Pzlib.gpr -L<directory where libz.a is>
|
||||
|
||||
|
||||
How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2
|
||||
|
||||
1. Make a project with all *.ads and *.adb files from the distribution.
|
||||
2. Build the libz.a library from the ZLib C sources.
|
||||
3. Rename libz.a to z.lib.
|
||||
4. Add the library z.lib to the project.
|
||||
5. Add the libc.lib library from the ObjectAda distribution to the project.
|
||||
6. Build the executable using test.adb as a main procedure.
|
||||
|
||||
|
||||
How to use ZLib.Ada
|
||||
|
||||
The source files test.adb and read.adb are small demo programs that show
|
||||
the main functionality of ZLib.Ada.
|
||||
|
||||
The routines from the package specifications are commented.
|
||||
|
||||
|
||||
Homepage: http://zlib-ada.sourceforge.net/
|
||||
Author: Dmitriy Anisimkov <anisimkov@yahoo.com>
|
||||
|
||||
Contributors: Pascal Obry <pascal@obry.org>, Steve Sangwine <sjs@essex.ac.uk>
|
463
third_party/zlib/contrib/ada/test.adb
vendored
463
third_party/zlib/contrib/ada/test.adb
vendored
@ -1,463 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: test.adb,v 1.17 2003/08/12 12:13:30 vagul Exp $
|
||||
|
||||
-- The program has a few aims.
|
||||
-- 1. Test ZLib.Ada95 thick binding functionality.
|
||||
-- 2. Show the example of use main functionality of the ZLib.Ada95 binding.
|
||||
-- 3. Build this program automatically compile all ZLib.Ada95 packages under
|
||||
-- GNAT Ada95 compiler.
|
||||
|
||||
with ZLib.Streams;
|
||||
with Ada.Streams.Stream_IO;
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
|
||||
with Ada.Text_IO;
|
||||
|
||||
with Ada.Calendar;
|
||||
|
||||
procedure Test is
|
||||
|
||||
use Ada.Streams;
|
||||
use Stream_IO;
|
||||
|
||||
------------------------------------
|
||||
-- Test configuration parameters --
|
||||
------------------------------------
|
||||
|
||||
File_Size : Count := 100_000;
|
||||
Continuous : constant Boolean := False;
|
||||
|
||||
Header : constant ZLib.Header_Type := ZLib.Default;
|
||||
-- ZLib.None;
|
||||
-- ZLib.Auto;
|
||||
-- ZLib.GZip;
|
||||
-- Do not use Header other then Default in ZLib versions 1.1.4
|
||||
-- and older.
|
||||
|
||||
Strategy : constant ZLib.Strategy_Type := ZLib.Default_Strategy;
|
||||
Init_Random : constant := 10;
|
||||
|
||||
-- End --
|
||||
|
||||
In_File_Name : constant String := "testzlib.in";
|
||||
-- Name of the input file
|
||||
|
||||
Z_File_Name : constant String := "testzlib.zlb";
|
||||
-- Name of the compressed file.
|
||||
|
||||
Out_File_Name : constant String := "testzlib.out";
|
||||
-- Name of the decompressed file.
|
||||
|
||||
File_In : File_Type;
|
||||
File_Out : File_Type;
|
||||
File_Back : File_Type;
|
||||
File_Z : ZLib.Streams.Stream_Type;
|
||||
|
||||
Filter : ZLib.Filter_Type;
|
||||
|
||||
Time_Stamp : Ada.Calendar.Time;
|
||||
|
||||
procedure Generate_File;
|
||||
-- Generate file of spetsified size with some random data.
|
||||
-- The random data is repeatable, for the good compression.
|
||||
|
||||
procedure Compare_Streams
|
||||
(Left, Right : in out Root_Stream_Type'Class);
|
||||
-- The procedure compearing data in 2 streams.
|
||||
-- It is for compare data before and after compression/decompression.
|
||||
|
||||
procedure Compare_Files (Left, Right : String);
|
||||
-- Compare files. Based on the Compare_Streams.
|
||||
|
||||
procedure Copy_Streams
|
||||
(Source, Target : in out Root_Stream_Type'Class;
|
||||
Buffer_Size : in Stream_Element_Offset := 1024);
|
||||
-- Copying data from one stream to another. It is for test stream
|
||||
-- interface of the library.
|
||||
|
||||
procedure Data_In
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Generic_Translate.
|
||||
-- reading data from the File_In.
|
||||
|
||||
procedure Data_Out (Item : in Stream_Element_Array);
|
||||
-- this procedure is for generic instantiation of
|
||||
-- ZLib.Generic_Translate.
|
||||
-- writing data to the File_Out.
|
||||
|
||||
procedure Stamp;
|
||||
-- Store the timestamp to the local variable.
|
||||
|
||||
procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count);
|
||||
-- Print the time statistic with the message.
|
||||
|
||||
procedure Translate is new ZLib.Generic_Translate
|
||||
(Data_In => Data_In,
|
||||
Data_Out => Data_Out);
|
||||
-- This procedure is moving data from File_In to File_Out
|
||||
-- with compression or decompression, depend on initialization of
|
||||
-- Filter parameter.
|
||||
|
||||
-------------------
|
||||
-- Compare_Files --
|
||||
-------------------
|
||||
|
||||
procedure Compare_Files (Left, Right : String) is
|
||||
Left_File, Right_File : File_Type;
|
||||
begin
|
||||
Open (Left_File, In_File, Left);
|
||||
Open (Right_File, In_File, Right);
|
||||
Compare_Streams (Stream (Left_File).all, Stream (Right_File).all);
|
||||
Close (Left_File);
|
||||
Close (Right_File);
|
||||
end Compare_Files;
|
||||
|
||||
---------------------
|
||||
-- Compare_Streams --
|
||||
---------------------
|
||||
|
||||
procedure Compare_Streams
|
||||
(Left, Right : in out Ada.Streams.Root_Stream_Type'Class)
|
||||
is
|
||||
Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#);
|
||||
Left_Last, Right_Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Read (Left, Left_Buffer, Left_Last);
|
||||
Read (Right, Right_Buffer, Right_Last);
|
||||
|
||||
if Left_Last /= Right_Last then
|
||||
Ada.Text_IO.Put_Line ("Compare error :"
|
||||
& Stream_Element_Offset'Image (Left_Last)
|
||||
& " /= "
|
||||
& Stream_Element_Offset'Image (Right_Last));
|
||||
|
||||
raise Constraint_Error;
|
||||
|
||||
elsif Left_Buffer (0 .. Left_Last)
|
||||
/= Right_Buffer (0 .. Right_Last)
|
||||
then
|
||||
Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal.");
|
||||
raise Constraint_Error;
|
||||
|
||||
end if;
|
||||
|
||||
exit when Left_Last < Left_Buffer'Last;
|
||||
end loop;
|
||||
end Compare_Streams;
|
||||
|
||||
------------------
|
||||
-- Copy_Streams --
|
||||
------------------
|
||||
|
||||
procedure Copy_Streams
|
||||
(Source, Target : in out Ada.Streams.Root_Stream_Type'Class;
|
||||
Buffer_Size : in Stream_Element_Offset := 1024)
|
||||
is
|
||||
Buffer : Stream_Element_Array (1 .. Buffer_Size);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Read (Source, Buffer, Last);
|
||||
Write (Target, Buffer (1 .. Last));
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end loop;
|
||||
end Copy_Streams;
|
||||
|
||||
-------------
|
||||
-- Data_In --
|
||||
-------------
|
||||
|
||||
procedure Data_In
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Read (File_In, Item, Last);
|
||||
end Data_In;
|
||||
|
||||
--------------
|
||||
-- Data_Out --
|
||||
--------------
|
||||
|
||||
procedure Data_Out (Item : in Stream_Element_Array) is
|
||||
begin
|
||||
Write (File_Out, Item);
|
||||
end Data_Out;
|
||||
|
||||
-------------------
|
||||
-- Generate_File --
|
||||
-------------------
|
||||
|
||||
procedure Generate_File is
|
||||
subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#;
|
||||
|
||||
package Random_Elements is
|
||||
new Ada.Numerics.Discrete_Random (Visible_Symbols);
|
||||
|
||||
Gen : Random_Elements.Generator;
|
||||
Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10;
|
||||
|
||||
Buffer_Count : constant Count := File_Size / Buffer'Length;
|
||||
-- Number of same buffers in the packet.
|
||||
|
||||
Density : constant Count := 30; -- from 0 to Buffer'Length - 2;
|
||||
|
||||
procedure Fill_Buffer (J, D : in Count);
|
||||
-- Change the part of the buffer.
|
||||
|
||||
-----------------
|
||||
-- Fill_Buffer --
|
||||
-----------------
|
||||
|
||||
procedure Fill_Buffer (J, D : in Count) is
|
||||
begin
|
||||
for K in 0 .. D loop
|
||||
Buffer
|
||||
(Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1))
|
||||
:= Random_Elements.Random (Gen);
|
||||
|
||||
end loop;
|
||||
end Fill_Buffer;
|
||||
|
||||
begin
|
||||
Random_Elements.Reset (Gen, Init_Random);
|
||||
|
||||
Create (File_In, Out_File, In_File_Name);
|
||||
|
||||
Fill_Buffer (1, Buffer'Length - 2);
|
||||
|
||||
for J in 1 .. Buffer_Count loop
|
||||
Write (File_In, Buffer);
|
||||
|
||||
Fill_Buffer (J, Density);
|
||||
end loop;
|
||||
|
||||
-- fill remain size.
|
||||
|
||||
Write
|
||||
(File_In,
|
||||
Buffer
|
||||
(1 .. Stream_Element_Offset
|
||||
(File_Size - Buffer'Length * Buffer_Count)));
|
||||
|
||||
Flush (File_In);
|
||||
Close (File_In);
|
||||
end Generate_File;
|
||||
|
||||
---------------------
|
||||
-- Print_Statistic --
|
||||
---------------------
|
||||
|
||||
procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is
|
||||
use Ada.Calendar;
|
||||
use Ada.Text_IO;
|
||||
|
||||
package Count_IO is new Integer_IO (ZLib.Count);
|
||||
|
||||
Curr_Dur : Duration := Clock - Time_Stamp;
|
||||
begin
|
||||
Put (Msg);
|
||||
|
||||
Set_Col (20);
|
||||
Ada.Text_IO.Put ("size =");
|
||||
|
||||
Count_IO.Put
|
||||
(Data_Size,
|
||||
Width => Stream_IO.Count'Image (File_Size)'Length);
|
||||
|
||||
Put_Line (" duration =" & Duration'Image (Curr_Dur));
|
||||
end Print_Statistic;
|
||||
|
||||
-----------
|
||||
-- Stamp --
|
||||
-----------
|
||||
|
||||
procedure Stamp is
|
||||
begin
|
||||
Time_Stamp := Ada.Calendar.Clock;
|
||||
end Stamp;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version);
|
||||
|
||||
loop
|
||||
Generate_File;
|
||||
|
||||
for Level in ZLib.Compression_Level'Range loop
|
||||
|
||||
Ada.Text_IO.Put_Line ("Level ="
|
||||
& ZLib.Compression_Level'Image (Level));
|
||||
|
||||
-- Test generic interface.
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Create (File_Out, Out_File, Z_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
-- Deflate using generic instantiation.
|
||||
|
||||
ZLib.Deflate_Init
|
||||
(Filter => Filter,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Translate (Filter);
|
||||
Print_Statistic ("Generic compress", ZLib.Total_Out (Filter));
|
||||
ZLib.Close (Filter);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Out);
|
||||
|
||||
Open (File_In, In_File, Z_File_Name);
|
||||
Create (File_Out, Out_File, Out_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
-- Inflate using generic instantiation.
|
||||
|
||||
ZLib.Inflate_Init (Filter, Header => Header);
|
||||
|
||||
Translate (Filter);
|
||||
Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter));
|
||||
|
||||
ZLib.Close (Filter);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Out);
|
||||
|
||||
Compare_Files (In_File_Name, Out_File_Name);
|
||||
|
||||
-- Test stream interface.
|
||||
|
||||
-- Compress to the back stream.
|
||||
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Create (File_Back, Out_File, Z_File_Name);
|
||||
|
||||
Stamp;
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.Out_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => True,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Copy_Streams
|
||||
(Source => Stream (File_In).all,
|
||||
Target => File_Z);
|
||||
|
||||
-- Flushing internal buffers to the back stream.
|
||||
|
||||
ZLib.Streams.Flush (File_Z, ZLib.Finish);
|
||||
|
||||
Print_Statistic ("Write compress",
|
||||
ZLib.Streams.Write_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
-- Compare reading from original file and from
|
||||
-- decompression stream.
|
||||
|
||||
Open (File_In, In_File, In_File_Name);
|
||||
Open (File_Back, In_File, Z_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.In_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => True,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
Compare_Streams (Stream (File_In).all, File_Z);
|
||||
|
||||
Print_Statistic ("Read decompress",
|
||||
ZLib.Streams.Read_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
-- Compress by reading from compression stream.
|
||||
|
||||
Open (File_Back, In_File, In_File_Name);
|
||||
Create (File_Out, Out_File, Z_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.In_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => False,
|
||||
Level => Level,
|
||||
Strategy => Strategy,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
Copy_Streams
|
||||
(Source => File_Z,
|
||||
Target => Stream (File_Out).all);
|
||||
|
||||
Print_Statistic ("Read compress",
|
||||
ZLib.Streams.Read_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
|
||||
Close (File_Out);
|
||||
Close (File_Back);
|
||||
|
||||
-- Decompress to decompression stream.
|
||||
|
||||
Open (File_In, In_File, Z_File_Name);
|
||||
Create (File_Back, Out_File, Out_File_Name);
|
||||
|
||||
ZLib.Streams.Create
|
||||
(Stream => File_Z,
|
||||
Mode => ZLib.Streams.Out_Stream,
|
||||
Back => ZLib.Streams.Stream_Access
|
||||
(Stream (File_Back)),
|
||||
Back_Compressed => False,
|
||||
Header => Header);
|
||||
|
||||
Stamp;
|
||||
|
||||
Copy_Streams
|
||||
(Source => Stream (File_In).all,
|
||||
Target => File_Z);
|
||||
|
||||
Print_Statistic ("Write decompress",
|
||||
ZLib.Streams.Write_Total_Out (File_Z));
|
||||
|
||||
ZLib.Streams.Close (File_Z);
|
||||
Close (File_In);
|
||||
Close (File_Back);
|
||||
|
||||
Compare_Files (In_File_Name, Out_File_Name);
|
||||
end loop;
|
||||
|
||||
Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok.");
|
||||
|
||||
exit when not Continuous;
|
||||
|
||||
File_Size := File_Size + 1;
|
||||
end loop;
|
||||
end Test;
|
225
third_party/zlib/contrib/ada/zlib-streams.adb
vendored
225
third_party/zlib/contrib/ada/zlib-streams.adb
vendored
@ -1,225 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib-streams.adb,v 1.10 2004/05/31 10:53:40 vagul Exp $
|
||||
|
||||
with Ada.Unchecked_Deallocation;
|
||||
|
||||
package body ZLib.Streams is
|
||||
|
||||
-----------
|
||||
-- Close --
|
||||
-----------
|
||||
|
||||
procedure Close (Stream : in out Stream_Type) is
|
||||
procedure Free is new Ada.Unchecked_Deallocation
|
||||
(Stream_Element_Array, Buffer_Access);
|
||||
begin
|
||||
if Stream.Mode = Out_Stream or Stream.Mode = Duplex then
|
||||
-- We should flush the data written by the writer.
|
||||
|
||||
Flush (Stream, Finish);
|
||||
|
||||
Close (Stream.Writer);
|
||||
end if;
|
||||
|
||||
if Stream.Mode = In_Stream or Stream.Mode = Duplex then
|
||||
Close (Stream.Reader);
|
||||
Free (Stream.Buffer);
|
||||
end if;
|
||||
end Close;
|
||||
|
||||
------------
|
||||
-- Create --
|
||||
------------
|
||||
|
||||
procedure Create
|
||||
(Stream : out Stream_Type;
|
||||
Mode : in Stream_Mode;
|
||||
Back : in Stream_Access;
|
||||
Back_Compressed : in Boolean;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Header : in Header_Type := Default;
|
||||
Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size)
|
||||
is
|
||||
|
||||
subtype Buffer_Subtype is Stream_Element_Array (1 .. Read_Buffer_Size);
|
||||
|
||||
procedure Init_Filter
|
||||
(Filter : in out Filter_Type;
|
||||
Compress : in Boolean);
|
||||
|
||||
-----------------
|
||||
-- Init_Filter --
|
||||
-----------------
|
||||
|
||||
procedure Init_Filter
|
||||
(Filter : in out Filter_Type;
|
||||
Compress : in Boolean) is
|
||||
begin
|
||||
if Compress then
|
||||
Deflate_Init
|
||||
(Filter, Level, Strategy, Header => Header);
|
||||
else
|
||||
Inflate_Init (Filter, Header => Header);
|
||||
end if;
|
||||
end Init_Filter;
|
||||
|
||||
begin
|
||||
Stream.Back := Back;
|
||||
Stream.Mode := Mode;
|
||||
|
||||
if Mode = Out_Stream or Mode = Duplex then
|
||||
Init_Filter (Stream.Writer, Back_Compressed);
|
||||
Stream.Buffer_Size := Write_Buffer_Size;
|
||||
else
|
||||
Stream.Buffer_Size := 0;
|
||||
end if;
|
||||
|
||||
if Mode = In_Stream or Mode = Duplex then
|
||||
Init_Filter (Stream.Reader, not Back_Compressed);
|
||||
|
||||
Stream.Buffer := new Buffer_Subtype;
|
||||
Stream.Rest_First := Stream.Buffer'Last + 1;
|
||||
Stream.Rest_Last := Stream.Buffer'Last;
|
||||
end if;
|
||||
end Create;
|
||||
|
||||
-----------
|
||||
-- Flush --
|
||||
-----------
|
||||
|
||||
procedure Flush
|
||||
(Stream : in out Stream_Type;
|
||||
Mode : in Flush_Mode := Sync_Flush)
|
||||
is
|
||||
Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
loop
|
||||
Flush (Stream.Writer, Buffer, Last, Mode);
|
||||
|
||||
Ada.Streams.Write (Stream.Back.all, Buffer (1 .. Last));
|
||||
|
||||
exit when Last < Buffer'Last;
|
||||
end loop;
|
||||
end Flush;
|
||||
|
||||
-------------
|
||||
-- Is_Open --
|
||||
-------------
|
||||
|
||||
function Is_Open (Stream : Stream_Type) return Boolean is
|
||||
begin
|
||||
return Is_Open (Stream.Reader) or else Is_Open (Stream.Writer);
|
||||
end Is_Open;
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Stream : in out Stream_Type;
|
||||
Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset)
|
||||
is
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset);
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Item : out Stream_Element_Array;
|
||||
Last : out Stream_Element_Offset) is
|
||||
begin
|
||||
Ada.Streams.Read (Stream.Back.all, Item, Last);
|
||||
end Read;
|
||||
|
||||
procedure Read is new ZLib.Read
|
||||
(Read => Read,
|
||||
Buffer => Stream.Buffer.all,
|
||||
Rest_First => Stream.Rest_First,
|
||||
Rest_Last => Stream.Rest_Last);
|
||||
|
||||
begin
|
||||
Read (Stream.Reader, Item, Last);
|
||||
end Read;
|
||||
|
||||
-------------------
|
||||
-- Read_Total_In --
|
||||
-------------------
|
||||
|
||||
function Read_Total_In (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_In (Stream.Reader);
|
||||
end Read_Total_In;
|
||||
|
||||
--------------------
|
||||
-- Read_Total_Out --
|
||||
--------------------
|
||||
|
||||
function Read_Total_Out (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_Out (Stream.Reader);
|
||||
end Read_Total_Out;
|
||||
|
||||
-----------
|
||||
-- Write --
|
||||
-----------
|
||||
|
||||
procedure Write
|
||||
(Stream : in out Stream_Type;
|
||||
Item : in Stream_Element_Array)
|
||||
is
|
||||
|
||||
procedure Write (Item : in Stream_Element_Array);
|
||||
|
||||
-----------
|
||||
-- Write --
|
||||
-----------
|
||||
|
||||
procedure Write (Item : in Stream_Element_Array) is
|
||||
begin
|
||||
Ada.Streams.Write (Stream.Back.all, Item);
|
||||
end Write;
|
||||
|
||||
procedure Write is new ZLib.Write
|
||||
(Write => Write,
|
||||
Buffer_Size => Stream.Buffer_Size);
|
||||
|
||||
begin
|
||||
Write (Stream.Writer, Item, No_Flush);
|
||||
end Write;
|
||||
|
||||
--------------------
|
||||
-- Write_Total_In --
|
||||
--------------------
|
||||
|
||||
function Write_Total_In (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_In (Stream.Writer);
|
||||
end Write_Total_In;
|
||||
|
||||
---------------------
|
||||
-- Write_Total_Out --
|
||||
---------------------
|
||||
|
||||
function Write_Total_Out (Stream : in Stream_Type) return Count is
|
||||
begin
|
||||
return Total_Out (Stream.Writer);
|
||||
end Write_Total_Out;
|
||||
|
||||
end ZLib.Streams;
|
114
third_party/zlib/contrib/ada/zlib-streams.ads
vendored
114
third_party/zlib/contrib/ada/zlib-streams.ads
vendored
@ -1,114 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib-streams.ads,v 1.12 2004/05/31 10:53:40 vagul Exp $
|
||||
|
||||
package ZLib.Streams is
|
||||
|
||||
type Stream_Mode is (In_Stream, Out_Stream, Duplex);
|
||||
|
||||
type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
|
||||
|
||||
type Stream_Type is
|
||||
new Ada.Streams.Root_Stream_Type with private;
|
||||
|
||||
procedure Read
|
||||
(Stream : in out Stream_Type;
|
||||
Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
|
||||
procedure Write
|
||||
(Stream : in out Stream_Type;
|
||||
Item : in Ada.Streams.Stream_Element_Array);
|
||||
|
||||
procedure Flush
|
||||
(Stream : in out Stream_Type;
|
||||
Mode : in Flush_Mode := Sync_Flush);
|
||||
-- Flush the written data to the back stream,
|
||||
-- all data placed to the compressor is flushing to the Back stream.
|
||||
-- Should not be used until necessary, because it is decreasing
|
||||
-- compression.
|
||||
|
||||
function Read_Total_In (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Read_Total_In);
|
||||
-- Return total number of bytes read from back stream so far.
|
||||
|
||||
function Read_Total_Out (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Read_Total_Out);
|
||||
-- Return total number of bytes read so far.
|
||||
|
||||
function Write_Total_In (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Write_Total_In);
|
||||
-- Return total number of bytes written so far.
|
||||
|
||||
function Write_Total_Out (Stream : in Stream_Type) return Count;
|
||||
pragma Inline (Write_Total_Out);
|
||||
-- Return total number of bytes written to the back stream.
|
||||
|
||||
procedure Create
|
||||
(Stream : out Stream_Type;
|
||||
Mode : in Stream_Mode;
|
||||
Back : in Stream_Access;
|
||||
Back_Compressed : in Boolean;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Header : in Header_Type := Default;
|
||||
Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size);
|
||||
-- Create the Comression/Decompression stream.
|
||||
-- If mode is In_Stream then Write operation is disabled.
|
||||
-- If mode is Out_Stream then Read operation is disabled.
|
||||
|
||||
-- If Back_Compressed is true then
|
||||
-- Data written to the Stream is compressing to the Back stream
|
||||
-- and data read from the Stream is decompressed data from the Back stream.
|
||||
|
||||
-- If Back_Compressed is false then
|
||||
-- Data written to the Stream is decompressing to the Back stream
|
||||
-- and data read from the Stream is compressed data from the Back stream.
|
||||
|
||||
-- !!! When the Need_Header is False ZLib-Ada is using undocumented
|
||||
-- ZLib 1.1.4 functionality to do not create/wait for ZLib headers.
|
||||
|
||||
function Is_Open (Stream : Stream_Type) return Boolean;
|
||||
|
||||
procedure Close (Stream : in out Stream_Type);
|
||||
|
||||
private
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
type Buffer_Access is access all Stream_Element_Array;
|
||||
|
||||
type Stream_Type
|
||||
is new Root_Stream_Type with
|
||||
record
|
||||
Mode : Stream_Mode;
|
||||
|
||||
Buffer : Buffer_Access;
|
||||
Rest_First : Stream_Element_Offset;
|
||||
Rest_Last : Stream_Element_Offset;
|
||||
-- Buffer for Read operation.
|
||||
-- We need to have this buffer in the record
|
||||
-- because not all read data from back stream
|
||||
-- could be processed during the read operation.
|
||||
|
||||
Buffer_Size : Stream_Element_Offset;
|
||||
-- Buffer size for write operation.
|
||||
-- We do not need to have this buffer
|
||||
-- in the record because all data could be
|
||||
-- processed in the write operation.
|
||||
|
||||
Back : Stream_Access;
|
||||
Reader : Filter_Type;
|
||||
Writer : Filter_Type;
|
||||
end record;
|
||||
|
||||
end ZLib.Streams;
|
141
third_party/zlib/contrib/ada/zlib-thin.adb
vendored
141
third_party/zlib/contrib/ada/zlib-thin.adb
vendored
@ -1,141 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib-thin.adb,v 1.8 2003/12/14 18:27:31 vagul Exp $
|
||||
|
||||
package body ZLib.Thin is
|
||||
|
||||
ZLIB_VERSION : constant Chars_Ptr := zlibVersion;
|
||||
|
||||
Z_Stream_Size : constant Int := Z_Stream'Size / System.Storage_Unit;
|
||||
|
||||
--------------
|
||||
-- Avail_In --
|
||||
--------------
|
||||
|
||||
function Avail_In (Strm : in Z_Stream) return UInt is
|
||||
begin
|
||||
return Strm.Avail_In;
|
||||
end Avail_In;
|
||||
|
||||
---------------
|
||||
-- Avail_Out --
|
||||
---------------
|
||||
|
||||
function Avail_Out (Strm : in Z_Stream) return UInt is
|
||||
begin
|
||||
return Strm.Avail_Out;
|
||||
end Avail_Out;
|
||||
|
||||
------------------
|
||||
-- Deflate_Init --
|
||||
------------------
|
||||
|
||||
function Deflate_Init
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
method : Int;
|
||||
windowBits : Int;
|
||||
memLevel : Int;
|
||||
strategy : Int)
|
||||
return Int is
|
||||
begin
|
||||
return deflateInit2
|
||||
(strm,
|
||||
level,
|
||||
method,
|
||||
windowBits,
|
||||
memLevel,
|
||||
strategy,
|
||||
ZLIB_VERSION,
|
||||
Z_Stream_Size);
|
||||
end Deflate_Init;
|
||||
|
||||
------------------
|
||||
-- Inflate_Init --
|
||||
------------------
|
||||
|
||||
function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int is
|
||||
begin
|
||||
return inflateInit2 (strm, windowBits, ZLIB_VERSION, Z_Stream_Size);
|
||||
end Inflate_Init;
|
||||
|
||||
------------------------
|
||||
-- Last_Error_Message --
|
||||
------------------------
|
||||
|
||||
function Last_Error_Message (Strm : in Z_Stream) return String is
|
||||
use Interfaces.C.Strings;
|
||||
begin
|
||||
if Strm.msg = Null_Ptr then
|
||||
return "";
|
||||
else
|
||||
return Value (Strm.msg);
|
||||
end if;
|
||||
end Last_Error_Message;
|
||||
|
||||
------------
|
||||
-- Set_In --
|
||||
------------
|
||||
|
||||
procedure Set_In
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt) is
|
||||
begin
|
||||
Strm.Next_In := Buffer;
|
||||
Strm.Avail_In := Size;
|
||||
end Set_In;
|
||||
|
||||
------------------
|
||||
-- Set_Mem_Func --
|
||||
------------------
|
||||
|
||||
procedure Set_Mem_Func
|
||||
(Strm : in out Z_Stream;
|
||||
Opaque : in Voidp;
|
||||
Alloc : in alloc_func;
|
||||
Free : in free_func) is
|
||||
begin
|
||||
Strm.opaque := Opaque;
|
||||
Strm.zalloc := Alloc;
|
||||
Strm.zfree := Free;
|
||||
end Set_Mem_Func;
|
||||
|
||||
-------------
|
||||
-- Set_Out --
|
||||
-------------
|
||||
|
||||
procedure Set_Out
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt) is
|
||||
begin
|
||||
Strm.Next_Out := Buffer;
|
||||
Strm.Avail_Out := Size;
|
||||
end Set_Out;
|
||||
|
||||
--------------
|
||||
-- Total_In --
|
||||
--------------
|
||||
|
||||
function Total_In (Strm : in Z_Stream) return ULong is
|
||||
begin
|
||||
return Strm.Total_In;
|
||||
end Total_In;
|
||||
|
||||
---------------
|
||||
-- Total_Out --
|
||||
---------------
|
||||
|
||||
function Total_Out (Strm : in Z_Stream) return ULong is
|
||||
begin
|
||||
return Strm.Total_Out;
|
||||
end Total_Out;
|
||||
|
||||
end ZLib.Thin;
|
450
third_party/zlib/contrib/ada/zlib-thin.ads
vendored
450
third_party/zlib/contrib/ada/zlib-thin.ads
vendored
@ -1,450 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2003 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib-thin.ads,v 1.11 2004/07/23 06:33:11 vagul Exp $
|
||||
|
||||
with Interfaces.C.Strings;
|
||||
|
||||
with System;
|
||||
|
||||
private package ZLib.Thin is
|
||||
|
||||
-- From zconf.h
|
||||
|
||||
MAX_MEM_LEVEL : constant := 9; -- zconf.h:105
|
||||
-- zconf.h:105
|
||||
MAX_WBITS : constant := 15; -- zconf.h:115
|
||||
-- 32K LZ77 window
|
||||
-- zconf.h:115
|
||||
SEEK_SET : constant := 8#0000#; -- zconf.h:244
|
||||
-- Seek from beginning of file.
|
||||
-- zconf.h:244
|
||||
SEEK_CUR : constant := 1; -- zconf.h:245
|
||||
-- Seek from current position.
|
||||
-- zconf.h:245
|
||||
SEEK_END : constant := 2; -- zconf.h:246
|
||||
-- Set file pointer to EOF plus "offset"
|
||||
-- zconf.h:246
|
||||
|
||||
type Byte is new Interfaces.C.unsigned_char; -- 8 bits
|
||||
-- zconf.h:214
|
||||
type UInt is new Interfaces.C.unsigned; -- 16 bits or more
|
||||
-- zconf.h:216
|
||||
type Int is new Interfaces.C.int;
|
||||
|
||||
type ULong is new Interfaces.C.unsigned_long; -- 32 bits or more
|
||||
-- zconf.h:217
|
||||
subtype Chars_Ptr is Interfaces.C.Strings.chars_ptr;
|
||||
|
||||
type ULong_Access is access ULong;
|
||||
type Int_Access is access Int;
|
||||
|
||||
subtype Voidp is System.Address; -- zconf.h:232
|
||||
|
||||
subtype Byte_Access is Voidp;
|
||||
|
||||
Nul : constant Voidp := System.Null_Address;
|
||||
-- end from zconf
|
||||
|
||||
Z_NO_FLUSH : constant := 8#0000#; -- zlib.h:125
|
||||
-- zlib.h:125
|
||||
Z_PARTIAL_FLUSH : constant := 1; -- zlib.h:126
|
||||
-- will be removed, use
|
||||
-- Z_SYNC_FLUSH instead
|
||||
-- zlib.h:126
|
||||
Z_SYNC_FLUSH : constant := 2; -- zlib.h:127
|
||||
-- zlib.h:127
|
||||
Z_FULL_FLUSH : constant := 3; -- zlib.h:128
|
||||
-- zlib.h:128
|
||||
Z_FINISH : constant := 4; -- zlib.h:129
|
||||
-- zlib.h:129
|
||||
Z_OK : constant := 8#0000#; -- zlib.h:132
|
||||
-- zlib.h:132
|
||||
Z_STREAM_END : constant := 1; -- zlib.h:133
|
||||
-- zlib.h:133
|
||||
Z_NEED_DICT : constant := 2; -- zlib.h:134
|
||||
-- zlib.h:134
|
||||
Z_ERRNO : constant := -1; -- zlib.h:135
|
||||
-- zlib.h:135
|
||||
Z_STREAM_ERROR : constant := -2; -- zlib.h:136
|
||||
-- zlib.h:136
|
||||
Z_DATA_ERROR : constant := -3; -- zlib.h:137
|
||||
-- zlib.h:137
|
||||
Z_MEM_ERROR : constant := -4; -- zlib.h:138
|
||||
-- zlib.h:138
|
||||
Z_BUF_ERROR : constant := -5; -- zlib.h:139
|
||||
-- zlib.h:139
|
||||
Z_VERSION_ERROR : constant := -6; -- zlib.h:140
|
||||
-- zlib.h:140
|
||||
Z_NO_COMPRESSION : constant := 8#0000#; -- zlib.h:145
|
||||
-- zlib.h:145
|
||||
Z_BEST_SPEED : constant := 1; -- zlib.h:146
|
||||
-- zlib.h:146
|
||||
Z_BEST_COMPRESSION : constant := 9; -- zlib.h:147
|
||||
-- zlib.h:147
|
||||
Z_DEFAULT_COMPRESSION : constant := -1; -- zlib.h:148
|
||||
-- zlib.h:148
|
||||
Z_FILTERED : constant := 1; -- zlib.h:151
|
||||
-- zlib.h:151
|
||||
Z_HUFFMAN_ONLY : constant := 2; -- zlib.h:152
|
||||
-- zlib.h:152
|
||||
Z_DEFAULT_STRATEGY : constant := 8#0000#; -- zlib.h:153
|
||||
-- zlib.h:153
|
||||
Z_BINARY : constant := 8#0000#; -- zlib.h:156
|
||||
-- zlib.h:156
|
||||
Z_ASCII : constant := 1; -- zlib.h:157
|
||||
-- zlib.h:157
|
||||
Z_UNKNOWN : constant := 2; -- zlib.h:158
|
||||
-- zlib.h:158
|
||||
Z_DEFLATED : constant := 8; -- zlib.h:161
|
||||
-- zlib.h:161
|
||||
Z_NULL : constant := 8#0000#; -- zlib.h:164
|
||||
-- for initializing zalloc, zfree, opaque
|
||||
-- zlib.h:164
|
||||
type gzFile is new Voidp; -- zlib.h:646
|
||||
|
||||
type Z_Stream is private;
|
||||
|
||||
type Z_Streamp is access all Z_Stream; -- zlib.h:89
|
||||
|
||||
type alloc_func is access function
|
||||
(Opaque : Voidp;
|
||||
Items : UInt;
|
||||
Size : UInt)
|
||||
return Voidp; -- zlib.h:63
|
||||
|
||||
type free_func is access procedure (opaque : Voidp; address : Voidp);
|
||||
|
||||
function zlibVersion return Chars_Ptr;
|
||||
|
||||
function Deflate (strm : Z_Streamp; flush : Int) return Int;
|
||||
|
||||
function DeflateEnd (strm : Z_Streamp) return Int;
|
||||
|
||||
function Inflate (strm : Z_Streamp; flush : Int) return Int;
|
||||
|
||||
function InflateEnd (strm : Z_Streamp) return Int;
|
||||
|
||||
function deflateSetDictionary
|
||||
(strm : Z_Streamp;
|
||||
dictionary : Byte_Access;
|
||||
dictLength : UInt)
|
||||
return Int;
|
||||
|
||||
function deflateCopy (dest : Z_Streamp; source : Z_Streamp) return Int;
|
||||
-- zlib.h:478
|
||||
|
||||
function deflateReset (strm : Z_Streamp) return Int; -- zlib.h:495
|
||||
|
||||
function deflateParams
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
strategy : Int)
|
||||
return Int; -- zlib.h:506
|
||||
|
||||
function inflateSetDictionary
|
||||
(strm : Z_Streamp;
|
||||
dictionary : Byte_Access;
|
||||
dictLength : UInt)
|
||||
return Int; -- zlib.h:548
|
||||
|
||||
function inflateSync (strm : Z_Streamp) return Int; -- zlib.h:565
|
||||
|
||||
function inflateReset (strm : Z_Streamp) return Int; -- zlib.h:580
|
||||
|
||||
function compress
|
||||
(dest : Byte_Access;
|
||||
destLen : ULong_Access;
|
||||
source : Byte_Access;
|
||||
sourceLen : ULong)
|
||||
return Int; -- zlib.h:601
|
||||
|
||||
function compress2
|
||||
(dest : Byte_Access;
|
||||
destLen : ULong_Access;
|
||||
source : Byte_Access;
|
||||
sourceLen : ULong;
|
||||
level : Int)
|
||||
return Int; -- zlib.h:615
|
||||
|
||||
function uncompress
|
||||
(dest : Byte_Access;
|
||||
destLen : ULong_Access;
|
||||
source : Byte_Access;
|
||||
sourceLen : ULong)
|
||||
return Int;
|
||||
|
||||
function gzopen (path : Chars_Ptr; mode : Chars_Ptr) return gzFile;
|
||||
|
||||
function gzdopen (fd : Int; mode : Chars_Ptr) return gzFile;
|
||||
|
||||
function gzsetparams
|
||||
(file : gzFile;
|
||||
level : Int;
|
||||
strategy : Int)
|
||||
return Int;
|
||||
|
||||
function gzread
|
||||
(file : gzFile;
|
||||
buf : Voidp;
|
||||
len : UInt)
|
||||
return Int;
|
||||
|
||||
function gzwrite
|
||||
(file : in gzFile;
|
||||
buf : in Voidp;
|
||||
len : in UInt)
|
||||
return Int;
|
||||
|
||||
function gzprintf (file : in gzFile; format : in Chars_Ptr) return Int;
|
||||
|
||||
function gzputs (file : in gzFile; s : in Chars_Ptr) return Int;
|
||||
|
||||
function gzgets
|
||||
(file : gzFile;
|
||||
buf : Chars_Ptr;
|
||||
len : Int)
|
||||
return Chars_Ptr;
|
||||
|
||||
function gzputc (file : gzFile; char : Int) return Int;
|
||||
|
||||
function gzgetc (file : gzFile) return Int;
|
||||
|
||||
function gzflush (file : gzFile; flush : Int) return Int;
|
||||
|
||||
function gzseek
|
||||
(file : gzFile;
|
||||
offset : Int;
|
||||
whence : Int)
|
||||
return Int;
|
||||
|
||||
function gzrewind (file : gzFile) return Int;
|
||||
|
||||
function gztell (file : gzFile) return Int;
|
||||
|
||||
function gzeof (file : gzFile) return Int;
|
||||
|
||||
function gzclose (file : gzFile) return Int;
|
||||
|
||||
function gzerror (file : gzFile; errnum : Int_Access) return Chars_Ptr;
|
||||
|
||||
function adler32
|
||||
(adler : ULong;
|
||||
buf : Byte_Access;
|
||||
len : UInt)
|
||||
return ULong;
|
||||
|
||||
function crc32
|
||||
(crc : ULong;
|
||||
buf : Byte_Access;
|
||||
len : UInt)
|
||||
return ULong;
|
||||
|
||||
function deflateInit
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
version : Chars_Ptr;
|
||||
stream_size : Int)
|
||||
return Int;
|
||||
|
||||
function deflateInit2
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
method : Int;
|
||||
windowBits : Int;
|
||||
memLevel : Int;
|
||||
strategy : Int;
|
||||
version : Chars_Ptr;
|
||||
stream_size : Int)
|
||||
return Int;
|
||||
|
||||
function Deflate_Init
|
||||
(strm : Z_Streamp;
|
||||
level : Int;
|
||||
method : Int;
|
||||
windowBits : Int;
|
||||
memLevel : Int;
|
||||
strategy : Int)
|
||||
return Int;
|
||||
pragma Inline (Deflate_Init);
|
||||
|
||||
function inflateInit
|
||||
(strm : Z_Streamp;
|
||||
version : Chars_Ptr;
|
||||
stream_size : Int)
|
||||
return Int;
|
||||
|
||||
function inflateInit2
|
||||
(strm : in Z_Streamp;
|
||||
windowBits : in Int;
|
||||
version : in Chars_Ptr;
|
||||
stream_size : in Int)
|
||||
return Int;
|
||||
|
||||
function inflateBackInit
|
||||
(strm : in Z_Streamp;
|
||||
windowBits : in Int;
|
||||
window : in Byte_Access;
|
||||
version : in Chars_Ptr;
|
||||
stream_size : in Int)
|
||||
return Int;
|
||||
-- Size of window have to be 2**windowBits.
|
||||
|
||||
function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int;
|
||||
pragma Inline (Inflate_Init);
|
||||
|
||||
function zError (err : Int) return Chars_Ptr;
|
||||
|
||||
function inflateSyncPoint (z : Z_Streamp) return Int;
|
||||
|
||||
function get_crc_table return ULong_Access;
|
||||
|
||||
-- Interface to the available fields of the z_stream structure.
|
||||
-- The application must update next_in and avail_in when avail_in has
|
||||
-- dropped to zero. It must update next_out and avail_out when avail_out
|
||||
-- has dropped to zero. The application must initialize zalloc, zfree and
|
||||
-- opaque before calling the init function.
|
||||
|
||||
procedure Set_In
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt);
|
||||
pragma Inline (Set_In);
|
||||
|
||||
procedure Set_Out
|
||||
(Strm : in out Z_Stream;
|
||||
Buffer : in Voidp;
|
||||
Size : in UInt);
|
||||
pragma Inline (Set_Out);
|
||||
|
||||
procedure Set_Mem_Func
|
||||
(Strm : in out Z_Stream;
|
||||
Opaque : in Voidp;
|
||||
Alloc : in alloc_func;
|
||||
Free : in free_func);
|
||||
pragma Inline (Set_Mem_Func);
|
||||
|
||||
function Last_Error_Message (Strm : in Z_Stream) return String;
|
||||
pragma Inline (Last_Error_Message);
|
||||
|
||||
function Avail_Out (Strm : in Z_Stream) return UInt;
|
||||
pragma Inline (Avail_Out);
|
||||
|
||||
function Avail_In (Strm : in Z_Stream) return UInt;
|
||||
pragma Inline (Avail_In);
|
||||
|
||||
function Total_In (Strm : in Z_Stream) return ULong;
|
||||
pragma Inline (Total_In);
|
||||
|
||||
function Total_Out (Strm : in Z_Stream) return ULong;
|
||||
pragma Inline (Total_Out);
|
||||
|
||||
function inflateCopy
|
||||
(dest : in Z_Streamp;
|
||||
Source : in Z_Streamp)
|
||||
return Int;
|
||||
|
||||
function compressBound (Source_Len : in ULong) return ULong;
|
||||
|
||||
function deflateBound
|
||||
(Strm : in Z_Streamp;
|
||||
Source_Len : in ULong)
|
||||
return ULong;
|
||||
|
||||
function gzungetc (C : in Int; File : in gzFile) return Int;
|
||||
|
||||
function zlibCompileFlags return ULong;
|
||||
|
||||
private
|
||||
|
||||
type Z_Stream is record -- zlib.h:68
|
||||
Next_In : Voidp := Nul; -- next input byte
|
||||
Avail_In : UInt := 0; -- number of bytes available at next_in
|
||||
Total_In : ULong := 0; -- total nb of input bytes read so far
|
||||
Next_Out : Voidp := Nul; -- next output byte should be put there
|
||||
Avail_Out : UInt := 0; -- remaining free space at next_out
|
||||
Total_Out : ULong := 0; -- total nb of bytes output so far
|
||||
msg : Chars_Ptr; -- last error message, NULL if no error
|
||||
state : Voidp; -- not visible by applications
|
||||
zalloc : alloc_func := null; -- used to allocate the internal state
|
||||
zfree : free_func := null; -- used to free the internal state
|
||||
opaque : Voidp; -- private data object passed to
|
||||
-- zalloc and zfree
|
||||
data_type : Int; -- best guess about the data type:
|
||||
-- ascii or binary
|
||||
adler : ULong; -- adler32 value of the uncompressed
|
||||
-- data
|
||||
reserved : ULong; -- reserved for future use
|
||||
end record;
|
||||
|
||||
pragma Convention (C, Z_Stream);
|
||||
|
||||
pragma Import (C, zlibVersion, "zlibVersion");
|
||||
pragma Import (C, Deflate, "deflate");
|
||||
pragma Import (C, DeflateEnd, "deflateEnd");
|
||||
pragma Import (C, Inflate, "inflate");
|
||||
pragma Import (C, InflateEnd, "inflateEnd");
|
||||
pragma Import (C, deflateSetDictionary, "deflateSetDictionary");
|
||||
pragma Import (C, deflateCopy, "deflateCopy");
|
||||
pragma Import (C, deflateReset, "deflateReset");
|
||||
pragma Import (C, deflateParams, "deflateParams");
|
||||
pragma Import (C, inflateSetDictionary, "inflateSetDictionary");
|
||||
pragma Import (C, inflateSync, "inflateSync");
|
||||
pragma Import (C, inflateReset, "inflateReset");
|
||||
pragma Import (C, compress, "compress");
|
||||
pragma Import (C, compress2, "compress2");
|
||||
pragma Import (C, uncompress, "uncompress");
|
||||
pragma Import (C, gzopen, "gzopen");
|
||||
pragma Import (C, gzdopen, "gzdopen");
|
||||
pragma Import (C, gzsetparams, "gzsetparams");
|
||||
pragma Import (C, gzread, "gzread");
|
||||
pragma Import (C, gzwrite, "gzwrite");
|
||||
pragma Import (C, gzprintf, "gzprintf");
|
||||
pragma Import (C, gzputs, "gzputs");
|
||||
pragma Import (C, gzgets, "gzgets");
|
||||
pragma Import (C, gzputc, "gzputc");
|
||||
pragma Import (C, gzgetc, "gzgetc");
|
||||
pragma Import (C, gzflush, "gzflush");
|
||||
pragma Import (C, gzseek, "gzseek");
|
||||
pragma Import (C, gzrewind, "gzrewind");
|
||||
pragma Import (C, gztell, "gztell");
|
||||
pragma Import (C, gzeof, "gzeof");
|
||||
pragma Import (C, gzclose, "gzclose");
|
||||
pragma Import (C, gzerror, "gzerror");
|
||||
pragma Import (C, adler32, "adler32");
|
||||
pragma Import (C, crc32, "crc32");
|
||||
pragma Import (C, deflateInit, "deflateInit_");
|
||||
pragma Import (C, inflateInit, "inflateInit_");
|
||||
pragma Import (C, deflateInit2, "deflateInit2_");
|
||||
pragma Import (C, inflateInit2, "inflateInit2_");
|
||||
pragma Import (C, zError, "zError");
|
||||
pragma Import (C, inflateSyncPoint, "inflateSyncPoint");
|
||||
pragma Import (C, get_crc_table, "get_crc_table");
|
||||
|
||||
-- since zlib 1.2.0:
|
||||
|
||||
pragma Import (C, inflateCopy, "inflateCopy");
|
||||
pragma Import (C, compressBound, "compressBound");
|
||||
pragma Import (C, deflateBound, "deflateBound");
|
||||
pragma Import (C, gzungetc, "gzungetc");
|
||||
pragma Import (C, zlibCompileFlags, "zlibCompileFlags");
|
||||
|
||||
pragma Import (C, inflateBackInit, "inflateBackInit_");
|
||||
|
||||
-- I stopped binding the inflateBack routines, because realize that
|
||||
-- it does not support zlib and gzip headers for now, and have no
|
||||
-- symmetric deflateBack routines.
|
||||
-- ZLib-Ada is symmetric regarding deflate/inflate data transformation
|
||||
-- and has a similar generic callback interface for the
|
||||
-- deflate/inflate transformation based on the regular Deflate/Inflate
|
||||
-- routines.
|
||||
|
||||
-- pragma Import (C, inflateBack, "inflateBack");
|
||||
-- pragma Import (C, inflateBackEnd, "inflateBackEnd");
|
||||
|
||||
end ZLib.Thin;
|
701
third_party/zlib/contrib/ada/zlib.adb
vendored
701
third_party/zlib/contrib/ada/zlib.adb
vendored
@ -1,701 +0,0 @@
|
||||
----------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2004 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- Open source license information is in the zlib.ads file. --
|
||||
----------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib.adb,v 1.31 2004/09/06 06:53:19 vagul Exp $
|
||||
|
||||
with Ada.Exceptions;
|
||||
with Ada.Unchecked_Conversion;
|
||||
with Ada.Unchecked_Deallocation;
|
||||
|
||||
with Interfaces.C.Strings;
|
||||
|
||||
with ZLib.Thin;
|
||||
|
||||
package body ZLib is
|
||||
|
||||
use type Thin.Int;
|
||||
|
||||
type Z_Stream is new Thin.Z_Stream;
|
||||
|
||||
type Return_Code_Enum is
|
||||
(OK,
|
||||
STREAM_END,
|
||||
NEED_DICT,
|
||||
ERRNO,
|
||||
STREAM_ERROR,
|
||||
DATA_ERROR,
|
||||
MEM_ERROR,
|
||||
BUF_ERROR,
|
||||
VERSION_ERROR);
|
||||
|
||||
type Flate_Step_Function is access
|
||||
function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int;
|
||||
pragma Convention (C, Flate_Step_Function);
|
||||
|
||||
type Flate_End_Function is access
|
||||
function (Ctrm : in Thin.Z_Streamp) return Thin.Int;
|
||||
pragma Convention (C, Flate_End_Function);
|
||||
|
||||
type Flate_Type is record
|
||||
Step : Flate_Step_Function;
|
||||
Done : Flate_End_Function;
|
||||
end record;
|
||||
|
||||
subtype Footer_Array is Stream_Element_Array (1 .. 8);
|
||||
|
||||
Simple_GZip_Header : constant Stream_Element_Array (1 .. 10)
|
||||
:= (16#1f#, 16#8b#, -- Magic header
|
||||
16#08#, -- Z_DEFLATED
|
||||
16#00#, -- Flags
|
||||
16#00#, 16#00#, 16#00#, 16#00#, -- Time
|
||||
16#00#, -- XFlags
|
||||
16#03# -- OS code
|
||||
);
|
||||
-- The simplest gzip header is not for informational, but just for
|
||||
-- gzip format compatibility.
|
||||
-- Note that some code below is using assumption
|
||||
-- Simple_GZip_Header'Last > Footer_Array'Last, so do not make
|
||||
-- Simple_GZip_Header'Last <= Footer_Array'Last.
|
||||
|
||||
Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum
|
||||
:= (0 => OK,
|
||||
1 => STREAM_END,
|
||||
2 => NEED_DICT,
|
||||
-1 => ERRNO,
|
||||
-2 => STREAM_ERROR,
|
||||
-3 => DATA_ERROR,
|
||||
-4 => MEM_ERROR,
|
||||
-5 => BUF_ERROR,
|
||||
-6 => VERSION_ERROR);
|
||||
|
||||
Flate : constant array (Boolean) of Flate_Type
|
||||
:= (True => (Step => Thin.Deflate'Access,
|
||||
Done => Thin.DeflateEnd'Access),
|
||||
False => (Step => Thin.Inflate'Access,
|
||||
Done => Thin.InflateEnd'Access));
|
||||
|
||||
Flush_Finish : constant array (Boolean) of Flush_Mode
|
||||
:= (True => Finish, False => No_Flush);
|
||||
|
||||
procedure Raise_Error (Stream : in Z_Stream);
|
||||
pragma Inline (Raise_Error);
|
||||
|
||||
procedure Raise_Error (Message : in String);
|
||||
pragma Inline (Raise_Error);
|
||||
|
||||
procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int);
|
||||
|
||||
procedure Free is new Ada.Unchecked_Deallocation
|
||||
(Z_Stream, Z_Stream_Access);
|
||||
|
||||
function To_Thin_Access is new Ada.Unchecked_Conversion
|
||||
(Z_Stream_Access, Thin.Z_Streamp);
|
||||
|
||||
procedure Translate_GZip
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode);
|
||||
-- Separate translate routine for make gzip header.
|
||||
|
||||
procedure Translate_Auto
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode);
|
||||
-- translate routine without additional headers.
|
||||
|
||||
-----------------
|
||||
-- Check_Error --
|
||||
-----------------
|
||||
|
||||
procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is
|
||||
use type Thin.Int;
|
||||
begin
|
||||
if Code /= Thin.Z_OK then
|
||||
Raise_Error
|
||||
(Return_Code_Enum'Image (Return_Code (Code))
|
||||
& ": " & Last_Error_Message (Stream));
|
||||
end if;
|
||||
end Check_Error;
|
||||
|
||||
-----------
|
||||
-- Close --
|
||||
-----------
|
||||
|
||||
procedure Close
|
||||
(Filter : in out Filter_Type;
|
||||
Ignore_Error : in Boolean := False)
|
||||
is
|
||||
Code : Thin.Int;
|
||||
begin
|
||||
if not Ignore_Error and then not Is_Open (Filter) then
|
||||
raise Status_Error;
|
||||
end if;
|
||||
|
||||
Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm));
|
||||
|
||||
if Ignore_Error or else Code = Thin.Z_OK then
|
||||
Free (Filter.Strm);
|
||||
else
|
||||
declare
|
||||
Error_Message : constant String
|
||||
:= Last_Error_Message (Filter.Strm.all);
|
||||
begin
|
||||
Free (Filter.Strm);
|
||||
Ada.Exceptions.Raise_Exception
|
||||
(ZLib_Error'Identity,
|
||||
Return_Code_Enum'Image (Return_Code (Code))
|
||||
& ": " & Error_Message);
|
||||
end;
|
||||
end if;
|
||||
end Close;
|
||||
|
||||
-----------
|
||||
-- CRC32 --
|
||||
-----------
|
||||
|
||||
function CRC32
|
||||
(CRC : in Unsigned_32;
|
||||
Data : in Ada.Streams.Stream_Element_Array)
|
||||
return Unsigned_32
|
||||
is
|
||||
use Thin;
|
||||
begin
|
||||
return Unsigned_32 (crc32 (ULong (CRC),
|
||||
Data'Address,
|
||||
Data'Length));
|
||||
end CRC32;
|
||||
|
||||
procedure CRC32
|
||||
(CRC : in out Unsigned_32;
|
||||
Data : in Ada.Streams.Stream_Element_Array) is
|
||||
begin
|
||||
CRC := CRC32 (CRC, Data);
|
||||
end CRC32;
|
||||
|
||||
------------------
|
||||
-- Deflate_Init --
|
||||
------------------
|
||||
|
||||
procedure Deflate_Init
|
||||
(Filter : in out Filter_Type;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Method : in Compression_Method := Deflated;
|
||||
Window_Bits : in Window_Bits_Type := Default_Window_Bits;
|
||||
Memory_Level : in Memory_Level_Type := Default_Memory_Level;
|
||||
Header : in Header_Type := Default)
|
||||
is
|
||||
use type Thin.Int;
|
||||
Win_Bits : Thin.Int := Thin.Int (Window_Bits);
|
||||
begin
|
||||
if Is_Open (Filter) then
|
||||
raise Status_Error;
|
||||
end if;
|
||||
|
||||
-- We allow ZLib to make header only in case of default header type.
|
||||
-- Otherwise we would either do header by ourselfs, or do not do
|
||||
-- header at all.
|
||||
|
||||
if Header = None or else Header = GZip then
|
||||
Win_Bits := -Win_Bits;
|
||||
end if;
|
||||
|
||||
-- For the GZip CRC calculation and make headers.
|
||||
|
||||
if Header = GZip then
|
||||
Filter.CRC := 0;
|
||||
Filter.Offset := Simple_GZip_Header'First;
|
||||
else
|
||||
Filter.Offset := Simple_GZip_Header'Last + 1;
|
||||
end if;
|
||||
|
||||
Filter.Strm := new Z_Stream;
|
||||
Filter.Compression := True;
|
||||
Filter.Stream_End := False;
|
||||
Filter.Header := Header;
|
||||
|
||||
if Thin.Deflate_Init
|
||||
(To_Thin_Access (Filter.Strm),
|
||||
Level => Thin.Int (Level),
|
||||
method => Thin.Int (Method),
|
||||
windowBits => Win_Bits,
|
||||
memLevel => Thin.Int (Memory_Level),
|
||||
strategy => Thin.Int (Strategy)) /= Thin.Z_OK
|
||||
then
|
||||
Raise_Error (Filter.Strm.all);
|
||||
end if;
|
||||
end Deflate_Init;
|
||||
|
||||
-----------
|
||||
-- Flush --
|
||||
-----------
|
||||
|
||||
procedure Flush
|
||||
(Filter : in out Filter_Type;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode)
|
||||
is
|
||||
No_Data : Stream_Element_Array := (1 .. 0 => 0);
|
||||
Last : Stream_Element_Offset;
|
||||
begin
|
||||
Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush);
|
||||
end Flush;
|
||||
|
||||
-----------------------
|
||||
-- Generic_Translate --
|
||||
-----------------------
|
||||
|
||||
procedure Generic_Translate
|
||||
(Filter : in out ZLib.Filter_Type;
|
||||
In_Buffer_Size : in Integer := Default_Buffer_Size;
|
||||
Out_Buffer_Size : in Integer := Default_Buffer_Size)
|
||||
is
|
||||
In_Buffer : Stream_Element_Array
|
||||
(1 .. Stream_Element_Offset (In_Buffer_Size));
|
||||
Out_Buffer : Stream_Element_Array
|
||||
(1 .. Stream_Element_Offset (Out_Buffer_Size));
|
||||
Last : Stream_Element_Offset;
|
||||
In_Last : Stream_Element_Offset;
|
||||
In_First : Stream_Element_Offset;
|
||||
Out_Last : Stream_Element_Offset;
|
||||
begin
|
||||
Main : loop
|
||||
Data_In (In_Buffer, Last);
|
||||
|
||||
In_First := In_Buffer'First;
|
||||
|
||||
loop
|
||||
Translate
|
||||
(Filter => Filter,
|
||||
In_Data => In_Buffer (In_First .. Last),
|
||||
In_Last => In_Last,
|
||||
Out_Data => Out_Buffer,
|
||||
Out_Last => Out_Last,
|
||||
Flush => Flush_Finish (Last < In_Buffer'First));
|
||||
|
||||
if Out_Buffer'First <= Out_Last then
|
||||
Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last));
|
||||
end if;
|
||||
|
||||
exit Main when Stream_End (Filter);
|
||||
|
||||
-- The end of in buffer.
|
||||
|
||||
exit when In_Last = Last;
|
||||
|
||||
In_First := In_Last + 1;
|
||||
end loop;
|
||||
end loop Main;
|
||||
|
||||
end Generic_Translate;
|
||||
|
||||
------------------
|
||||
-- Inflate_Init --
|
||||
------------------
|
||||
|
||||
procedure Inflate_Init
|
||||
(Filter : in out Filter_Type;
|
||||
Window_Bits : in Window_Bits_Type := Default_Window_Bits;
|
||||
Header : in Header_Type := Default)
|
||||
is
|
||||
use type Thin.Int;
|
||||
Win_Bits : Thin.Int := Thin.Int (Window_Bits);
|
||||
|
||||
procedure Check_Version;
|
||||
-- Check the latest header types compatibility.
|
||||
|
||||
procedure Check_Version is
|
||||
begin
|
||||
if Version <= "1.1.4" then
|
||||
Raise_Error
|
||||
("Inflate header type " & Header_Type'Image (Header)
|
||||
& " incompatible with ZLib version " & Version);
|
||||
end if;
|
||||
end Check_Version;
|
||||
|
||||
begin
|
||||
if Is_Open (Filter) then
|
||||
raise Status_Error;
|
||||
end if;
|
||||
|
||||
case Header is
|
||||
when None =>
|
||||
Check_Version;
|
||||
|
||||
-- Inflate data without headers determined
|
||||
-- by negative Win_Bits.
|
||||
|
||||
Win_Bits := -Win_Bits;
|
||||
when GZip =>
|
||||
Check_Version;
|
||||
|
||||
-- Inflate gzip data defined by flag 16.
|
||||
|
||||
Win_Bits := Win_Bits + 16;
|
||||
when Auto =>
|
||||
Check_Version;
|
||||
|
||||
-- Inflate with automatic detection
|
||||
-- of gzip or native header defined by flag 32.
|
||||
|
||||
Win_Bits := Win_Bits + 32;
|
||||
when Default => null;
|
||||
end case;
|
||||
|
||||
Filter.Strm := new Z_Stream;
|
||||
Filter.Compression := False;
|
||||
Filter.Stream_End := False;
|
||||
Filter.Header := Header;
|
||||
|
||||
if Thin.Inflate_Init
|
||||
(To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK
|
||||
then
|
||||
Raise_Error (Filter.Strm.all);
|
||||
end if;
|
||||
end Inflate_Init;
|
||||
|
||||
-------------
|
||||
-- Is_Open --
|
||||
-------------
|
||||
|
||||
function Is_Open (Filter : in Filter_Type) return Boolean is
|
||||
begin
|
||||
return Filter.Strm /= null;
|
||||
end Is_Open;
|
||||
|
||||
-----------------
|
||||
-- Raise_Error --
|
||||
-----------------
|
||||
|
||||
procedure Raise_Error (Message : in String) is
|
||||
begin
|
||||
Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message);
|
||||
end Raise_Error;
|
||||
|
||||
procedure Raise_Error (Stream : in Z_Stream) is
|
||||
begin
|
||||
Raise_Error (Last_Error_Message (Stream));
|
||||
end Raise_Error;
|
||||
|
||||
----------
|
||||
-- Read --
|
||||
----------
|
||||
|
||||
procedure Read
|
||||
(Filter : in out Filter_Type;
|
||||
Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode := No_Flush)
|
||||
is
|
||||
In_Last : Stream_Element_Offset;
|
||||
Item_First : Ada.Streams.Stream_Element_Offset := Item'First;
|
||||
V_Flush : Flush_Mode := Flush;
|
||||
|
||||
begin
|
||||
pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1);
|
||||
pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last);
|
||||
|
||||
loop
|
||||
if Rest_Last = Buffer'First - 1 then
|
||||
V_Flush := Finish;
|
||||
|
||||
elsif Rest_First > Rest_Last then
|
||||
Read (Buffer, Rest_Last);
|
||||
Rest_First := Buffer'First;
|
||||
|
||||
if Rest_Last < Buffer'First then
|
||||
V_Flush := Finish;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
Translate
|
||||
(Filter => Filter,
|
||||
In_Data => Buffer (Rest_First .. Rest_Last),
|
||||
In_Last => In_Last,
|
||||
Out_Data => Item (Item_First .. Item'Last),
|
||||
Out_Last => Last,
|
||||
Flush => V_Flush);
|
||||
|
||||
Rest_First := In_Last + 1;
|
||||
|
||||
exit when Stream_End (Filter)
|
||||
or else Last = Item'Last
|
||||
or else (Last >= Item'First and then Allow_Read_Some);
|
||||
|
||||
Item_First := Last + 1;
|
||||
end loop;
|
||||
end Read;
|
||||
|
||||
----------------
|
||||
-- Stream_End --
|
||||
----------------
|
||||
|
||||
function Stream_End (Filter : in Filter_Type) return Boolean is
|
||||
begin
|
||||
if Filter.Header = GZip and Filter.Compression then
|
||||
return Filter.Stream_End
|
||||
and then Filter.Offset = Footer_Array'Last + 1;
|
||||
else
|
||||
return Filter.Stream_End;
|
||||
end if;
|
||||
end Stream_End;
|
||||
|
||||
--------------
|
||||
-- Total_In --
|
||||
--------------
|
||||
|
||||
function Total_In (Filter : in Filter_Type) return Count is
|
||||
begin
|
||||
return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all));
|
||||
end Total_In;
|
||||
|
||||
---------------
|
||||
-- Total_Out --
|
||||
---------------
|
||||
|
||||
function Total_Out (Filter : in Filter_Type) return Count is
|
||||
begin
|
||||
return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all));
|
||||
end Total_Out;
|
||||
|
||||
---------------
|
||||
-- Translate --
|
||||
---------------
|
||||
|
||||
procedure Translate
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode) is
|
||||
begin
|
||||
if Filter.Header = GZip and then Filter.Compression then
|
||||
Translate_GZip
|
||||
(Filter => Filter,
|
||||
In_Data => In_Data,
|
||||
In_Last => In_Last,
|
||||
Out_Data => Out_Data,
|
||||
Out_Last => Out_Last,
|
||||
Flush => Flush);
|
||||
else
|
||||
Translate_Auto
|
||||
(Filter => Filter,
|
||||
In_Data => In_Data,
|
||||
In_Last => In_Last,
|
||||
Out_Data => Out_Data,
|
||||
Out_Last => Out_Last,
|
||||
Flush => Flush);
|
||||
end if;
|
||||
end Translate;
|
||||
|
||||
--------------------
|
||||
-- Translate_Auto --
|
||||
--------------------
|
||||
|
||||
procedure Translate_Auto
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode)
|
||||
is
|
||||
use type Thin.Int;
|
||||
Code : Thin.Int;
|
||||
|
||||
begin
|
||||
if not Is_Open (Filter) then
|
||||
raise Status_Error;
|
||||
end if;
|
||||
|
||||
if Out_Data'Length = 0 and then In_Data'Length = 0 then
|
||||
raise Constraint_Error;
|
||||
end if;
|
||||
|
||||
Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length);
|
||||
Set_In (Filter.Strm.all, In_Data'Address, In_Data'Length);
|
||||
|
||||
Code := Flate (Filter.Compression).Step
|
||||
(To_Thin_Access (Filter.Strm),
|
||||
Thin.Int (Flush));
|
||||
|
||||
if Code = Thin.Z_STREAM_END then
|
||||
Filter.Stream_End := True;
|
||||
else
|
||||
Check_Error (Filter.Strm.all, Code);
|
||||
end if;
|
||||
|
||||
In_Last := In_Data'Last
|
||||
- Stream_Element_Offset (Avail_In (Filter.Strm.all));
|
||||
Out_Last := Out_Data'Last
|
||||
- Stream_Element_Offset (Avail_Out (Filter.Strm.all));
|
||||
end Translate_Auto;
|
||||
|
||||
--------------------
|
||||
-- Translate_GZip --
|
||||
--------------------
|
||||
|
||||
procedure Translate_GZip
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode)
|
||||
is
|
||||
Out_First : Stream_Element_Offset;
|
||||
|
||||
procedure Add_Data (Data : in Stream_Element_Array);
|
||||
-- Add data to stream from the Filter.Offset till necessary,
|
||||
-- used for add gzip headr/footer.
|
||||
|
||||
procedure Put_32
|
||||
(Item : in out Stream_Element_Array;
|
||||
Data : in Unsigned_32);
|
||||
pragma Inline (Put_32);
|
||||
|
||||
--------------
|
||||
-- Add_Data --
|
||||
--------------
|
||||
|
||||
procedure Add_Data (Data : in Stream_Element_Array) is
|
||||
Data_First : Stream_Element_Offset renames Filter.Offset;
|
||||
Data_Last : Stream_Element_Offset;
|
||||
Data_Len : Stream_Element_Offset; -- -1
|
||||
Out_Len : Stream_Element_Offset; -- -1
|
||||
begin
|
||||
Out_First := Out_Last + 1;
|
||||
|
||||
if Data_First > Data'Last then
|
||||
return;
|
||||
end if;
|
||||
|
||||
Data_Len := Data'Last - Data_First;
|
||||
Out_Len := Out_Data'Last - Out_First;
|
||||
|
||||
if Data_Len <= Out_Len then
|
||||
Out_Last := Out_First + Data_Len;
|
||||
Data_Last := Data'Last;
|
||||
else
|
||||
Out_Last := Out_Data'Last;
|
||||
Data_Last := Data_First + Out_Len;
|
||||
end if;
|
||||
|
||||
Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last);
|
||||
|
||||
Data_First := Data_Last + 1;
|
||||
Out_First := Out_Last + 1;
|
||||
end Add_Data;
|
||||
|
||||
------------
|
||||
-- Put_32 --
|
||||
------------
|
||||
|
||||
procedure Put_32
|
||||
(Item : in out Stream_Element_Array;
|
||||
Data : in Unsigned_32)
|
||||
is
|
||||
D : Unsigned_32 := Data;
|
||||
begin
|
||||
for J in Item'First .. Item'First + 3 loop
|
||||
Item (J) := Stream_Element (D and 16#FF#);
|
||||
D := Shift_Right (D, 8);
|
||||
end loop;
|
||||
end Put_32;
|
||||
|
||||
begin
|
||||
Out_Last := Out_Data'First - 1;
|
||||
|
||||
if not Filter.Stream_End then
|
||||
Add_Data (Simple_GZip_Header);
|
||||
|
||||
Translate_Auto
|
||||
(Filter => Filter,
|
||||
In_Data => In_Data,
|
||||
In_Last => In_Last,
|
||||
Out_Data => Out_Data (Out_First .. Out_Data'Last),
|
||||
Out_Last => Out_Last,
|
||||
Flush => Flush);
|
||||
|
||||
CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last));
|
||||
end if;
|
||||
|
||||
if Filter.Stream_End and then Out_Last <= Out_Data'Last then
|
||||
-- This detection method would work only when
|
||||
-- Simple_GZip_Header'Last > Footer_Array'Last
|
||||
|
||||
if Filter.Offset = Simple_GZip_Header'Last + 1 then
|
||||
Filter.Offset := Footer_Array'First;
|
||||
end if;
|
||||
|
||||
declare
|
||||
Footer : Footer_Array;
|
||||
begin
|
||||
Put_32 (Footer, Filter.CRC);
|
||||
Put_32 (Footer (Footer'First + 4 .. Footer'Last),
|
||||
Unsigned_32 (Total_In (Filter)));
|
||||
Add_Data (Footer);
|
||||
end;
|
||||
end if;
|
||||
end Translate_GZip;
|
||||
|
||||
-------------
|
||||
-- Version --
|
||||
-------------
|
||||
|
||||
function Version return String is
|
||||
begin
|
||||
return Interfaces.C.Strings.Value (Thin.zlibVersion);
|
||||
end Version;
|
||||
|
||||
-----------
|
||||
-- Write --
|
||||
-----------
|
||||
|
||||
procedure Write
|
||||
(Filter : in out Filter_Type;
|
||||
Item : in Ada.Streams.Stream_Element_Array;
|
||||
Flush : in Flush_Mode := No_Flush)
|
||||
is
|
||||
Buffer : Stream_Element_Array (1 .. Buffer_Size);
|
||||
In_Last : Stream_Element_Offset;
|
||||
Out_Last : Stream_Element_Offset;
|
||||
In_First : Stream_Element_Offset := Item'First;
|
||||
begin
|
||||
if Item'Length = 0 and Flush = No_Flush then
|
||||
return;
|
||||
end if;
|
||||
|
||||
loop
|
||||
Translate
|
||||
(Filter => Filter,
|
||||
In_Data => Item (In_First .. Item'Last),
|
||||
In_Last => In_Last,
|
||||
Out_Data => Buffer,
|
||||
Out_Last => Out_Last,
|
||||
Flush => Flush);
|
||||
|
||||
if Out_Last >= Buffer'First then
|
||||
Write (Buffer (1 .. Out_Last));
|
||||
end if;
|
||||
|
||||
exit when In_Last = Item'Last or Stream_End (Filter);
|
||||
|
||||
In_First := In_Last + 1;
|
||||
end loop;
|
||||
end Write;
|
||||
|
||||
end ZLib;
|
328
third_party/zlib/contrib/ada/zlib.ads
vendored
328
third_party/zlib/contrib/ada/zlib.ads
vendored
@ -1,328 +0,0 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- ZLib for Ada thick binding. --
|
||||
-- --
|
||||
-- Copyright (C) 2002-2004 Dmitriy Anisimkov --
|
||||
-- --
|
||||
-- This library 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; either version 2 of the License, or (at --
|
||||
-- your option) any later version. --
|
||||
-- --
|
||||
-- This library 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 library; if not, write to the Free Software Foundation, --
|
||||
-- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --
|
||||
-- --
|
||||
-- As a special exception, if other files instantiate generics from this --
|
||||
-- unit, or you link this unit with other files to produce an executable, --
|
||||
-- this unit does not by itself cause the resulting executable to be --
|
||||
-- covered by the GNU General Public License. This exception does not --
|
||||
-- however invalidate any other reasons why the executable file might be --
|
||||
-- covered by the GNU Public License. --
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- $Id: zlib.ads,v 1.26 2004/09/06 06:53:19 vagul Exp $
|
||||
|
||||
with Ada.Streams;
|
||||
|
||||
with Interfaces;
|
||||
|
||||
package ZLib is
|
||||
|
||||
ZLib_Error : exception;
|
||||
Status_Error : exception;
|
||||
|
||||
type Compression_Level is new Integer range -1 .. 9;
|
||||
|
||||
type Flush_Mode is private;
|
||||
|
||||
type Compression_Method is private;
|
||||
|
||||
type Window_Bits_Type is new Integer range 8 .. 15;
|
||||
|
||||
type Memory_Level_Type is new Integer range 1 .. 9;
|
||||
|
||||
type Unsigned_32 is new Interfaces.Unsigned_32;
|
||||
|
||||
type Strategy_Type is private;
|
||||
|
||||
type Header_Type is (None, Auto, Default, GZip);
|
||||
-- Header type usage have a some limitation for inflate.
|
||||
-- See comment for Inflate_Init.
|
||||
|
||||
subtype Count is Ada.Streams.Stream_Element_Count;
|
||||
|
||||
Default_Memory_Level : constant Memory_Level_Type := 8;
|
||||
Default_Window_Bits : constant Window_Bits_Type := 15;
|
||||
|
||||
----------------------------------
|
||||
-- Compression method constants --
|
||||
----------------------------------
|
||||
|
||||
Deflated : constant Compression_Method;
|
||||
-- Only one method allowed in this ZLib version
|
||||
|
||||
---------------------------------
|
||||
-- Compression level constants --
|
||||
---------------------------------
|
||||
|
||||
No_Compression : constant Compression_Level := 0;
|
||||
Best_Speed : constant Compression_Level := 1;
|
||||
Best_Compression : constant Compression_Level := 9;
|
||||
Default_Compression : constant Compression_Level := -1;
|
||||
|
||||
--------------------------
|
||||
-- Flush mode constants --
|
||||
--------------------------
|
||||
|
||||
No_Flush : constant Flush_Mode;
|
||||
-- Regular way for compression, no flush
|
||||
|
||||
Partial_Flush : constant Flush_Mode;
|
||||
-- Will be removed, use Z_SYNC_FLUSH instead
|
||||
|
||||
Sync_Flush : constant Flush_Mode;
|
||||
-- All pending output is flushed to the output buffer and the output
|
||||
-- is aligned on a byte boundary, so that the decompressor can get all
|
||||
-- input data available so far. (In particular avail_in is zero after the
|
||||
-- call if enough output space has been provided before the call.)
|
||||
-- Flushing may degrade compression for some compression algorithms and so
|
||||
-- it should be used only when necessary.
|
||||
|
||||
Block_Flush : constant Flush_Mode;
|
||||
-- Z_BLOCK requests that inflate() stop
|
||||
-- if and when it get to the next deflate block boundary. When decoding the
|
||||
-- zlib or gzip format, this will cause inflate() to return immediately
|
||||
-- after the header and before the first block. When doing a raw inflate,
|
||||
-- inflate() will go ahead and process the first block, and will return
|
||||
-- when it gets to the end of that block, or when it runs out of data.
|
||||
|
||||
Full_Flush : constant Flush_Mode;
|
||||
-- All output is flushed as with SYNC_FLUSH, and the compression state
|
||||
-- is reset so that decompression can restart from this point if previous
|
||||
-- compressed data has been damaged or if random access is desired. Using
|
||||
-- Full_Flush too often can seriously degrade the compression.
|
||||
|
||||
Finish : constant Flush_Mode;
|
||||
-- Just for tell the compressor that input data is complete.
|
||||
|
||||
------------------------------------
|
||||
-- Compression strategy constants --
|
||||
------------------------------------
|
||||
|
||||
-- RLE stategy could be used only in version 1.2.0 and later.
|
||||
|
||||
Filtered : constant Strategy_Type;
|
||||
Huffman_Only : constant Strategy_Type;
|
||||
RLE : constant Strategy_Type;
|
||||
Default_Strategy : constant Strategy_Type;
|
||||
|
||||
Default_Buffer_Size : constant := 4096;
|
||||
|
||||
type Filter_Type is tagged limited private;
|
||||
-- The filter is for compression and for decompression.
|
||||
-- The usage of the type is depend of its initialization.
|
||||
|
||||
function Version return String;
|
||||
pragma Inline (Version);
|
||||
-- Return string representation of the ZLib version.
|
||||
|
||||
procedure Deflate_Init
|
||||
(Filter : in out Filter_Type;
|
||||
Level : in Compression_Level := Default_Compression;
|
||||
Strategy : in Strategy_Type := Default_Strategy;
|
||||
Method : in Compression_Method := Deflated;
|
||||
Window_Bits : in Window_Bits_Type := Default_Window_Bits;
|
||||
Memory_Level : in Memory_Level_Type := Default_Memory_Level;
|
||||
Header : in Header_Type := Default);
|
||||
-- Compressor initialization.
|
||||
-- When Header parameter is Auto or Default, then default zlib header
|
||||
-- would be provided for compressed data.
|
||||
-- When Header is GZip, then gzip header would be set instead of
|
||||
-- default header.
|
||||
-- When Header is None, no header would be set for compressed data.
|
||||
|
||||
procedure Inflate_Init
|
||||
(Filter : in out Filter_Type;
|
||||
Window_Bits : in Window_Bits_Type := Default_Window_Bits;
|
||||
Header : in Header_Type := Default);
|
||||
-- Decompressor initialization.
|
||||
-- Default header type mean that ZLib default header is expecting in the
|
||||
-- input compressed stream.
|
||||
-- Header type None mean that no header is expecting in the input stream.
|
||||
-- GZip header type mean that GZip header is expecting in the
|
||||
-- input compressed stream.
|
||||
-- Auto header type mean that header type (GZip or Native) would be
|
||||
-- detected automatically in the input stream.
|
||||
-- Note that header types parameter values None, GZip and Auto are
|
||||
-- supported for inflate routine only in ZLib versions 1.2.0.2 and later.
|
||||
-- Deflate_Init is supporting all header types.
|
||||
|
||||
function Is_Open (Filter : in Filter_Type) return Boolean;
|
||||
pragma Inline (Is_Open);
|
||||
-- Is the filter opened for compression or decompression.
|
||||
|
||||
procedure Close
|
||||
(Filter : in out Filter_Type;
|
||||
Ignore_Error : in Boolean := False);
|
||||
-- Closing the compression or decompressor.
|
||||
-- If stream is closing before the complete and Ignore_Error is False,
|
||||
-- The exception would be raised.
|
||||
|
||||
generic
|
||||
with procedure Data_In
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
with procedure Data_Out
|
||||
(Item : in Ada.Streams.Stream_Element_Array);
|
||||
procedure Generic_Translate
|
||||
(Filter : in out Filter_Type;
|
||||
In_Buffer_Size : in Integer := Default_Buffer_Size;
|
||||
Out_Buffer_Size : in Integer := Default_Buffer_Size);
|
||||
-- Compress/decompress data fetch from Data_In routine and pass the result
|
||||
-- to the Data_Out routine. User should provide Data_In and Data_Out
|
||||
-- for compression/decompression data flow.
|
||||
-- Compression or decompression depend on Filter initialization.
|
||||
|
||||
function Total_In (Filter : in Filter_Type) return Count;
|
||||
pragma Inline (Total_In);
|
||||
-- Returns total number of input bytes read so far
|
||||
|
||||
function Total_Out (Filter : in Filter_Type) return Count;
|
||||
pragma Inline (Total_Out);
|
||||
-- Returns total number of bytes output so far
|
||||
|
||||
function CRC32
|
||||
(CRC : in Unsigned_32;
|
||||
Data : in Ada.Streams.Stream_Element_Array)
|
||||
return Unsigned_32;
|
||||
pragma Inline (CRC32);
|
||||
-- Compute CRC32, it could be necessary for make gzip format
|
||||
|
||||
procedure CRC32
|
||||
(CRC : in out Unsigned_32;
|
||||
Data : in Ada.Streams.Stream_Element_Array);
|
||||
pragma Inline (CRC32);
|
||||
-- Compute CRC32, it could be necessary for make gzip format
|
||||
|
||||
-------------------------------------------------
|
||||
-- Below is more complex low level routines. --
|
||||
-------------------------------------------------
|
||||
|
||||
procedure Translate
|
||||
(Filter : in out Filter_Type;
|
||||
In_Data : in Ada.Streams.Stream_Element_Array;
|
||||
In_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode);
|
||||
-- Compress/decompress the In_Data buffer and place the result into
|
||||
-- Out_Data. In_Last is the index of last element from In_Data accepted by
|
||||
-- the Filter. Out_Last is the last element of the received data from
|
||||
-- Filter. To tell the filter that incoming data are complete put the
|
||||
-- Flush parameter to Finish.
|
||||
|
||||
function Stream_End (Filter : in Filter_Type) return Boolean;
|
||||
pragma Inline (Stream_End);
|
||||
-- Return the true when the stream is complete.
|
||||
|
||||
procedure Flush
|
||||
(Filter : in out Filter_Type;
|
||||
Out_Data : out Ada.Streams.Stream_Element_Array;
|
||||
Out_Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode);
|
||||
pragma Inline (Flush);
|
||||
-- Flushing the data from the compressor.
|
||||
|
||||
generic
|
||||
with procedure Write
|
||||
(Item : in Ada.Streams.Stream_Element_Array);
|
||||
-- User should provide this routine for accept
|
||||
-- compressed/decompressed data.
|
||||
|
||||
Buffer_Size : in Ada.Streams.Stream_Element_Offset
|
||||
:= Default_Buffer_Size;
|
||||
-- Buffer size for Write user routine.
|
||||
|
||||
procedure Write
|
||||
(Filter : in out Filter_Type;
|
||||
Item : in Ada.Streams.Stream_Element_Array;
|
||||
Flush : in Flush_Mode := No_Flush);
|
||||
-- Compress/Decompress data from Item to the generic parameter procedure
|
||||
-- Write. Output buffer size could be set in Buffer_Size generic parameter.
|
||||
|
||||
generic
|
||||
with procedure Read
|
||||
(Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset);
|
||||
-- User should provide data for compression/decompression
|
||||
-- thru this routine.
|
||||
|
||||
Buffer : in out Ada.Streams.Stream_Element_Array;
|
||||
-- Buffer for keep remaining data from the previous
|
||||
-- back read.
|
||||
|
||||
Rest_First, Rest_Last : in out Ada.Streams.Stream_Element_Offset;
|
||||
-- Rest_First have to be initialized to Buffer'Last + 1
|
||||
-- Rest_Last have to be initialized to Buffer'Last
|
||||
-- before usage.
|
||||
|
||||
Allow_Read_Some : in Boolean := False;
|
||||
-- Is it allowed to return Last < Item'Last before end of data.
|
||||
|
||||
procedure Read
|
||||
(Filter : in out Filter_Type;
|
||||
Item : out Ada.Streams.Stream_Element_Array;
|
||||
Last : out Ada.Streams.Stream_Element_Offset;
|
||||
Flush : in Flush_Mode := No_Flush);
|
||||
-- Compress/Decompress data from generic parameter procedure Read to the
|
||||
-- Item. User should provide Buffer and initialized Rest_First, Rest_Last
|
||||
-- indicators. If Allow_Read_Some is True, Read routines could return
|
||||
-- Last < Item'Last only at end of stream.
|
||||
|
||||
private
|
||||
|
||||
use Ada.Streams;
|
||||
|
||||
pragma Assert (Ada.Streams.Stream_Element'Size = 8);
|
||||
pragma Assert (Ada.Streams.Stream_Element'Modulus = 2**8);
|
||||
|
||||
type Flush_Mode is new Integer range 0 .. 5;
|
||||
|
||||
type Compression_Method is new Integer range 8 .. 8;
|
||||
|
||||
type Strategy_Type is new Integer range 0 .. 3;
|
||||
|
||||
No_Flush : constant Flush_Mode := 0;
|
||||
Partial_Flush : constant Flush_Mode := 1;
|
||||
Sync_Flush : constant Flush_Mode := 2;
|
||||
Full_Flush : constant Flush_Mode := 3;
|
||||
Finish : constant Flush_Mode := 4;
|
||||
Block_Flush : constant Flush_Mode := 5;
|
||||
|
||||
Filtered : constant Strategy_Type := 1;
|
||||
Huffman_Only : constant Strategy_Type := 2;
|
||||
RLE : constant Strategy_Type := 3;
|
||||
Default_Strategy : constant Strategy_Type := 0;
|
||||
|
||||
Deflated : constant Compression_Method := 8;
|
||||
|
||||
type Z_Stream;
|
||||
|
||||
type Z_Stream_Access is access all Z_Stream;
|
||||
|
||||
type Filter_Type is tagged limited record
|
||||
Strm : Z_Stream_Access;
|
||||
Compression : Boolean;
|
||||
Stream_End : Boolean;
|
||||
Header : Header_Type;
|
||||
CRC : Unsigned_32;
|
||||
Offset : Stream_Element_Offset;
|
||||
-- Offset for gzip header/footer output.
|
||||
end record;
|
||||
|
||||
end ZLib;
|
20
third_party/zlib/contrib/ada/zlib.gpr
vendored
20
third_party/zlib/contrib/ada/zlib.gpr
vendored
@ -1,20 +0,0 @@
|
||||
project Zlib is
|
||||
|
||||
for Languages use ("Ada");
|
||||
for Source_Dirs use (".");
|
||||
for Object_Dir use ".";
|
||||
for Main use ("test.adb", "mtest.adb", "read.adb", "buffer_demo");
|
||||
|
||||
package Compiler is
|
||||
for Default_Switches ("ada") use ("-gnatwcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst");
|
||||
end Compiler;
|
||||
|
||||
package Linker is
|
||||
for Default_Switches ("ada") use ("-lz");
|
||||
end Linker;
|
||||
|
||||
package Builder is
|
||||
for Default_Switches ("ada") use ("-s", "-gnatQ");
|
||||
end Builder;
|
||||
|
||||
end Zlib;
|
452
third_party/zlib/contrib/amd64/amd64-match.S
vendored
452
third_party/zlib/contrib/amd64/amd64-match.S
vendored
@ -1,452 +0,0 @@
|
||||
/*
|
||||
* match.S -- optimized version of longest_match()
|
||||
* based on the similar work by Gilles Vollant, and Brian Raiter, written 1998
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the BSD License. Use by owners of Che Guevarra
|
||||
* parafernalia is prohibited, where possible, and highly discouraged
|
||||
* elsewhere.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
# define match_init _match_init
|
||||
# define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define scanend ebx
|
||||
#define scanendw bx
|
||||
#define chainlenwmask edx /* high word: current chain len low word: s->wmask */
|
||||
#define curmatch rsi
|
||||
#define curmatchd esi
|
||||
#define windowbestlen r8
|
||||
#define scanalign r9
|
||||
#define scanalignd r9d
|
||||
#define window r10
|
||||
#define bestlen r11
|
||||
#define bestlend r11d
|
||||
#define scanstart r12d
|
||||
#define scanstartw r12w
|
||||
#define scan r13
|
||||
#define nicematch r14d
|
||||
#define limit r15
|
||||
#define limitd r15d
|
||||
#define prev rcx
|
||||
|
||||
/*
|
||||
* The 258 is a "magic number, not a parameter -- changing it
|
||||
* breaks the hell loose
|
||||
*/
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
#define LocalVarsSize (112)
|
||||
#define _chainlenwmask ( 8-LocalVarsSize)(%rsp)
|
||||
#define _windowbestlen (16-LocalVarsSize)(%rsp)
|
||||
#define save_r14 (24-LocalVarsSize)(%rsp)
|
||||
#define save_rsi (32-LocalVarsSize)(%rsp)
|
||||
#define save_rbx (40-LocalVarsSize)(%rsp)
|
||||
#define save_r12 (56-LocalVarsSize)(%rsp)
|
||||
#define save_r13 (64-LocalVarsSize)(%rsp)
|
||||
#define save_r15 (80-LocalVarsSize)(%rsp)
|
||||
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
/*
|
||||
* On AMD64 the first argument of a function (in our case -- the pointer to
|
||||
* deflate_state structure) is passed in %rdi, hence our offsets below are
|
||||
* all off of that.
|
||||
*/
|
||||
|
||||
/* you can check the structure offset by running
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "deflate.h"
|
||||
|
||||
void print_depl()
|
||||
{
|
||||
deflate_state ds;
|
||||
deflate_state *s=&ds;
|
||||
printf("size pointer=%u\n",(int)sizeof(void*));
|
||||
|
||||
printf("#define dsWSize (%3u)(%%rdi)\n",(int)(((char*)&(s->w_size))-((char*)s)));
|
||||
printf("#define dsWMask (%3u)(%%rdi)\n",(int)(((char*)&(s->w_mask))-((char*)s)));
|
||||
printf("#define dsWindow (%3u)(%%rdi)\n",(int)(((char*)&(s->window))-((char*)s)));
|
||||
printf("#define dsPrev (%3u)(%%rdi)\n",(int)(((char*)&(s->prev))-((char*)s)));
|
||||
printf("#define dsMatchLen (%3u)(%%rdi)\n",(int)(((char*)&(s->match_length))-((char*)s)));
|
||||
printf("#define dsPrevMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_match))-((char*)s)));
|
||||
printf("#define dsStrStart (%3u)(%%rdi)\n",(int)(((char*)&(s->strstart))-((char*)s)));
|
||||
printf("#define dsMatchStart (%3u)(%%rdi)\n",(int)(((char*)&(s->match_start))-((char*)s)));
|
||||
printf("#define dsLookahead (%3u)(%%rdi)\n",(int)(((char*)&(s->lookahead))-((char*)s)));
|
||||
printf("#define dsPrevLen (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_length))-((char*)s)));
|
||||
printf("#define dsMaxChainLen (%3u)(%%rdi)\n",(int)(((char*)&(s->max_chain_length))-((char*)s)));
|
||||
printf("#define dsGoodMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->good_match))-((char*)s)));
|
||||
printf("#define dsNiceMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->nice_match))-((char*)s)));
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
to compile for XCode 3.2 on MacOSX x86_64
|
||||
- run "gcc -g -c -DXCODE_MAC_X64_STRUCTURE amd64-match.S"
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CURRENT_LINX_XCODE_MAC_X64_STRUCTURE
|
||||
#define dsWSize ( 68)(%rdi)
|
||||
#define dsWMask ( 76)(%rdi)
|
||||
#define dsWindow ( 80)(%rdi)
|
||||
#define dsPrev ( 96)(%rdi)
|
||||
#define dsMatchLen (144)(%rdi)
|
||||
#define dsPrevMatch (148)(%rdi)
|
||||
#define dsStrStart (156)(%rdi)
|
||||
#define dsMatchStart (160)(%rdi)
|
||||
#define dsLookahead (164)(%rdi)
|
||||
#define dsPrevLen (168)(%rdi)
|
||||
#define dsMaxChainLen (172)(%rdi)
|
||||
#define dsGoodMatch (188)(%rdi)
|
||||
#define dsNiceMatch (192)(%rdi)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef STRUCT_OFFSET
|
||||
# define STRUCT_OFFSET (0)
|
||||
#endif
|
||||
|
||||
|
||||
#define dsWSize ( 56 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsWMask ( 64 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsWindow ( 72 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsPrev ( 88 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsMatchLen (136 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsPrevMatch (140 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsStrStart (148 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsMatchStart (152 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsLookahead (156 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsPrevLen (160 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsMaxChainLen (164 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsGoodMatch (180 + STRUCT_OFFSET)(%rdi)
|
||||
#define dsNiceMatch (184 + STRUCT_OFFSET)(%rdi)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
|
||||
longest_match:
|
||||
/*
|
||||
* Retrieve the function arguments. %curmatch will hold cur_match
|
||||
* throughout the entire function (passed via rsi on amd64).
|
||||
* rdi will hold the pointer to the deflate_state (first arg on amd64)
|
||||
*/
|
||||
mov %rsi, save_rsi
|
||||
mov %rbx, save_rbx
|
||||
mov %r12, save_r12
|
||||
mov %r13, save_r13
|
||||
mov %r14, save_r14
|
||||
mov %r15, save_r15
|
||||
|
||||
/* uInt wmask = s->w_mask; */
|
||||
/* unsigned chain_length = s->max_chain_length; */
|
||||
/* if (s->prev_length >= s->good_match) { */
|
||||
/* chain_length >>= 2; */
|
||||
/* } */
|
||||
|
||||
movl dsPrevLen, %eax
|
||||
movl dsGoodMatch, %ebx
|
||||
cmpl %ebx, %eax
|
||||
movl dsWMask, %eax
|
||||
movl dsMaxChainLen, %chainlenwmask
|
||||
jl LastMatchGood
|
||||
shrl $2, %chainlenwmask
|
||||
LastMatchGood:
|
||||
|
||||
/* chainlen is decremented once beforehand so that the function can */
|
||||
/* use the sign flag instead of the zero flag for the exit test. */
|
||||
/* It is then shifted into the high word, to make room for the wmask */
|
||||
/* value, which it will always accompany. */
|
||||
|
||||
decl %chainlenwmask
|
||||
shll $16, %chainlenwmask
|
||||
orl %eax, %chainlenwmask
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch, %eax
|
||||
movl dsLookahead, %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, %nicematch
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
mov dsWindow, %window
|
||||
movl dsStrStart, %limitd
|
||||
lea (%limit, %window), %scan
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
mov %scan, %scanalign
|
||||
negl %scanalignd
|
||||
andl $3, %scanalignd
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize, %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
xorl %ecx, %ecx
|
||||
subl %eax, %limitd
|
||||
cmovng %ecx, %limitd
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen, %bestlend
|
||||
|
||||
/* Store the sum of s->window + best_len in %windowbestlen locally, and in memory. */
|
||||
|
||||
lea (%window, %bestlen), %windowbestlen
|
||||
mov %windowbestlen, _windowbestlen
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
/* Posf *prev = s->prev; */
|
||||
|
||||
movzwl (%scan), %scanstart
|
||||
movzwl -1(%scan, %bestlen), %scanend
|
||||
mov dsPrev, %prev
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
movl %chainlenwmask, _chainlenwmask
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* do {
|
||||
* match = s->window + cur_match;
|
||||
* if (*(ushf*)(match+best_len-1) != scan_end ||
|
||||
* *(ushf*)match != scan_start) continue;
|
||||
* [...]
|
||||
* } while ((cur_match = prev[cur_match & wmask]) > limit
|
||||
* && --chain_length != 0);
|
||||
*
|
||||
* Here is the inner loop of the function. The function will spend the
|
||||
* majority of its time in this loop, and majority of that time will
|
||||
* be spent in the first ten instructions.
|
||||
*/
|
||||
LookupLoop:
|
||||
andl %chainlenwmask, %curmatchd
|
||||
movzwl (%prev, %curmatch, 2), %curmatchd
|
||||
cmpl %limitd, %curmatchd
|
||||
jbe LeaveNow
|
||||
subl $0x00010000, %chainlenwmask
|
||||
js LeaveNow
|
||||
LoopEntry: cmpw -1(%windowbestlen, %curmatch), %scanendw
|
||||
jne LookupLoop
|
||||
cmpw %scanstartw, (%window, %curmatch)
|
||||
jne LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
movl %chainlenwmask, _chainlenwmask
|
||||
|
||||
/* %scan is the string under scrutiny, and %prev to the string we */
|
||||
/* are hoping to match it up with. In actuality, %esi and %edi are */
|
||||
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
|
||||
/* initialized to -(MAX_MATCH_8 - scanalign). */
|
||||
|
||||
mov $(-MAX_MATCH_8), %rdx
|
||||
lea (%curmatch, %window), %windowbestlen
|
||||
lea MAX_MATCH_8(%windowbestlen, %scanalign), %windowbestlen
|
||||
lea MAX_MATCH_8(%scan, %scanalign), %prev
|
||||
|
||||
/* the prefetching below makes very little difference... */
|
||||
prefetcht1 (%windowbestlen, %rdx)
|
||||
prefetcht1 (%prev, %rdx)
|
||||
|
||||
/*
|
||||
* Test the strings for equality, 8 bytes at a time. At the end,
|
||||
* adjust %rdx so that it is offset to the exact byte that mismatched.
|
||||
*
|
||||
* It should be confessed that this loop usually does not represent
|
||||
* much of the total running time. Replacing it with a more
|
||||
* straightforward "rep cmpsb" would not drastically degrade
|
||||
* performance -- unrolling it, for example, makes no difference.
|
||||
*/
|
||||
|
||||
#undef USE_SSE /* works, but is 6-7% slower, than non-SSE... */
|
||||
|
||||
LoopCmps:
|
||||
#ifdef USE_SSE
|
||||
/* Preload the SSE registers */
|
||||
movdqu (%windowbestlen, %rdx), %xmm1
|
||||
movdqu (%prev, %rdx), %xmm2
|
||||
pcmpeqb %xmm2, %xmm1
|
||||
movdqu 16(%windowbestlen, %rdx), %xmm3
|
||||
movdqu 16(%prev, %rdx), %xmm4
|
||||
pcmpeqb %xmm4, %xmm3
|
||||
movdqu 32(%windowbestlen, %rdx), %xmm5
|
||||
movdqu 32(%prev, %rdx), %xmm6
|
||||
pcmpeqb %xmm6, %xmm5
|
||||
movdqu 48(%windowbestlen, %rdx), %xmm7
|
||||
movdqu 48(%prev, %rdx), %xmm8
|
||||
pcmpeqb %xmm8, %xmm7
|
||||
|
||||
/* Check the comparisions' results */
|
||||
pmovmskb %xmm1, %rax
|
||||
notw %ax
|
||||
bsfw %ax, %ax
|
||||
jnz LeaveLoopCmps
|
||||
|
||||
/* this is the only iteration of the loop with a possibility of having
|
||||
incremented rdx by 0x108 (each loop iteration add 16*4 = 0x40
|
||||
and (0x40*4)+8=0x108 */
|
||||
add $8, %rdx
|
||||
jz LenMaximum
|
||||
add $8, %rdx
|
||||
|
||||
|
||||
pmovmskb %xmm3, %rax
|
||||
notw %ax
|
||||
bsfw %ax, %ax
|
||||
jnz LeaveLoopCmps
|
||||
|
||||
|
||||
add $16, %rdx
|
||||
|
||||
|
||||
pmovmskb %xmm5, %rax
|
||||
notw %ax
|
||||
bsfw %ax, %ax
|
||||
jnz LeaveLoopCmps
|
||||
|
||||
add $16, %rdx
|
||||
|
||||
|
||||
pmovmskb %xmm7, %rax
|
||||
notw %ax
|
||||
bsfw %ax, %ax
|
||||
jnz LeaveLoopCmps
|
||||
|
||||
add $16, %rdx
|
||||
|
||||
jmp LoopCmps
|
||||
LeaveLoopCmps: add %rax, %rdx
|
||||
#else
|
||||
mov (%windowbestlen, %rdx), %rax
|
||||
xor (%prev, %rdx), %rax
|
||||
jnz LeaveLoopCmps
|
||||
|
||||
mov 8(%windowbestlen, %rdx), %rax
|
||||
xor 8(%prev, %rdx), %rax
|
||||
jnz LeaveLoopCmps8
|
||||
|
||||
mov 16(%windowbestlen, %rdx), %rax
|
||||
xor 16(%prev, %rdx), %rax
|
||||
jnz LeaveLoopCmps16
|
||||
|
||||
add $24, %rdx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
# if 0
|
||||
/*
|
||||
* This three-liner is tantalizingly simple, but bsf is a slow instruction,
|
||||
* and the complicated alternative down below is quite a bit faster. Sad...
|
||||
*/
|
||||
|
||||
LeaveLoopCmps: bsf %rax, %rax /* find the first non-zero bit */
|
||||
shrl $3, %eax /* divide by 8 to get the byte */
|
||||
add %rax, %rdx
|
||||
# else
|
||||
LeaveLoopCmps16:
|
||||
add $8, %rdx
|
||||
LeaveLoopCmps8:
|
||||
add $8, %rdx
|
||||
LeaveLoopCmps: testl $0xFFFFFFFF, %eax /* Check the first 4 bytes */
|
||||
jnz Check16
|
||||
add $4, %rdx
|
||||
shr $32, %rax
|
||||
Check16: testw $0xFFFF, %ax
|
||||
jnz LenLower
|
||||
add $2, %rdx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adc $0, %rdx
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
|
||||
/* then automatically accept it as the best possible match and leave. */
|
||||
|
||||
lea (%prev, %rdx), %rax
|
||||
sub %scan, %rax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
jge LenMaximum
|
||||
|
||||
/* If the length of the match is not longer than the best match we */
|
||||
/* have so far, then forget it and return to the lookup loop. */
|
||||
|
||||
cmpl %bestlend, %eax
|
||||
jg LongerMatch
|
||||
mov _windowbestlen, %windowbestlen
|
||||
mov dsPrev, %prev
|
||||
movl _chainlenwmask, %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch:
|
||||
movl %eax, %bestlend
|
||||
movl %curmatchd, dsMatchStart
|
||||
cmpl %nicematch, %eax
|
||||
jge LeaveNow
|
||||
|
||||
lea (%window, %bestlen), %windowbestlen
|
||||
mov %windowbestlen, _windowbestlen
|
||||
|
||||
movzwl -1(%scan, %rax), %scanend
|
||||
mov dsPrev, %prev
|
||||
movl _chainlenwmask, %chainlenwmask
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum:
|
||||
movl $MAX_MATCH, %bestlend
|
||||
movl %curmatchd, dsMatchStart
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl dsLookahead, %eax
|
||||
cmpl %eax, %bestlend
|
||||
cmovngl %bestlend, %eax
|
||||
LookaheadRet:
|
||||
|
||||
/* Restore the registers and return from whence we came. */
|
||||
|
||||
mov save_rsi, %rsi
|
||||
mov save_rbx, %rbx
|
||||
mov save_r12, %r12
|
||||
mov save_r13, %r13
|
||||
mov save_r14, %r14
|
||||
mov save_r15, %r15
|
||||
|
||||
ret
|
||||
|
||||
match_init: ret
|
51
third_party/zlib/contrib/asm686/README.686
vendored
51
third_party/zlib/contrib/asm686/README.686
vendored
@ -1,51 +0,0 @@
|
||||
This is a patched version of zlib, modified to use
|
||||
Pentium-Pro-optimized assembly code in the deflation algorithm. The
|
||||
files changed/added by this patch are:
|
||||
|
||||
README.686
|
||||
match.S
|
||||
|
||||
The speedup that this patch provides varies, depending on whether the
|
||||
compiler used to build the original version of zlib falls afoul of the
|
||||
PPro's speed traps. My own tests show a speedup of around 10-20% at
|
||||
the default compression level, and 20-30% using -9, against a version
|
||||
compiled using gcc 2.7.2.3. Your mileage may vary.
|
||||
|
||||
Note that this code has been tailored for the PPro/PII in particular,
|
||||
and will not perform particuarly well on a Pentium.
|
||||
|
||||
If you are using an assembler other than GNU as, you will have to
|
||||
translate match.S to use your assembler's syntax. (Have fun.)
|
||||
|
||||
Brian Raiter
|
||||
breadbox@muppetlabs.com
|
||||
April, 1998
|
||||
|
||||
|
||||
Added for zlib 1.1.3:
|
||||
|
||||
The patches come from
|
||||
http://www.muppetlabs.com/~breadbox/software/assembly.html
|
||||
|
||||
To compile zlib with this asm file, copy match.S to the zlib directory
|
||||
then do:
|
||||
|
||||
CFLAGS="-O3 -DASMV" ./configure
|
||||
make OBJA=match.o
|
||||
|
||||
|
||||
Update:
|
||||
|
||||
I've been ignoring these assembly routines for years, believing that
|
||||
gcc's generated code had caught up with it sometime around gcc 2.95
|
||||
and the major rearchitecting of the Pentium 4. However, I recently
|
||||
learned that, despite what I believed, this code still has some life
|
||||
in it. On the Pentium 4 and AMD64 chips, it continues to run about 8%
|
||||
faster than the code produced by gcc 4.1.
|
||||
|
||||
In acknowledgement of its continuing usefulness, I've altered the
|
||||
license to match that of the rest of zlib. Share and Enjoy!
|
||||
|
||||
Brian Raiter
|
||||
breadbox@muppetlabs.com
|
||||
April, 2007
|
357
third_party/zlib/contrib/asm686/match.S
vendored
357
third_party/zlib/contrib/asm686/match.S
vendored
@ -1,357 +0,0 @@
|
||||
/* match.S -- x86 assembly version of the zlib longest_match() function.
|
||||
* Optimized for the Intel 686 chips (PPro and later).
|
||||
*
|
||||
* Copyright (C) 1998, 2007 Brian Raiter <breadbox@muppetlabs.com>
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the author be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef NO_UNDERLINE
|
||||
#define match_init _match_init
|
||||
#define longest_match _longest_match
|
||||
#endif
|
||||
|
||||
#define MAX_MATCH (258)
|
||||
#define MIN_MATCH (3)
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
|
||||
|
||||
/* stack frame offsets */
|
||||
|
||||
#define chainlenwmask 0 /* high word: current chain len */
|
||||
/* low word: s->wmask */
|
||||
#define window 4 /* local copy of s->window */
|
||||
#define windowbestlen 8 /* s->window + bestlen */
|
||||
#define scanstart 16 /* first two bytes of string */
|
||||
#define scanend 12 /* last two bytes of string */
|
||||
#define scanalign 20 /* dword-misalignment of string */
|
||||
#define nicematch 24 /* a good enough match size */
|
||||
#define bestlen 28 /* size of best match so far */
|
||||
#define scan 32 /* ptr to string wanting match */
|
||||
|
||||
#define LocalVarsSize (36)
|
||||
/* saved ebx 36 */
|
||||
/* saved edi 40 */
|
||||
/* saved esi 44 */
|
||||
/* saved ebp 48 */
|
||||
/* return address 52 */
|
||||
#define deflatestate 56 /* the function arguments */
|
||||
#define curmatch 60
|
||||
|
||||
/* All the +zlib1222add offsets are due to the addition of fields
|
||||
* in zlib in the deflate_state structure since the asm code was first written
|
||||
* (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
|
||||
* (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
|
||||
* if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
|
||||
*/
|
||||
|
||||
#define zlib1222add (8)
|
||||
|
||||
#define dsWSize (36+zlib1222add)
|
||||
#define dsWMask (44+zlib1222add)
|
||||
#define dsWindow (48+zlib1222add)
|
||||
#define dsPrev (56+zlib1222add)
|
||||
#define dsMatchLen (88+zlib1222add)
|
||||
#define dsPrevMatch (92+zlib1222add)
|
||||
#define dsStrStart (100+zlib1222add)
|
||||
#define dsMatchStart (104+zlib1222add)
|
||||
#define dsLookahead (108+zlib1222add)
|
||||
#define dsPrevLen (112+zlib1222add)
|
||||
#define dsMaxChainLen (116+zlib1222add)
|
||||
#define dsGoodMatch (132+zlib1222add)
|
||||
#define dsNiceMatch (136+zlib1222add)
|
||||
|
||||
|
||||
.file "match.S"
|
||||
|
||||
.globl match_init, longest_match
|
||||
|
||||
.text
|
||||
|
||||
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
|
||||
.cfi_sections .debug_frame
|
||||
|
||||
longest_match:
|
||||
|
||||
.cfi_startproc
|
||||
/* Save registers that the compiler may be using, and adjust %esp to */
|
||||
/* make room for our stack frame. */
|
||||
|
||||
pushl %ebp
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_offset ebp, -8
|
||||
pushl %edi
|
||||
.cfi_def_cfa_offset 12
|
||||
pushl %esi
|
||||
.cfi_def_cfa_offset 16
|
||||
pushl %ebx
|
||||
.cfi_def_cfa_offset 20
|
||||
subl $LocalVarsSize, %esp
|
||||
.cfi_def_cfa_offset LocalVarsSize+20
|
||||
|
||||
/* Retrieve the function arguments. %ecx will hold cur_match */
|
||||
/* throughout the entire function. %edx will hold the pointer to the */
|
||||
/* deflate_state structure during the function's setup (before */
|
||||
/* entering the main loop). */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl curmatch(%esp), %ecx
|
||||
|
||||
/* uInt wmask = s->w_mask; */
|
||||
/* unsigned chain_length = s->max_chain_length; */
|
||||
/* if (s->prev_length >= s->good_match) { */
|
||||
/* chain_length >>= 2; */
|
||||
/* } */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl dsGoodMatch(%edx), %ebx
|
||||
cmpl %ebx, %eax
|
||||
movl dsWMask(%edx), %eax
|
||||
movl dsMaxChainLen(%edx), %ebx
|
||||
jl LastMatchGood
|
||||
shrl $2, %ebx
|
||||
LastMatchGood:
|
||||
|
||||
/* chainlen is decremented once beforehand so that the function can */
|
||||
/* use the sign flag instead of the zero flag for the exit test. */
|
||||
/* It is then shifted into the high word, to make room for the wmask */
|
||||
/* value, which it will always accompany. */
|
||||
|
||||
decl %ebx
|
||||
shll $16, %ebx
|
||||
orl %eax, %ebx
|
||||
movl %ebx, chainlenwmask(%esp)
|
||||
|
||||
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
|
||||
|
||||
movl dsNiceMatch(%edx), %eax
|
||||
movl dsLookahead(%edx), %ebx
|
||||
cmpl %eax, %ebx
|
||||
jl LookaheadLess
|
||||
movl %eax, %ebx
|
||||
LookaheadLess: movl %ebx, nicematch(%esp)
|
||||
|
||||
/* register Bytef *scan = s->window + s->strstart; */
|
||||
|
||||
movl dsWindow(%edx), %esi
|
||||
movl %esi, window(%esp)
|
||||
movl dsStrStart(%edx), %ebp
|
||||
lea (%esi,%ebp), %edi
|
||||
movl %edi, scan(%esp)
|
||||
|
||||
/* Determine how many bytes the scan ptr is off from being */
|
||||
/* dword-aligned. */
|
||||
|
||||
movl %edi, %eax
|
||||
negl %eax
|
||||
andl $3, %eax
|
||||
movl %eax, scanalign(%esp)
|
||||
|
||||
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
|
||||
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
|
||||
|
||||
movl dsWSize(%edx), %eax
|
||||
subl $MIN_LOOKAHEAD, %eax
|
||||
subl %eax, %ebp
|
||||
jg LimitPositive
|
||||
xorl %ebp, %ebp
|
||||
LimitPositive:
|
||||
|
||||
/* int best_len = s->prev_length; */
|
||||
|
||||
movl dsPrevLen(%edx), %eax
|
||||
movl %eax, bestlen(%esp)
|
||||
|
||||
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
|
||||
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
|
||||
/* register ush scan_start = *(ushf*)scan; */
|
||||
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
|
||||
/* Posf *prev = s->prev; */
|
||||
|
||||
movzwl (%edi), %ebx
|
||||
movl %ebx, scanstart(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl %ebx, scanend(%esp)
|
||||
movl dsPrev(%edx), %edi
|
||||
|
||||
/* Jump into the main loop. */
|
||||
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LoopEntry
|
||||
|
||||
.balign 16
|
||||
|
||||
/* do {
|
||||
* match = s->window + cur_match;
|
||||
* if (*(ushf*)(match+best_len-1) != scan_end ||
|
||||
* *(ushf*)match != scan_start) continue;
|
||||
* [...]
|
||||
* } while ((cur_match = prev[cur_match & wmask]) > limit
|
||||
* && --chain_length != 0);
|
||||
*
|
||||
* Here is the inner loop of the function. The function will spend the
|
||||
* majority of its time in this loop, and majority of that time will
|
||||
* be spent in the first ten instructions.
|
||||
*
|
||||
* Within this loop:
|
||||
* %ebx = scanend
|
||||
* %ecx = curmatch
|
||||
* %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
|
||||
* %esi = windowbestlen - i.e., (window + bestlen)
|
||||
* %edi = prev
|
||||
* %ebp = limit
|
||||
*/
|
||||
LookupLoop:
|
||||
andl %edx, %ecx
|
||||
movzwl (%edi,%ecx,2), %ecx
|
||||
cmpl %ebp, %ecx
|
||||
jbe LeaveNow
|
||||
subl $0x00010000, %edx
|
||||
js LeaveNow
|
||||
LoopEntry: movzwl -1(%esi,%ecx), %eax
|
||||
cmpl %ebx, %eax
|
||||
jnz LookupLoop
|
||||
movl window(%esp), %eax
|
||||
movzwl (%eax,%ecx), %eax
|
||||
cmpl scanstart(%esp), %eax
|
||||
jnz LookupLoop
|
||||
|
||||
/* Store the current value of chainlen. */
|
||||
|
||||
movl %edx, chainlenwmask(%esp)
|
||||
|
||||
/* Point %edi to the string under scrutiny, and %esi to the string we */
|
||||
/* are hoping to match it up with. In actuality, %esi and %edi are */
|
||||
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
|
||||
/* initialized to -(MAX_MATCH_8 - scanalign). */
|
||||
|
||||
movl window(%esp), %esi
|
||||
movl scan(%esp), %edi
|
||||
addl %ecx, %esi
|
||||
movl scanalign(%esp), %eax
|
||||
movl $(-MAX_MATCH_8), %edx
|
||||
lea MAX_MATCH_8(%edi,%eax), %edi
|
||||
lea MAX_MATCH_8(%esi,%eax), %esi
|
||||
|
||||
/* Test the strings for equality, 8 bytes at a time. At the end,
|
||||
* adjust %edx so that it is offset to the exact byte that mismatched.
|
||||
*
|
||||
* We already know at this point that the first three bytes of the
|
||||
* strings match each other, and they can be safely passed over before
|
||||
* starting the compare loop. So what this code does is skip over 0-3
|
||||
* bytes, as much as necessary in order to dword-align the %edi
|
||||
* pointer. (%esi will still be misaligned three times out of four.)
|
||||
*
|
||||
* It should be confessed that this loop usually does not represent
|
||||
* much of the total running time. Replacing it with a more
|
||||
* straightforward "rep cmpsb" would not drastically degrade
|
||||
* performance.
|
||||
*/
|
||||
LoopCmps:
|
||||
movl (%esi,%edx), %eax
|
||||
xorl (%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps
|
||||
movl 4(%esi,%edx), %eax
|
||||
xorl 4(%edi,%edx), %eax
|
||||
jnz LeaveLoopCmps4
|
||||
addl $8, %edx
|
||||
jnz LoopCmps
|
||||
jmp LenMaximum
|
||||
LeaveLoopCmps4: addl $4, %edx
|
||||
LeaveLoopCmps: testl $0x0000FFFF, %eax
|
||||
jnz LenLower
|
||||
addl $2, %edx
|
||||
shrl $16, %eax
|
||||
LenLower: subb $1, %al
|
||||
adcl $0, %edx
|
||||
|
||||
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
|
||||
/* then automatically accept it as the best possible match and leave. */
|
||||
|
||||
lea (%edi,%edx), %eax
|
||||
movl scan(%esp), %edi
|
||||
subl %edi, %eax
|
||||
cmpl $MAX_MATCH, %eax
|
||||
jge LenMaximum
|
||||
|
||||
/* If the length of the match is not longer than the best match we */
|
||||
/* have so far, then forget it and return to the lookup loop. */
|
||||
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
cmpl %ebx, %eax
|
||||
jg LongerMatch
|
||||
movl windowbestlen(%esp), %esi
|
||||
movl dsPrev(%edx), %edi
|
||||
movl scanend(%esp), %ebx
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* s->match_start = cur_match; */
|
||||
/* best_len = len; */
|
||||
/* if (len >= nice_match) break; */
|
||||
/* scan_end = *(ushf*)(scan+best_len-1); */
|
||||
|
||||
LongerMatch: movl nicematch(%esp), %ebx
|
||||
movl %eax, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
cmpl %ebx, %eax
|
||||
jge LeaveNow
|
||||
movl window(%esp), %esi
|
||||
addl %eax, %esi
|
||||
movl %esi, windowbestlen(%esp)
|
||||
movzwl -1(%edi,%eax), %ebx
|
||||
movl dsPrev(%edx), %edi
|
||||
movl %ebx, scanend(%esp)
|
||||
movl chainlenwmask(%esp), %edx
|
||||
jmp LookupLoop
|
||||
|
||||
/* Accept the current string, with the maximum possible length. */
|
||||
|
||||
LenMaximum: movl deflatestate(%esp), %edx
|
||||
movl $MAX_MATCH, bestlen(%esp)
|
||||
movl %ecx, dsMatchStart(%edx)
|
||||
|
||||
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
|
||||
/* return s->lookahead; */
|
||||
|
||||
LeaveNow:
|
||||
movl deflatestate(%esp), %edx
|
||||
movl bestlen(%esp), %ebx
|
||||
movl dsLookahead(%edx), %eax
|
||||
cmpl %eax, %ebx
|
||||
jg LookaheadRet
|
||||
movl %ebx, %eax
|
||||
LookaheadRet:
|
||||
|
||||
/* Restore the stack and return from whence we came. */
|
||||
|
||||
addl $LocalVarsSize, %esp
|
||||
.cfi_def_cfa_offset 20
|
||||
popl %ebx
|
||||
.cfi_def_cfa_offset 16
|
||||
popl %esi
|
||||
.cfi_def_cfa_offset 12
|
||||
popl %edi
|
||||
.cfi_def_cfa_offset 8
|
||||
popl %ebp
|
||||
.cfi_def_cfa_offset 4
|
||||
.cfi_endproc
|
||||
match_init: ret
|
8
third_party/zlib/contrib/blast/Makefile
vendored
8
third_party/zlib/contrib/blast/Makefile
vendored
@ -1,8 +0,0 @@
|
||||
blast: blast.c blast.h
|
||||
cc -DTEST -o blast blast.c
|
||||
|
||||
test: blast
|
||||
blast < test.pk | cmp - test.txt
|
||||
|
||||
clean:
|
||||
rm -f blast blast.o
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user