2
0
mirror of https://github.com/rehlds/rehlds.git synced 2024-12-26 14:45:44 +03:00

Merge remote-tracking branch 'upstream/master' into flood-fix

This commit is contained in:
Sergey Shorokhov 2021-10-07 11:32:25 +03:00
commit 6e1829f660
286 changed files with 3904 additions and 11923 deletions

300
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,300 @@
name: C/C++ CI
on:
push:
branches: [master]
paths-ignore:
- '**.md'
pull_request:
types: [opened, reopened, synchronize]
release:
types: [published]
jobs:
windows:
name: 'Windows'
runs-on: windows-latest
env:
solution: 'msvc/ReHLDS.sln'
buildPlatform: 'Win32'
buildRelease: 'Release'
buildReleasePlay: 'Release Play'
buildTest: 'Test Fixes'
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1.0.2
- name: Build and Run unittests
run: |
msbuild ${{ env.solution }} -p:Configuration="${{ env.buildTest }}" /t:Clean,Build /p:Platform=${{ env.buildPlatform }} /p:PlatformToolset=v140_xp /p:XPDeprecationWarning=false
.\"msvc\Test Fixes\swds.exe"
If ($LASTEXITCODE -ne 0 -And
$LASTEXITCODE -ne 3)
{[Environment]::Exit(1)}
shell: "pwsh"
- name: Build
run: |
msbuild ${{ env.solution }} -p:Configuration="${{ env.buildRelease }}" /t:Clean,Build /p:Platform=${{ env.buildPlatform }} /p:PlatformToolset=v140_xp /p:XPDeprecationWarning=false
msbuild ${{ env.solution }} -p:Configuration="${{ env.buildReleasePlay }}" /t:Clean,Build /p:Platform=${{ env.buildPlatform }} /p:PlatformToolset=v140_xp /p:XPDeprecationWarning=false
- name: Move files
run: |
mkdir publish\debug
mkdir publish\tests
mkdir publish\bin\win32\valve\dlls
move "msvc\${{ env.buildReleasePlay }}\swds.dll" publish\tests\swds.dll
move msvc\${{ env.buildRelease }}\hlds.exe publish\bin\win32\hlds.exe
move msvc\${{ env.buildRelease }}\hltv.exe publish\bin\win32\hltv.exe
move msvc\${{ env.buildRelease }}\swds.dll publish\bin\win32\swds.dll
move msvc\${{ env.buildRelease }}\core.dll publish\bin\win32\core.dll
move msvc\${{ env.buildRelease }}\proxy.dll publish\bin\win32\proxy.dll
move msvc\${{ env.buildRelease }}\demoplayer.dll publish\bin\win32\demoplayer.dll
move msvc\${{ env.buildRelease }}\filesystem_stdio.dll publish\bin\win32\filesystem_stdio.dll
move msvc\${{ env.buildRelease }}\director.dll publish\bin\win32\valve\dlls\director.dll
move msvc\${{ env.buildRelease }}\hlds.pdb publish\debug\hlds.pdb
move msvc\${{ env.buildRelease }}\hltv.pdb publish\debug\hltv.pdb
move msvc\${{ env.buildRelease }}\swds.pdb publish\debug\swds.pdb
move msvc\${{ env.buildRelease }}\core.pdb publish\debug\core.pdb
move msvc\${{ env.buildRelease }}\proxy.pdb publish\debug\proxy.pdb
move msvc\${{ env.buildRelease }}\demoplayer.pdb publish\debug\demoplayer.pdb
move msvc\${{ env.buildRelease }}\filesystem_stdio.pdb publish\debug\filesystem_stdio.pdb
move msvc\${{ env.buildRelease }}\director.pdb publish\debug\director.pdb
- name: Deploy artifacts
uses: actions/upload-artifact@v2
with:
name: win32
path: publish/*
testdemos:
name: 'Test demos'
runs-on: ubuntu-latest
container: s1lentq/testdemos:latest
needs: [windows]
env:
WINEDEBUG: -all
WINEDLLOVERRIDES: mshtml=
defaults:
run:
shell: bash
working-directory: ../../../opt/HLDS
steps:
- name: Deploying windows artifacts
uses: actions/download-artifact@v2
with:
name: win32
- name: Play demos
run: |
chown root ~
rsync -a deps/rehlds/* .
mv $GITHUB_WORKSPACE/tests/swds.dll .
descs=(
"CS: Multiplayer"
"Half-Life: Physics singleplayer"
"Half-Life: Multiplayer on crossfire map"
"Half-Life: Shooting with several weapons"
)
demos=(
"cstrike-muliplayer-1"
"rehlds-phys-single1"
"crossfire-1-multiplayer-1"
"shooting-hl-1"
)
retVal=0
for i in "${!demos[@]}"; do
params=$(cat "testdemos/${demos[i]}.params")
echo -e "\e[1m[$((i + 1))/${#demos[@]}] \e[1;36m${descs[i]} testing...\e[0m"
echo -e " - \e[0;33mParameters $params\e[0m"
wine hlds.exe --rehlds-enable-all-hooks --rehlds-test-play "testdemos/${demos[i]}.bin" $params &> result.log || retVal=$?
if [ $retVal -ne 777 ] && [ $retVal -ne 9 ]; then
# Print with catchy messages
while read line; do
echo -e " \e[0;33m$line"
done <<< $(cat result.log | sed '0,/demo failed/I!d;/wine:/d;/./,$!d')
echo " 🔸 🔸 🔸 🔸 🔸 🔸 🔸 🔸 🔸 🔸"
while read line; do
echo -e " \e[1;31m$line";
done < rehlds_demo_error.txt
echo -e " \e[30;41mExit code: $retVal\e[0m"
echo -e "\e[1m[$((i + 1))/${#demos[@]}] \e[1;36m${descs[i]} testing...\e[1;31m Failed ❌"
exit 6 # Test demo failed
else
# Print result HLDS console
while read line; do
echo -e " \e[0;33m$line"
done <<< $(cat result.log | sed '/wine:/d;/./,$!d')
echo -e " \e[30;43mExit code: $retVal\e[0m"
echo -e "\e[1m[$((i + 1))/${#demos[@]}] \e[1;36m${descs[i]} testing...\e[1;32m Succeed ✔"
fi
done
linux:
name: 'Linux'
runs-on: ubuntu-latest
container: s1lentq/linux86buildtools:latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Build and Run unittests
run: |
rm -rf build && CC=icc CXX=icpc cmake -DCMAKE_BUILD_TYPE=Unittests -B build && cmake --build build -j8
retVal=0
export LD_LIBRARY_PATH="rehlds/lib/linux32:$LD_LIBRARY_PATH"
./build/rehlds/engine_i486 2> /dev/null > result.log || retVal=$?
while read line; do
if [[ ${line} == *"Warning in test"* ]] ; then
echo -e "\e[2;38m$line"
elif [[ ${line} == *"Failure in test"* ]] ; then
echo -e "\e[1;31m$line"
else
echo -e "\e[0;33m$line"
fi
done <<< $(cat result.log)
if [ $retVal -ne 0 ] && [ $retVal -ne 3 ]; then
echo -e "\e[30;41mExit code: $retVal\e[0m"
exit 1 # Unittest failed
else
echo -e "\e[30;43mExit code: $retVal\e[0m"
fi
shell: bash
- name: Build using Intel C++ Compiler
run: |
rm -rf build && CC=icc CXX=icpc cmake -B build && cmake --build build -j8
- name: Prepare HLSDK
run: |
mkdir -p publish/hlsdk
rsync -a rehlds/common/ publish/hlsdk/common/
rsync -a rehlds/dlls/ publish/hlsdk/dlls/
rsync -a rehlds/pm_shared/ publish/hlsdk/pm_shared/
rsync -a rehlds/public/ publish/hlsdk/public/ --exclude rehlds/
rsync -a rehlds/public/rehlds/ publish/hlsdk/engine
- name: Move files
run: |
mkdir -p publish/bin/linux32/valve/dlls
mv build/rehlds/engine_i486.so publish/bin/linux32/engine_i486.so
mv rehlds/version/appversion.h publish/appversion.h
mv build/rehlds/dedicated/hlds_linux publish/bin/linux32/hlds_linux
mv build/rehlds/HLTV/Console/hltv publish/bin/linux32/hltv
mv build/rehlds/HLTV/Core/core.so publish/bin/linux32/core.so
mv build/rehlds/HLTV/Proxy/proxy.so publish/bin/linux32/proxy.so
mv build/rehlds/HLTV/DemoPlayer/demoplayer.so publish/bin/linux32/demoplayer.so
mv build/rehlds/HLTV/Director/director.so publish/bin/linux32/valve/dlls/director.so
mv build/rehlds/filesystem/FileSystem_Stdio/filesystem_stdio.so publish/bin/linux32/filesystem_stdio.so
- name: Run GLIBC/ABI version compat test
run: |
binaries=(
"publish/bin/linux32/engine_i486.so"
"publish/bin/linux32/hlds_linux"
"publish/bin/linux32/hltv"
"publish/bin/linux32/core.so"
"publish/bin/linux32/proxy.so"
"publish/bin/linux32/demoplayer.so"
"publish/bin/linux32/valve/dlls/director.so"
"publish/bin/linux32/filesystem_stdio.so"
)
bash ./rehlds/version/glibc_test.sh ${binaries[@]}
if [[ $? -ne 0 ]]; then
exit 1 # Assertion failed
fi
shell: bash
- name: Deploy artifacts
uses: actions/upload-artifact@v2
id: upload-job
with:
name: linux32
path: publish/*
- name: Cleanup temporary artifacts
if: success() && steps.upload-job.outcome == 'success'
run: |
rm -rf hlsdk
rm -f appversion.h
publish:
name: 'Publish'
runs-on: ubuntu-latest
needs: [windows, testdemos, linux]
steps:
- name: Deploying linux artifacts
uses: actions/download-artifact@v2
with:
name: linux32
- name: Deploying windows artifacts
uses: actions/download-artifact@v2
with:
name: win32
- name: Reading appversion.h
run: |
if [ -e appversion.h ]; then
APP_VERSION=$(cat appversion.h | grep -wi '#define APP_VERSION_STRD' | sed -e 's/#define APP_VERSION_STRD[ \t\r\n\v\f]\+\(.*\)/\1/i' -e 's/\r//g')
if [ $? -ne 0 ]; then
APP_VERSION=""
else
# Remove quotes
APP_VERSION=$(echo $APP_VERSION | xargs)
echo "APP_VERSION=${APP_VERSION}" >> $GITHUB_ENV
fi
fi
rm -f appversion.h
- name: Packaging bin/dbg
id: packaging-job
if: |
github.event_name == 'release' &&
github.event.action == 'published' &&
startsWith(github.ref, 'refs/tags/')
run: |
7z a -tzip rehlds-bin-${{ env.APP_VERSION }}.zip bin/linux32/ hlsdk/
7z a -t7z -m0=lzma2 -mx=9 -mfb=64 -aoa rehlds-dbg-${{ env.APP_VERSION }}.7z debug/
- name: Publish artifacts
uses: softprops/action-gh-release@v1
id: publish-job
if: |
startsWith(github.ref, 'refs/tags/') &&
steps.packaging-job.outcome == 'success'
with:
files: |
*.zip
*.7z
env:
GITHUB_TOKEN: ${{ secrets.API_TOKEN }}
- name: Cleanup temporary artifacts
if: success() && steps.publish-job.outcome == 'success'
run: |
rm -rf bin debug hlsdk
rm -f *.7z *.zip appversion.h

6
.gitignore vendored
View File

@ -1,10 +1,9 @@
**/build
**/.gradle
.idea
*.iml
*.bat
*.log
*.lnk
*.aps
**/msvc/Debug*
**/msvc/Release*
**/msvc/Tests
@ -21,6 +20,3 @@
**/msvc/ipch
rehlds/version/appversion.h
rehlds/_rehldsTestImg
rehlds/_dev
publish

18
CMakeLists.txt Normal file
View File

@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.1)
project(rehlds CXX)
if (WIN32)
message(FATAL_ERROR "CMakeLists.txt Windows platform isn't supported yet. Use msvc/ReHLDS.sln instead it!")
endif()
add_custom_target(appversion DEPENDS
COMMAND "${PROJECT_SOURCE_DIR}/rehlds/version/appversion.sh" "${PROJECT_SOURCE_DIR}"
)
add_subdirectory(rehlds)
if (NOT CMAKE_BUILD_TYPE MATCHES Unittests)
add_subdirectory(rehlds/dedicated)
add_subdirectory(rehlds/filesystem)
add_subdirectory(rehlds/HLTV)
endif()

126
README.md
View File

@ -1,5 +1,4 @@
# Rehlds [![Build Status](http://teamcity.rehlds.org/app/rest/builds/buildType:(id:Rehlds_Publish)/statusIcon)](http://teamcity.rehlds.org/viewType.html?buildTypeId=Rehlds_Publish&guest=1) [![Download](https://camo.githubusercontent.com/65c70643ec7b40eea50971003624c2fb04d8d375/687474703a2f2f7265686c64732e6f72672f76657273696f6e2f7265686c64732e737667)](http://teamcity.rehlds.org/guestAuth/downloadArtifacts.html?buildTypeId=Rehlds_Publish&buildId=lastSuccessful)
# ReHLDS [![C/C++ CI](https://github.com/dreamstalker/rehlds/actions/workflows/build.yml/badge.svg)](https://github.com/dreamstalker/rehlds/actions/workflows/build.yml) [![Download](https://camo.githubusercontent.com/7ab483250adb4037b26e9575331218ee51108190d0938b7836d32f1209ccf907/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f647265616d7374616c6b65722f7265686c64732e737667)](https://github.com/dreamstalker/rehlds/releases/latest) [![Downloads](https://camo.githubusercontent.com/d37654956d99bb9fb7a348fdac39b214d6ae14a7cfb9f96bf873c6b46cdf9ef6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f646f776e6c6f6164732f647265616d7374616c6b65722f7265686c64732f746f74616c3f636f6c6f723d696d706f7274616e74)]() [![Percentage of issues still open](http://isitmaintained.com/badge/open/dreamstalker/rehlds.svg)](http://isitmaintained.com/project/dreamstalker/rehlds "Percentage of issues still open") [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) <img align="right" src="https://user-images.githubusercontent.com/5860435/111066129-040e5e00-84f0-11eb-9e1f-7a7e8611da2b.png" alt="ReHLDS" />
Reverse-engineered (and bugfixed) HLDS
## What is this?
@ -7,7 +6,7 @@ ReHLDS is a result of reverse engineering of original HLDS (build 6152/6153) usi
Along with reverse engineering, a lot of defects and (potential) bugs were found and fixed
You can try play on one of the servers that using rehlds: http://www.gametracker.com/search/?search_by=server_variable&search_by2=sv_version
You can try play on one of the servers that using rehlds: [Game Tracker](http://www.gametracker.com/search/?search_by=server_variable&search_by2=sv_version)
## Goals of the project
<ul>
@ -16,23 +15,21 @@ You can try play on one of the servers that using rehlds: http://www.gametracker
</ul>
## How can use it?
Rehlds is fully compatible with latest official HLDS downloaded by steamcmd. All you have to do is to download rehlds binaries and replace original swds.dll/engine_i486.so. For windows you can also copy a swds.pdb file with a debug information.
<br /><b>Warning!</b> Rehlds is not compatible with an old 5xxx or below platforms downloaded by hldsupdatetool.
ReHLDS is fully compatible with latest official HLDS downloaded by steamcmd. All you have to do is to download rehlds binaries and replace original swds.dll/engine_i486.so. For windows you can also copy a swds.pdb file with a debug information.
<br /><b>Warning!</b> ReHLDS is not compatible with an old 5xxx or below platforms downloaded by hldsupdatetool.
Compiled binaries are available here: http://nexus.rehlds.org/nexus/content/repositories/rehlds-dev/rehlds/rehlds/
## Downloads
* [Release builds](https://github.com/dreamstalker/rehlds/releases)
* [Dev builds](https://github.com/dreamstalker/rehlds/actions/workflows/build.yml)
Rehlds binaries require SSE, SSE2 and SSE3 instruction sets to run and can benefit from SSE4.1 and SSE4.2.
ReHLDS binaries require `SSE`, `SSE2` and `SSE3` instruction sets to run and can benefit from `SSE4.1` and `SSE4.2`
Archive's bin directory contains 2 subdirectories, 'bugfixed' and 'pure'
<ul>
<li>'pure' version is designed to work exactly as official hlds engine</li>
<li>'bugfixed' version contains some fixes and improvements</li>
</ul>
<b>Warning!</b> Rehlds is not binary compatible with original hlds since it's compiled with compilers other than ones used for original hlds. This means that plugins that do binary code analysis (Orpheu for example) probably will not work with rehlds.
<b>Warning!</b> ReHLDS is not binary compatible with original hlds since it's compiled with compilers other than ones used for original hlds.
This means that plugins that do binary code analysis (Orpheu for example) probably will not work with rehlds.
## Configuring
Bugfixed version of rehlds contains an additional cvars:
<details>
<summary>Click to expand</summary>
<ul>
<li>listipcfgfile <filename> // File for permanent ip bans. Default: listip.cfg
<li>syserror_logfile <filename> // File for the system error log. Default: sys_error.log
@ -56,66 +53,81 @@ Bugfixed version of rehlds contains an additional cvars:
<li>sv_rehlds_attachedentities_playeranimationspeed_fix // Fixes bug with gait animation speed increase when player has some attached entities (aiments). Can cause animation lags when cl_updaterate is low. Default: 0
<li>sv_rehlds_maxclients_from_single_ip // Limit number of connections from the single ip address. Default: 5
<li>sv_use_entity_file // Use custom entity file for a map. Path to an entity file will be "maps/[map name].ent". 0 - use original entities. 1 - use .ent files from maps directory. 2 - use .ent files from maps directory and create new .ent file if not exist.
<li>sv_usercmd_custom_random_seed // When enabled server will populate an additional random seed independent of the client. Default: 0
</ul>
</details>
## Commands
Bugfixed version of rehlds contains an additional commands:
<ul>
<li>rescount // Prints the total count of precached resources in the server console
<li>reslist &lt;sound | model | decal | generic | event&gt; // Separately prints the details of the precached resources for sounds, models, decals, generic and events in server console. Useful for managing resources and dealing with the goldsource precache limits.
</ul>
## Build instructions
There are several software requirements for building rehlds:
<ol>
<li>Java Development Kit (JDK) 7+ (http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)</li>
<li>For Windows: Visual Studio 2013 and later</li>
<li>For Linux: Intel C++ Compiler 13 and later or GCC 4.9.2 or later (some earlier versions might work too)</li>
</ol>
### Checking requirements
#### JDK version
Windows<pre>&gt; %JAVA_HOME%\bin\javac -version
javac 1.8.0_25
There are several software requirements for building rehlds:
#### Windows
<pre>
Visual Studio 2015 (C++14 standard) and later
</pre>
Linux
<pre>$ javac -version
javac 1.7.0_65
</pre>
#### Visual Studio
Help -> About
#### ICC
<pre>$ icc --version
icc (ICC) 15.0.1 20141023
</pre>
#### GCC
<pre>$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
#### Linux
<pre>
cmake >= 3.10
GCC >= 4.9.2 (Optional)
ICC >= 15.0.1 20141023 (Optional)
LLVM (Clang) >= 6.0 (Optional)
</pre>
### Building
On Windows:
<pre>gradlew --max-workers=1 clean buildRelease</pre>
* For faster building without unit tests use this:exclamation:
<pre>gradlew --max-workers=1 clean buildFixes</pre>
<b>NOTE:</b> You can also use `Visual Studio` to build, just select from the solution configurations list `Release Swds` or `Debug Swds`<br />
On Linux (ICC):
<pre>./gradlew --max-workers=1 clean buildRelease</pre>
* For faster building without unit tests use this:exclamation:
<pre>./gradlew --max-workers=1 clean buildFixes</pre>
#### Windows
Use `Visual Studio` to build, open `msvc/ReHLDS.sln` and just select from the solution configurations list `Release Swds` or `Debug Swds`
On Linux (GCC):
<pre>./gradlew --max-workers=1 -PuseGcc clean buildRelease</pre>
* For faster building without unit tests use this:exclamation:
<pre>./gradlew --max-workers=1 -PuseGcc clean buildFixes</pre>
#### Linux
Also there is a task `buildEngine`, it builds only engine, without other parts of the project.<br />
Compiled binaries will be placed in the rehlds/build/binaries/ directory
* Optional options using `build.sh --compiler=[gcc] --jobs=[N] -D[option]=[ON or OFF]` (without square brackets)
<pre>
-c=|--compiler=[icc|gcc|clang] - Select preferred C/C++ compiler to build
-j=|--jobs=[N] - Specifies the number of jobs (commands) to run simultaneously (For faster building)
<sub>Definitions (-D)</sub>
DEBUG - Enables debugging mode
USE_STATIC_LIBSTDC - Enables static linking library libstdc++
</pre>
* ICC <pre>./build.sh --compiler=intel</pre>
* LLVM (Clang) <pre>./build.sh --compiler=clang</pre>
* GCC <pre>./build.sh --compiler=gcc</pre>
##### Checking build environment (Debian / Ubuntu)
<details>
<summary>Click to expand</summary>
<ul>
<li>
Installing required packages
<pre>
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y gcc-multilib g++-multilib
sudo apt-get install -y build-essential
sudo apt-get install -y libc6-dev libc6-dev-i386
</pre>
</li>
<li>
Select the preferred C/C++ Compiler installation
<pre>
1) sudo apt-get install -y gcc g++
2) sudo apt-get install -y clang
</pre>
</li>
</ul>
</details>
## How can I help the project?
Just install it on your game server and report problems you faced.

View File

@ -1,55 +0,0 @@
import versioning.GitVersioner
import versioning.RehldsVersionInfo
import org.joda.time.DateTime
apply plugin: 'maven-publish'
apply from: 'shared.gradle'
group = 'rehlds'
apply plugin: 'idea'
idea {
project {
languageLevel = 'JDK_1_7'
}
}
def gitInfo = GitVersioner.versionForDir(project.rootDir)
RehldsVersionInfo versionInfo
if (gitInfo && gitInfo.tag && gitInfo.tag[0] == 'v') {
def m = gitInfo.tag =~ /^v(\d+)\.(\d+)(\.(\d+))?$/
if (!m.find()) {
throw new RuntimeException("Invalid git version tag name ${gitInfo.tag}")
}
versionInfo = new RehldsVersionInfo(
majorVersion: m.group(1) as int,
minorVersion: m.group(2) as int,
maintenanceVersion: m.group(4) ? (m.group(4) as int) : null,
localChanges: gitInfo.localChanges,
commitDate: gitInfo.commitDate,
commitSHA: gitInfo.commitSHA,
commitURL: gitInfo.commitURL
)
} else {
versionInfo = new RehldsVersionInfo(
majorVersion: project.majorVersion as int,
minorVersion: project.minorVersion as int,
maintenanceVersion: project.maintenanceVersion as int,
suffix: 'dev',
localChanges: gitInfo ? gitInfo.localChanges : true,
commitDate: gitInfo ? gitInfo.commitDate : new DateTime(),
commitSHA: gitInfo ? gitInfo.commitSHA : "",
commitURL: gitInfo ? gitInfo.commitURL : "",
commitCount: gitInfo ? (gitInfo.commitCount as int) : null
)
}
project.ext.rehldsVersionInfo = versionInfo
project.version = versionInfo.asMavenVersion()
apply from: 'publish.gradle'
task wrapper(type: Wrapper) {
gradleVersion = '2.4'
}

60
build.sh Executable file
View File

@ -0,0 +1,60 @@
#!/bin/bash
main()
{
CC=gcc
CXX=g++
if [[ "$*" =~ "--help" ]]; then
help
exit 0;
fi
n=0
args=()
for i in "$@"
do
case $i in
-j=*|--jobs=*)
jobs="-j${i#*=}"
shift
;;
-c=*|--compiler=*)
C="${i#*=}"
shift
;;
*)
args[$n]="$i"
((++n))
;;
esac
done
case "$C" in
("intel"|"icc") CC=icc CXX=icpc ;;
("gcc"|"g++") CC=gcc CXX=g++ ;;
("clang|llvm") CC=clang CXX=clang++ ;;
*)
;;
esac
rm -rf build
mkdir build
pushd build &> /dev/null
CC=$CC CXX=$CXX cmake ${args[@]} ..
make ${jobs}
popd > /dev/null
}
help()
{
printf "Usage: ./build.sh <options>\n\n"
printf " -c= | --compiler=<icc|gcc|clang> - Select preferred C/C++ compiler to build\n"
printf " -j= | --jobs=<N> - Specifies the number of jobs (commands) to run simultaneously (For faster building)\n\n"
}
# Initialize
main $*
# Exit normally
exit 0

View File

@ -1,27 +0,0 @@
apply plugin: 'groovy'
repositories {
//mavenLocal()
mavenCentral()
maven {
url 'http://nexus.rehlds.org/nexus/content/repositories/rehlds-releases/'
}
maven {
url 'http://nexus.rehlds.org/nexus/content/repositories/rehlds-snapshots/'
}
maven {
url 'http://nexus.rehlds.org/nexus/content/repositories/rehlds-dev/'
}
}
dependencies {
compile gradleApi()
compile localGroovy()
compile 'commons-io:commons-io:2.4'
compile 'commons-lang:commons-lang:2.6'
compile 'joda-time:joda-time:2.7'
compile 'org.doomedsociety.gradlecpp:gradle-cpp-plugin:1.2'
compile 'org.eclipse.jgit:org.eclipse.jgit:3.7.0.201502260915-r'
compile 'org.apache.velocity:velocity:1.7'
}

View File

@ -1,58 +0,0 @@
package dirsync.builder
import dirsync.model.tree.DirectoryNode
import dirsync.model.tree.FileNode
import groovy.transform.CompileStatic
class FileSystemTreeBuilder {
@CompileStatic
private static FileNode<File> buildNodeForFile(File file, DirectoryNode<File> parent) {
if (parent.getChildren(file.name)) {
throw new RuntimeException("Parent dir ${parent.name} already contains child node ${file.name}");
}
return new FileNode(
name: file.name,
lastModifiedDate: file.lastModified(),
data: file,
parent: parent,
size: file.size()
);
}
@CompileStatic
private static DirectoryNode<File> buildNodeForDirectoryRecursive(File dir, DirectoryNode<File> parent) {
if (!dir.isDirectory()) {
throw new RuntimeException("File ${dir.absolutePath} is not a directory")
}
if (parent != null && parent.getChildren(dir.name)) {
throw new RuntimeException("Parent dir ${parent.name} already contains child node ${dir.name}");
}
DirectoryNode<File> thisNode = new DirectoryNode(
name: dir.name,
lastModifiedDate: dir.lastModified(),
data: dir,
parent: parent
);
dir.eachFile { File f ->
if (f.isDirectory()) {
thisNode.childNodes[f.name] = buildNodeForDirectoryRecursive(f, thisNode)
} else {
thisNode.childNodes[f.name] = buildNodeForFile(f, thisNode)
}
}
return thisNode;
}
static DirectoryNode<File> buildFileSystemTree(File rootDir) {
def root = buildNodeForDirectoryRecursive(rootDir, null);
PostBuildPass.doPostBuild(root)
return root
}
}

View File

@ -1,60 +0,0 @@
package dirsync.builder
import dirsync.model.tree.DirectoryNode
import dirsync.model.tree.FileNode
class FileTreeMerger {
private static <T> void mergeContentsRecursive(DirectoryNode<T> newParent, DirectoryNode<T> toMerge) {
toMerge.childNodes.each { cn ->
def node = cn.value
def existingNode = newParent.childNodes[node.name]
if (existingNode) {
if (!(existingNode instanceof DirectoryNode) || !(node instanceof DirectoryNode))
throw new RuntimeException("Failed to merge non-directory nodes ${node.fullPath}")
def existingDirNode = existingNode as DirectoryNode<T>
def dirNode = node as DirectoryNode<T>
existingDirNode.lastModifiedDate = Math.max(existingDirNode.lastModifiedDate, dirNode.lastModifiedDate)
mergeContentsRecursive(existingDirNode, dirNode)
} else {
if (node instanceof DirectoryNode) {
def dirNode = node as DirectoryNode<T>
def newNode = new DirectoryNode<T>(
name: dirNode.name,
data: dirNode.data,
parent: newParent,
lastModifiedDate: dirNode.lastModifiedDate
)
newParent.childNodes[node.name] = newNode
mergeContentsRecursive(newNode, dirNode)
} else {
FileNode<T> fileNode = node as FileNode<T>
FileNode<T> newNode = new FileNode<T>(
name: fileNode.name,
data: fileNode.data,
parent: newParent,
lastModifiedDate: fileNode.lastModifiedDate,
size: fileNode.size
)
newParent.childNodes[node.name] = newNode
}
}
}
}
public static <T> DirectoryNode<T> mergeTrees(DirectoryNode<T> tree1, DirectoryNode<T> tree2) {
DirectoryNode<T> newRoot = new DirectoryNode<T>(
name: tree1.name ?: tree2.name
)
mergeContentsRecursive(newRoot, tree1)
mergeContentsRecursive(newRoot, tree2)
PostBuildPass.doPostBuild(newRoot)
return newRoot
}
}

View File

@ -1,22 +0,0 @@
package dirsync.builder
import dirsync.model.tree.DirectoryNode
class PostBuildPass {
private static <T> void postProcessRecursive(DirectoryNode<T> dir) {
dir.childNodes.each { cne ->
def childNode = cne.value
childNode.fullPath = dir.fullPath ? dir.fullPath + '/' + childNode.name : childNode.name
if (childNode instanceof DirectoryNode) {
def childDirNode = childNode as DirectoryNode<T>
postProcessRecursive(childDirNode)
}
}
}
static <T> void doPostBuild(DirectoryNode<T> root) {
root.fullPath = ''
postProcessRecursive(root)
}
}

View File

@ -1,53 +0,0 @@
package dirsync.builder
import dirsync.model.tree.DirectoryNode
import dirsync.model.tree.FileNode
import dirsync.model.tree.ZipData
import java.util.zip.ZipFile
class ZipTreeBuilder {
static DirectoryNode<ZipData> buildForZipArchive(String zipArchive, ZipFile zf) {
DirectoryNode<ZipData> root = new DirectoryNode<>()
zf.entries().each { ze ->
def path = ze.name.replace('\\', '/')
if (path.endsWith('/'))
path = path.substring(0, path.length() - 1)
def parentPath = path.contains('/') ? path.substring(0, path.lastIndexOf('/')) : ''
def childPath = path.contains('/') ? path.substring(path.lastIndexOf('/') + 1) : path
def parentNode = (DirectoryNode<ZipData>) root.getByPath(parentPath)
if (parentNode == null)
throw new RuntimeException("Error reading ${zipArchive}: could not find parent path ${parentPath} for path ${path}")
def childNode = parentNode.getChildren(childPath)
if (childNode)
throw new RuntimeException("Error reading ${zipArchive}: duplicate path ${path}")
if (ze.directory) {
childNode = new DirectoryNode<ZipData>(
name: childPath,
lastModifiedDate: ze.time,
data: new ZipData(zipEntryName: ze.name, zipArchiveName: zipArchive),
parent: parentNode
);
} else {
childNode = new FileNode<ZipData>(
name: childPath,
lastModifiedDate: ze.time,
data: new ZipData(zipEntryName: ze.name, zipArchiveName: zipArchive),
parent: parentNode,
size: ze.size
);
}
parentNode.childNodes[childPath] = childNode
//println '' + ze.directory + ' ' + ze.name + ' ' + parentPath + ' ' + childPath
}
PostBuildPass.doPostBuild(root)
return root
}
}

View File

@ -1,97 +0,0 @@
package dirsync.merger
import dirsync.model.synccmd.AbstractSyncCmd
import dirsync.model.synccmd.CopyDirCmd
import dirsync.model.synccmd.CopyFileCmd
import dirsync.model.synccmd.DeleteDirCmd
import dirsync.model.synccmd.DeleteFileCmd
import dirsync.model.synccmd.ReplaceFileCmd
import dirsync.model.tree.DirectoryNode
import dirsync.model.tree.FileNode
import groovy.transform.TypeChecked
@TypeChecked
class FileTreeComparator {
private static <T, U> void mergeDirsRecursive(DirectoryNode<T> left, DirectoryNode<U> right, List<AbstractSyncCmd<T, U>> diffs) {
// left => right
left.childNodes.each { le ->
def leftNode = le.value
def rightNode = right.childNodes[leftNode.name]
if (rightNode == null) {
switch (leftNode) {
case DirectoryNode:
def leftDirNode = leftNode as DirectoryNode<T>
diffs << new CopyDirCmd<>(src: leftDirNode, dstParentDir: right)
break
case FileNode:
def leftFileNode = leftNode as FileNode<T>
diffs << new CopyFileCmd<>(src: leftFileNode, dstDir: right)
break
default:
throw new RuntimeException("Invalid node class ${leftNode.class.name}")
}
return
}
if (rightNode.class != leftNode.class) {
throw new RuntimeException("node classes mismatch: ${leftNode.class.name} != ${rightNode.class.name}")
}
switch (rightNode) {
case DirectoryNode:
def leftDirNode = leftNode as DirectoryNode<T>
def rightDirNode = rightNode as DirectoryNode<U>
mergeDirsRecursive(leftDirNode, rightDirNode, diffs)
break
case FileNode:
def leftFileNode = leftNode as FileNode<T>
def rightFileNode = rightNode as FileNode<T>
if (leftFileNode.size != rightFileNode.size || leftFileNode.lastModifiedDate != rightFileNode.lastModifiedDate) {
diffs << new ReplaceFileCmd<>(src: leftFileNode, dst: rightFileNode)
}
break
default:
throw new RuntimeException("Invalid node class ${rightNode.class.name}")
}
} // ~left => right
//right => left
right.childNodes.each { re ->
def rightNode = re.value
def leftNode = left.childNodes[rightNode.name]
if (leftNode != null) {
return //already processed in left => right
}
switch (rightNode) {
case DirectoryNode:
def rightDirNode = rightNode as DirectoryNode<U>
diffs << new DeleteDirCmd<>(dirNode: rightDirNode)
break
case FileNode:
def rightFileNode = rightNode as FileNode<T>
diffs << new DeleteFileCmd<>(node: rightFileNode)
break
default:
throw new RuntimeException("Invalid node class ${rightNode.class.name}")
}
} // ~right => left
}
static <T, U> List<AbstractSyncCmd<T, U>> mergeTrees(DirectoryNode<T> leftRoot, DirectoryNode<U> rightRoot) {
List<AbstractSyncCmd<T, U>> res = []
mergeDirsRecursive(leftRoot, rightRoot, res)
return res
}
}

View File

@ -1,103 +0,0 @@
package dirsync.merger
import dirsync.model.synccmd.AbstractSyncCmd
import dirsync.model.synccmd.CopyDirCmd
import dirsync.model.synccmd.CopyFileCmd
import dirsync.model.synccmd.DeleteDirCmd
import dirsync.model.synccmd.DeleteFileCmd
import dirsync.model.synccmd.ReplaceFileCmd
import dirsync.model.tree.DirectoryNode
import dirsync.model.tree.FileNode
import dirsync.model.tree.TreePhysMapper
import groovy.transform.TypeChecked
import org.apache.commons.io.IOUtils
@TypeChecked
public class FileTreeDiffApplier {
static <T, U> void copyDirRecursive(DirectoryNode<T> src, TreePhysMapper<T> srcMapper, TreePhysMapper<U> dstMapper) {
dstMapper.createDirectory(src.fullPath)
src.childNodes.each { ce ->
def childNode = ce.value
def childPath = childNode.fullPath
switch (childNode) {
case FileNode:
srcMapper.fileContent(childNode.data).withStream { InputStream inStream ->
dstMapper.createFile(childPath).withStream { OutputStream outStream ->
IOUtils.copy(inStream, outStream)
}
dstMapper.setFileLastUpdatedDate(childPath, childNode.lastModifiedDate)
}
break;
case DirectoryNode:
copyDirRecursive(childNode as DirectoryNode<T>, srcMapper, dstMapper)
break;
default:
throw new RuntimeException("Invalid node class: ${childNode.class.name}")
}
}
}
static <T, U> void handleCopyFile(CopyFileCmd<T, U> fileCopy, TreePhysMapper<T> srcMapper, TreePhysMapper<U> dstMapper) {
def dstPath = fileCopy.dstDir.fullPath ? fileCopy.dstDir.fullPath + '/' + fileCopy.src.name : fileCopy.src.name
srcMapper.fileContent(fileCopy.src.data).withStream { InputStream inStream ->
dstMapper.createFile(dstPath).withStream { OutputStream outStream ->
IOUtils.copy(inStream, outStream)
}
dstMapper.setFileLastUpdatedDate(dstPath, fileCopy.src.lastModifiedDate)
}
}
static <T, U> void handleDeleteDir(DeleteDirCmd<T, U> delDir, TreePhysMapper<T> srcMapper, TreePhysMapper<U> dstMapper) {
dstMapper.removeDirectory(delDir.dirNode.fullPath)
}
static <T, U> void handleDeleteFile(DeleteFileCmd<T, U> delFile, TreePhysMapper<T> srcMapper, TreePhysMapper<U> dstMapper) {
dstMapper.removeFile(delFile.node.fullPath)
}
static <T, U> void handleReplaceFile(ReplaceFileCmd<T, U> replaceFile, TreePhysMapper<T> srcMapper, TreePhysMapper<U> dstMapper) {
dstMapper.removeFile(replaceFile.dst.fullPath)
srcMapper.fileContent(replaceFile.src.data).withStream { InputStream inStream ->
dstMapper.createFile(replaceFile.dst.fullPath).withStream { OutputStream outStream ->
IOUtils.copy(inStream, outStream)
}
dstMapper.setFileLastUpdatedDate(replaceFile.dst.fullPath, replaceFile.src.lastModifiedDate)
}
}
static <T, U> void applyDiffs(List<AbstractSyncCmd<T, U>> diffs, TreePhysMapper<T> srcMapper, TreePhysMapper<U> dstMapper) {
diffs.each { diff ->
switch (diff) {
case CopyDirCmd:
def copyDir = diff as CopyDirCmd<T, U>
copyDirRecursive(copyDir.src, srcMapper, dstMapper)
break
case CopyFileCmd:
handleCopyFile(diff as CopyFileCmd<T, U>, srcMapper, dstMapper)
break
case DeleteDirCmd:
handleDeleteDir(diff as DeleteDirCmd<T, U>, srcMapper, dstMapper)
break
case DeleteFileCmd:
handleDeleteFile(diff as DeleteFileCmd<T, U>, srcMapper, dstMapper)
break
case ReplaceFileCmd:
handleReplaceFile(diff as ReplaceFileCmd<T, U>, srcMapper, dstMapper)
break
default:
throw new RuntimeException("Invalid diff command ${diff.class.name}")
}
}
}
}

View File

@ -1,4 +0,0 @@
package dirsync.model.synccmd
class AbstractSyncCmd<T, U> {
}

View File

@ -1,8 +0,0 @@
package dirsync.model.synccmd
import dirsync.model.tree.DirectoryNode
class CopyDirCmd<T, U> extends AbstractSyncCmd<T, U> {
DirectoryNode<T> src
DirectoryNode<U> dstParentDir
}

View File

@ -1,9 +0,0 @@
package dirsync.model.synccmd
import dirsync.model.tree.DirectoryNode
import dirsync.model.tree.FileNode
class CopyFileCmd<T, U> extends AbstractSyncCmd<T, U> {
FileNode<T> src
DirectoryNode<U> dstDir
}

View File

@ -1,7 +0,0 @@
package dirsync.model.synccmd
import dirsync.model.tree.DirectoryNode
class DeleteDirCmd<T, U> extends AbstractSyncCmd<T, U> {
DirectoryNode<U> dirNode
}

View File

@ -1,7 +0,0 @@
package dirsync.model.synccmd
import dirsync.model.tree.FileNode
class DeleteFileCmd<T, U> extends AbstractSyncCmd<T, U> {
FileNode<U> node
}

View File

@ -1,8 +0,0 @@
package dirsync.model.synccmd
import dirsync.model.tree.FileNode
class ReplaceFileCmd<T, U> extends AbstractSyncCmd<T, U> {
FileNode<T> src
FileNode<U> dst
}

View File

@ -1,27 +0,0 @@
package dirsync.model.tree
import groovy.transform.CompileStatic
@CompileStatic
abstract class AbstractFileTreeNode<T> {
DirectoryNode<T> parent
String name
String fullPath
long lastModifiedDate
T data
boolean equals(o) {
if (this.is(o)) return true
if (getClass() != o.class) return false
AbstractFileTreeNode that = (AbstractFileTreeNode) o
if (name != that.name) return false
return true
}
int hashCode() {
return (name != null ? name.hashCode() : 0)
}
}

View File

@ -1,42 +0,0 @@
package dirsync.model.tree
import groovy.transform.CompileStatic
@CompileStatic
class DirectoryNode<T> extends AbstractFileTreeNode<T> {
Map<String, AbstractFileTreeNode<T>> childNodes = new HashMap<>()
AbstractFileTreeNode<T> getChildren(String name) {
return childNodes[name];
}
AbstractFileTreeNode<T> getChildren(String[] names, int idx) {
if (idx == names.length)
return this
AbstractFileTreeNode<T> c = childNodes[names[idx]]
if (c == null)
return null
if (c instanceof DirectoryNode) {
def d = (DirectoryNode<T>) c;
return d.getChildren(names, idx + 1)
}
return null;
}
AbstractFileTreeNode<T> getByPath(String path) {
path = path.replace('\\', '/')
if (path.endsWith('/'))
path = path.substring(0, path.length() - 1)
if (path.empty) {
return this
}
String[] components = path.split('/')
return getChildren(components, 0)
}
}

View File

@ -1,50 +0,0 @@
package dirsync.model.tree
class FSMapper extends TreePhysMapper<File> {
final File root
FSMapper(File root) {
this.root = root
}
@Override
InputStream fileContent(File file) {
return file.newDataInputStream()
}
@Override
void createDirectory(String dir) {
def target = new File(root, dir)
if (!target.mkdirs()) {
throw new RuntimeException("Failed to create directory ${target.absolutePath}")
}
}
@Override
void removeDirectory(String dir) {
def target = new File(root, dir)
if (!target.deleteDir()) {
throw new RuntimeException("Failed to delete directory ${target.absolutePath}")
}
}
@Override
void removeFile(String path) {
def target = new File(root, path)
if (!target.delete()) {
throw new RuntimeException("Failed to delete file ${target.absolutePath}")
}
}
@Override
OutputStream createFile(String path) {
def target = new File(root, path)
return target.newOutputStream()
}
@Override
void setFileLastUpdatedDate(String path, long date) {
def target = new File(root, path)
target.setLastModified(date)
}
}

View File

@ -1,8 +0,0 @@
package dirsync.model.tree
import groovy.transform.CompileStatic
@CompileStatic
class FileNode<T> extends AbstractFileTreeNode<T> {
long size
}

View File

@ -1,11 +0,0 @@
package dirsync.model.tree
abstract class TreePhysMapper<T> {
abstract InputStream fileContent(T file)
abstract void createDirectory(String dir)
abstract void removeDirectory(String dir)
abstract void removeFile(String path)
abstract OutputStream createFile(String path)
abstract void setFileLastUpdatedDate(String path, long date)
}

View File

@ -1,9 +0,0 @@
package dirsync.model.tree
import groovy.transform.CompileStatic
@CompileStatic
class ZipData {
String zipEntryName
String zipArchiveName
}

View File

@ -1,72 +0,0 @@
package dirsync.model.tree
import dirsync.builder.FileTreeMerger
import dirsync.builder.ZipTreeBuilder
import sun.reflect.generics.reflectiveObjects.NotImplementedException
import java.util.zip.ZipFile
public class ZipTreeMapper extends TreePhysMapper<ZipData> implements Closeable {
Map<String, ZipFile> zipArchives = [:]
void addZipArchive(String zipArchive) {
zipArchives[zipArchive] = new ZipFile(zipArchive)
}
DirectoryNode<ZipData> buildFileTree() {
def root = new DirectoryNode<ZipData>()
zipArchives.each { ze ->
def zipTree = ZipTreeBuilder.buildForZipArchive(ze.key, ze.value)
root = FileTreeMerger.mergeTrees(root, zipTree)
}
return root
}
@Override
void close() throws IOException {
zipArchives.each { ze ->
try { ze.value.close() } catch (Exception ignored) { }
}
}
@Override
InputStream fileContent(ZipData file) {
def archive = zipArchives[file.zipArchiveName]
if (!archive) {
throw new RuntimeException("Archive ${file.zipArchiveName} is not loaded");
}
def zipEntry = archive.getEntry(file.zipEntryName)
if (!zipEntry) {
throw new RuntimeException("File ${file.zipEntryName} not found in archive ${file.zipArchiveName}");
}
return archive.getInputStream(zipEntry)
}
@Override
void createDirectory(String dir) {
throw new NotImplementedException()
}
@Override
void removeDirectory(String dir) {
throw new NotImplementedException()
}
@Override
void removeFile(String path) {
throw new NotImplementedException()
}
@Override
OutputStream createFile(String path) {
throw new NotImplementedException()
}
@Override
void setFileLastUpdatedDate(String path, long date) {
throw new NotImplementedException()
}
}

View File

@ -1,19 +0,0 @@
package gradlecpp
import org.gradle.api.Project
import org.gradle.nativeplatform.NativeBinarySpec
class CppUnitTestExtension {
Project _project
CppUnitTestExtension(Project p) {
_project = p
}
void eachTestExecutable(Closure action) {
_project.binaries.each { NativeBinarySpec bin ->
if (!bin.hasProperty('cppUnitTestsExecutable')) return
action(bin)
}
}
}

View File

@ -1,256 +0,0 @@
package gradlecpp
import gradlecpp.teamcity.TeamCityIntegration
import org.gradle.api.Action
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.internal.project.AbstractProject
import org.gradle.model.internal.core.DirectNodeModelAction
import org.gradle.model.internal.core.ModelActionRole
import org.gradle.model.internal.core.ModelPath
import org.gradle.model.internal.core.ModelReference
import org.gradle.model.internal.core.MutableModelNode
import org.gradle.model.internal.core.rule.describe.ModelRuleDescriptor
import org.gradle.model.internal.core.rule.describe.SimpleModelRuleDescriptor
import org.gradle.model.internal.registry.ModelRegistry
import org.gradle.nativeplatform.NativeBinarySpec
import org.gradle.nativeplatform.NativeLibrarySpec
import org.gradle.nativeplatform.internal.AbstractNativeBinarySpec
import org.doomedsociety.gradlecpp.GradleCppUtils
class CppUnitTestPlugin implements Plugin<Project> {
private static class TestExecStatus {
boolean successful
boolean warning
int exitCode
String output
long durationMsec
String cmdLine
String execDir
}
static void onBinariesCreated(Project p, String desc, Closure action) {
ModelRegistry mr = (p as AbstractProject).getModelRegistry()
def modelPath = ModelPath.path("binaries")
ModelRuleDescriptor ruleDescriptor = new SimpleModelRuleDescriptor(desc);
mr.configure(ModelActionRole.Finalize, DirectNodeModelAction.of(ModelReference.of(modelPath), ruleDescriptor, new Action<MutableModelNode>() {
@Override
void execute(MutableModelNode node) {
action()
}
}))
}
@Override
void apply(Project project) {
project.extensions.create('cppUnitTest', CppUnitTestExtension, project)
onBinariesCreated(project, 'CppUnitTestPlugin::AttachUnitTest', {
processCppUnitTests(project)
})
}
/**
* Attaches test tasks to C/C++ libraries build tasks
*/
static void processCppUnitTests(Project p) {
//println "processCppUnitTests::afterEvaluate on ${p.name}: project type is ${p.projectType}"
p.binaries.all { NativeBinarySpec bin ->
if (!(bin.component instanceof NativeLibrarySpec)) {
return
}
def testComponentName = bin.component.name + '_tests'
Collection<NativeBinarySpec> testCandidates = p.binaries.matching { it.component.name == testComponentName && bin.buildType == it.buildType && bin.flavor == it.flavor }
if (testCandidates.size() > 1) {
throw new GradleException("Found >1 test candidates for library ${bin.component.name} in project ${p}: ${testCandidates}")
} else if (!testCandidates.empty) {
def testBinary = testCandidates.first()
GradleCppUtils.onTasksCreated(p, 'CppUnitTestPlugin::AttachUnitTestTask', {
attachTestTaskToCppLibrary(bin, testBinary)
})
String testTaskName = bin.namingScheme.getTaskName('unitTest')
bin.ext.cppUnitTestTask = testTaskName
} else {
throw new GradleException("No tests found for library ${bin.component.name} in project ${p}")
}
}
}
static TestExecStatus runTestExecutable(NativeBinarySpec testSubject, String executable, List<String> params, String phase, int timeout) {
def execFile = new File(executable)
def outDir = new File(testSubject.buildTask.project.buildDir, "tests/${testSubject.name}/run")
outDir.mkdirs()
def outPath = new File(outDir, "${phase}.log")
def cmdParams = [];
cmdParams << execFile.absolutePath
cmdParams.addAll(params)
def execDir = execFile.parentFile
def pb = new ProcessBuilder(cmdParams).redirectErrorStream(true).directory(execDir)
if (!GradleCppUtils.windows) {
pb.environment().put('LD_LIBRARY_PATH', '.')
}
def sout = new StringBuffer()
long startTime = System.currentTimeMillis()
def p = pb.start()
p.consumeProcessOutput(sout, sout)
p.waitForOrKill(timeout * 1000)
long endTime = System.currentTimeMillis()
int exitVal = p.exitValue()
outPath.withWriter('UTF-8') { writer ->
writer.write(sout.toString())
}
return new TestExecStatus(
exitCode: exitVal,
successful: (exitVal == 0 || exitVal == 3),
warning: (exitVal == 3),
output: sout.toString(),
durationMsec: endTime - startTime,
cmdLine: cmdParams.join(' '),
execDir: execDir.absolutePath
)
}
static void dumpTestExecStatus(TestExecStatus stat) {
if (!stat) {
println "Execution of test executable failed"
}
println "Test executable command: ${stat.cmdLine}"
println "Test executable run directury: ${stat.execDir}"
println "Test executable exit code: ${stat.exitCode}"
println "Test executable output BEGIN"
println stat.output
println "Test executable output END"
}
static void attachTestTaskToCppLibrary(NativeBinarySpec libBin, NativeBinarySpec testExecBin) {
Project p = libBin.buildTask.project
def libBinImpl = libBin as AbstractNativeBinarySpec
def libLinkTask = GradleCppUtils.getLinkTask(libBin)
def testExecLinkTask = GradleCppUtils.getLinkTask(testExecBin)
// collect all output files from library and test executable
def depFiles = []
depFiles.addAll(libLinkTask.outputs.files.files)
depFiles.addAll(testExecLinkTask.outputs.files.files)
//create 'tests' task
def testTaskName = libBinImpl.namingScheme.getTaskName('unitTest')
def testTask = p.task(testTaskName, { Task testTask ->
//output dir
def testResDir = new File(p.buildDir, "tests/${libBin.name}")
//inputs/outputs for up-to-date check
testTask.outputs.dir testResDir
testTask.inputs.files depFiles
//dependencies on library and test executable
testTask.dependsOn libLinkTask
testTask.dependsOn testExecLinkTask
// binary build depends on unit test
libBin.buildTask.dependsOn testTask
// extra project-specific dependencies
def testDepsTask = p.tasks.findByName('testDeps')
if (testDepsTask != null) {
testTask.dependsOn testDepsTask
}
// task actions
testTask.doLast {
//temporary file that store info about all tests (XML)
File allTests = File.createTempFile('j4s-testinfo', 'data')
allTests.deleteOnExit()
//fill file with test info
print "Fetching test info..."
def getTestsStatus = runTestExecutable(libBin, testExecBin.executableFile.absolutePath, ['-writeTestInfo', allTests.absolutePath], '__getTests', 5000)
if (!getTestsStatus.successful) {
println " Failed"
dumpTestExecStatus(getTestsStatus)
throw new GradleException("Unable to fetch test names")
}
println " OK"
getTestsStatus = null // allow GC to collect it
// parse the test info file
def root = new XmlSlurper().parse(allTests)
// run all tests
println "Running ${root.test.size()} tests..."
TeamCityIntegration.suiteStarted("unitTests.${libBin.name}")
int failCount = 0;
int warnCount = 0;
root.test.list().each { testInfo ->
def testName = '' + testInfo.@name.text()
def testGroup = '' + testInfo.@group.text()
def testTimeout = ('' + testInfo.@timeout.text()) as int
if (!TeamCityIntegration.writeOutput) {
print " ${testGroup}-${testName}..."
System.out.flush()
}
TeamCityIntegration.testStarted("${testGroup}-${testName}")
def testExecStatus = runTestExecutable(libBin, testExecBin.executableFile.absolutePath, ['-runTest', testGroup, testName], "${testGroup}-${testName}", testTimeout)
if (!testExecStatus.successful) {
if (!TeamCityIntegration.writeOutput) {
println " Failed"
}
TeamCityIntegration.testFailed("${testGroup}-${testName}", "test executable return code is ${testExecStatus.exitCode}", "test executable return code is ${testExecStatus.exitCode}")
dumpTestExecStatus(testExecStatus)
failCount++
} else {
if (!TeamCityIntegration.writeOutput) {
if (testExecStatus.warning) {
println " WARNING"
dumpTestExecStatus(testExecStatus)
warnCount++
}
else
println " OK"
}
}
TeamCityIntegration.testStdOut("${testGroup}-${testName}", testExecStatus.output)
TeamCityIntegration.testFinished("${testGroup}-${testName}", testExecStatus.durationMsec)
}
TeamCityIntegration.suiteFinished("unitTests.${libBin.name}")
if (failCount) {
throw new GradleException("CPP unit tests: ${failCount} tests failed");
}
else if (warnCount) {
println "CPP unit tests: ${warnCount} tests warnings";
}
}
})
}
}

View File

@ -1,17 +0,0 @@
package gradlecpp
import org.gradle.api.Plugin
import org.gradle.api.Project
class RehldsPlayTestPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.configurations {
rehlds_playtest_image
}
project.dependencies {
rehlds_playtest_image 'rehlds.testimg:testimg:0.2'
}
}
}

View File

@ -1,80 +0,0 @@
package gradlecpp
import gradlecpp.teamcity.TeamCityIntegration
import org.apache.commons.lang.SystemUtils
import org.gradle.api.DefaultTask
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.TaskAction
import org.gradle.nativeplatform.NativeBinarySpec
import rehlds.testdemo.RehldsDemoRunner
import rehlds.testdemo.RehldsTestParser
class RehldsPlayTestTask extends DefaultTask {
def FileCollection testDemos
def Closure postExtractAction
def File rehldsImageRoot
def File rehldsTestLogs
def NativeBinarySpec testFor
@TaskAction
def doPlay() {
if (!SystemUtils.IS_OS_WINDOWS) {
return
}
if (!testDemos) {
println 'RehldsPlayTestTask: no demos attached to the testDemos property'
}
rehldsImageRoot.mkdirs()
rehldsTestLogs.mkdirs()
def demoRunner = new RehldsDemoRunner(this.project.configurations.rehlds_playtest_image.getFiles(), rehldsImageRoot, postExtractAction)
println "Preparing engine..."
demoRunner.prepareEngine()
println "Running ${testDemos.getFiles().size()} ReHLDS test demos..."
TeamCityIntegration.suiteStarted("rehldsDemo.${testFor.name}")
int failCount = 0;
testDemos.getFiles().each { f ->
def testInfo = RehldsTestParser.parseTestInfo(f)
TeamCityIntegration.testStarted(testInfo.testName)
if (!TeamCityIntegration.writeOutput) {
print "Running ReHLDS test demo ${testInfo.testName} "
System.out.flush()
}
def testRes = demoRunner.runTest(testInfo, rehldsTestLogs)
if (testRes.success) {
if (!TeamCityIntegration.writeOutput) {
println ' OK'
}
} else {
TeamCityIntegration.testFailed(testInfo.testName, "Exit code: ${testRes.returnCode}", "Exit code: ${testRes.returnCode}")
if (!TeamCityIntegration.writeOutput) {
println ' Failed'
println "ReHLDS testdemo ${testInfo.testName} playback failed. Exit status is ${testRes.returnCode}."
println "Dumping console output:"
println testRes.hldsConsoleOutput
}
failCount++
}
TeamCityIntegration.testStdOut(testInfo.testName, testRes.hldsConsoleOutput)
TeamCityIntegration.testFinished(testInfo.testName, testRes.duration)
}
TeamCityIntegration.suiteFinished("rehldsDemo.${testFor.name}")
if (failCount) {
throw new RuntimeException("Rehlds testdemos: failed ${failCount} tests")
}
}
}

View File

@ -1,34 +0,0 @@
package gradlecpp
import org.apache.velocity.Template
import org.apache.velocity.VelocityContext
import org.apache.velocity.app.Velocity
class VelocityUtils {
static {
Properties p = new Properties();
p.setProperty("resource.loader", "class");
p.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
p.setProperty("class.resource.loader.path", "");
p.setProperty("input.encoding", "UTF-8");
p.setProperty("output.encoding", "UTF-8");
Velocity.init(p);
}
static String renderTemplate(File tplFile, Map<String, ? extends Object> ctx) {
Template tpl = Velocity.getTemplate(tplFile.absolutePath)
if (!tpl) {
throw new RuntimeException("Failed to load velocity template ${tplFile.absolutePath}: not found")
}
def velocityContext = new VelocityContext(ctx)
def sw = new StringWriter()
tpl.merge(velocityContext, sw)
return sw.toString()
}
}

View File

@ -1,84 +0,0 @@
package gradlecpp.teamcity
import groovy.transform.CompileStatic
class TeamCityIntegration {
static final String flowId = System.getenv('TEAMCITY_PROCESS_FLOW_ID')
static final boolean underTeamcity = System.getenv('TEAMCITY_PROJECT_NAME')
static boolean writeOutput = underTeamcity
@CompileStatic
private static String escape(String s) {
StringBuilder sb = new StringBuilder((int)(s.length() * 1.2));
for (char c in s.chars) {
switch (c) {
case '\n': sb.append('|n'); break;
case '\r': sb.append('|r'); break;
case '\'': sb.append('|\''); break;
case '|': sb.append('||'); break;
case ']': sb.append('|]'); break;
default: sb.append(c);
}
}
return sb.toString()
}
@CompileStatic
static void writeMessage(String name, Map params) {
if (!writeOutput) return
StringBuilder sb = new StringBuilder()
sb.append('##teamcity[').append(name)
params.each { e ->
if (e.value != null) {
sb.append(' ').append('' + e.key).append('=\'').append(escape('' + e.value)).append('\'')
}
}
sb.append(']')
println sb.toString()
}
static void suiteStarted(String suiteName) {
writeMessage('testSuiteStarted', [name: suiteName, flowId: flowId ?: null])
}
static void suiteFinished(String suiteName) {
writeMessage('testSuiteFinished', [name: suiteName, flowId: flowId ?: null])
}
static void testStarted(String testName) {
writeMessage('testStarted', [name: testName, flowId: flowId ?: null])
}
static void testStdOut(String testName, String output) {
writeMessage('testStdOut', [name: testName, out: output, flowId: flowId ?: null])
}
static void testFinished(String testName, long durationMs) {
writeMessage('testFinished', [
name: testName,
flowId: flowId ?: null,
duration: (durationMs >= 0) ? durationMs : null
])
}
static void testFailed(String testName, String message, String details) {
writeMessage('testFailed', [
name: testName,
flowId: flowId ?: null,
message: message,
details: details
])
}
static void testIgnored(String testName, String message) {
writeMessage('testIgnored', [
name: testName,
flowId: flowId ?: null,
message: message,
])
}
}

View File

@ -1,81 +0,0 @@
package rehlds.testdemo
import dirsync.builder.FileSystemTreeBuilder
import dirsync.merger.FileTreeComparator
import dirsync.merger.FileTreeDiffApplier
import dirsync.model.tree.DirectoryNode
import dirsync.model.tree.FSMapper
import dirsync.model.tree.ZipData
import dirsync.model.tree.ZipTreeMapper
class RehldsDemoRunner {
ZipTreeMapper rehldsImage = new ZipTreeMapper()
File rootDir
DirectoryNode<ZipData> engineImageTree
Closure postExtract
static class TestResult {
boolean success
int returnCode
String hldsConsoleOutput
long duration
}
RehldsDemoRunner(Collection<File> engineImageZips, File rootDir, Closure postExtract) {
this.rootDir = rootDir
engineImageZips.each { f ->
rehldsImage.addZipArchive(f.absolutePath)
}
engineImageTree = rehldsImage.buildFileTree()
this.postExtract = postExtract
}
void prepareEngine() {
def existingTree = FileSystemTreeBuilder.buildFileSystemTree(rootDir)
def cmds = FileTreeComparator.mergeTrees(engineImageTree, existingTree)
FSMapper fsMapper = new FSMapper(rootDir)
FileTreeDiffApplier.applyDiffs(cmds, rehldsImage, fsMapper)
if (postExtract != null) {
postExtract.run()
}
}
TestResult runTest(RehldsTestInfo info, File testLogDir) {
long startTime = System.currentTimeMillis()
prepareEngine()
def outPath = new File(testLogDir, "${info.testName}_run.log")
def cmdParams = []
cmdParams << new File(rootDir, 'hlds.exe').absolutePath
cmdParams.addAll(info.hldsArgs)
if (info.rehldsExtraArgs) {
cmdParams.addAll(info.rehldsExtraArgs)
}
cmdParams << '--rehlds-test-play' << info.testBinFile.absolutePath
def pb = new ProcessBuilder(cmdParams).redirectErrorStream(true).directory(rootDir)
def sout = new StringBuffer()
def p = pb.start()
p.consumeProcessOutput(sout, sout)
p.waitForOrKill(info.timeoutSeconds * 1000)
int exitVal = p.exitValue()
outPath.withWriter('UTF-8') { writer ->
writer.write(sout.toString())
}
long endTime = System.currentTimeMillis()
return new TestResult(
success: (exitVal == 777),
returnCode: exitVal,
hldsConsoleOutput: sout.toString(),
duration: endTime - startTime
)
}
}

View File

@ -1,9 +0,0 @@
package rehlds.testdemo
class RehldsTestInfo {
String testName
List<String> hldsArgs
String rehldsExtraArgs
int timeoutSeconds
File testBinFile
}

View File

@ -1,63 +0,0 @@
package rehlds.testdemo
import groovy.util.slurpersupport.GPathResult
import org.apache.commons.io.IOUtils
import java.util.zip.ZipFile
class RehldsTestParser {
static final String REHLDS_TEST_METAINFO_FILE = 'rehlds_test_metainfo.xml'
static RehldsTestInfo parseTestInfo(File testArchive) {
def zf = new ZipFile(testArchive);
try {
def metaInfoEntry = zf.getEntry(REHLDS_TEST_METAINFO_FILE)
if (metaInfoEntry == null) {
throw new RuntimeException("Unable to open ${REHLDS_TEST_METAINFO_FILE} in ${testArchive.absolutePath}")
}
GPathResult metaInfo = null
zf.getInputStream(metaInfoEntry).withStream { InputStream ins ->
metaInfo = new XmlSlurper().parse(ins)
}
RehldsTestInfo testInfo = new RehldsTestInfo(
testName: metaInfo.name.text(),
hldsArgs: metaInfo.runArgs.arg.list().collect { it.text().trim() },
timeoutSeconds: metaInfo.timeout.text() as int
)
//validate testInfo
if (!testInfo.testName) {
throw new RuntimeException("Error parsing ${testArchive.absolutePath}: test name is not specified")
}
if (!testInfo.hldsArgs) {
throw new RuntimeException("Error parsing ${testArchive.absolutePath}: run arguments are not specified")
}
if (testInfo.timeoutSeconds <= 0) {
throw new RuntimeException("Error parsing ${testArchive.absolutePath}: bad timeout")
}
def testBinName = testInfo.testName + '.bin'
def testBinEntry = zf.getEntry(testBinName)
if (testBinEntry == null) {
throw new RuntimeException("Error parsing ${testArchive.absolutePath}: test binary ${testBinName} not found inside archive")
}
testInfo.testBinFile = File.createTempFile(testBinName, 'rehlds')
testInfo.testBinFile.deleteOnExit()
zf.getInputStream(testBinEntry).withStream { InputStream ins ->
testInfo.testBinFile.withOutputStream { OutputStream os ->
IOUtils.copy(ins, os)
}
}
return testInfo
} finally {
try { zf.close() } catch (Exception ignored) { }
}
}
}

View File

@ -1,16 +0,0 @@
package versioning
import groovy.transform.CompileStatic
import groovy.transform.TypeChecked
import org.joda.time.DateTime
@CompileStatic @TypeChecked
class GitInfo {
boolean localChanges
DateTime commitDate
String branch
String tag
String commitSHA
String commitURL
Integer commitCount
}

View File

@ -1,126 +0,0 @@
package versioning
import java.util.Set;
import groovy.transform.CompileStatic
import groovy.transform.TypeChecked
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.lib.ObjectId
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.lib.StoredConfig
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.revwalk.RevWalk
import org.eclipse.jgit.storage.file.FileRepositoryBuilder
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
@CompileStatic @TypeChecked
class GitVersioner {
static GitInfo versionForDir(String dir) {
versionForDir(new File(dir))
}
static int getCountCommit(Repository repo) {
Iterable<RevCommit> commits = Git.wrap(repo).log().call()
int count = 0;
commits.each {
count++;
}
return count;
}
static String prepareUrlToCommits(String url) {
if (url == null) {
// default remote url
return "https://github.com/dreamstalker/rehlds/commit/";
}
StringBuilder sb = new StringBuilder();
String childPath;
int pos = url.indexOf('@');
if (pos != -1) {
childPath = url.substring(pos + 1, url.lastIndexOf('.git')).replace(':', '/');
sb.append('https://');
} else {
pos = url.lastIndexOf('.git');
childPath = (pos == -1) ? url : url.substring(0, pos);
}
// support for different links to history of commits
if (url.indexOf('bitbucket.org') != -1) {
sb.append(childPath).append('/commits/');
} else {
sb.append(childPath).append('/commit/');
}
return sb.toString();
}
// check uncommited changes
static boolean getUncommittedChanges(Repository repo) {
Git git = new Git(repo);
Status status = git.status().call();
Set<String> uncommittedChanges = status.getUncommittedChanges();
for(String uncommitted : uncommittedChanges) {
return true;
}
return false;
}
static GitInfo versionForDir(File dir) {
FileRepositoryBuilder builder = new FileRepositoryBuilder()
Repository repo = builder.setWorkTree(dir)
.findGitDir()
.build()
ObjectId head = repo.resolve('HEAD')
if (!head) {
return null
}
final StoredConfig cfg = repo.getConfig();
def commit = new RevWalk(repo).parseCommit(head)
if (!commit) {
throw new RuntimeException("Can't find last commit.")
}
def localChanges = getUncommittedChanges(repo);
def commitDate = new DateTime(1000L * commit.commitTime, DateTimeZone.UTC);
if (localChanges) {
commitDate = new DateTime();
}
def branch = repo.getBranch()
String url = null;
String remote_name = cfg.getString("branch", branch, "remote");
if (remote_name == null) {
for (String remotes : cfg.getSubsections("remote")) {
if (url != null) {
println 'Found a second remote: (' + remotes + '), url: (' + cfg.getString("remote", remotes, "url") + ')'
continue;
}
url = cfg.getString("remote", remotes, "url");
}
} else {
url = cfg.getString("remote", remote_name, "url");
}
String commitURL = prepareUrlToCommits(url);
String tag = repo.tags.find { kv -> kv.value.objectId == commit.id }?.key
String commitSHA = commit.getId().abbreviate(7).name();
return new GitInfo(
localChanges: localChanges,
commitDate: commitDate,
branch: branch,
tag: tag,
commitSHA: commitSHA,
commitURL: commitURL,
commitCount: getCountCommit(repo)
)
}
}

View File

@ -1,56 +0,0 @@
package versioning
import groovy.transform.CompileStatic
import groovy.transform.ToString
import groovy.transform.TypeChecked
import org.joda.time.format.DateTimeFormat
import org.joda.time.DateTime
@CompileStatic @TypeChecked
@ToString(includeNames = true)
class RehldsVersionInfo {
int majorVersion
int minorVersion
Integer maintenanceVersion
String suffix
boolean localChanges
DateTime commitDate
String commitSHA
String commitURL
Integer commitCount
String asMavenVersion(boolean extra = true) {
StringBuilder sb = new StringBuilder()
sb.append(majorVersion).append('.' + minorVersion);
if (maintenanceVersion != null) {
sb.append('.' + maintenanceVersion);
}
if (commitCount != null) {
sb.append('.' + commitCount)
}
if (extra && suffix) {
sb.append('-' + suffix)
}
// do mark for this build like a modified version
if (extra && localChanges) {
sb.append('+m');
}
return sb.toString()
}
String asCommitDate() {
String pattern = "MMM d yyyy";
if (commitDate.getDayOfMonth() >= 10) {
pattern = "MMM d yyyy";
}
return DateTimeFormat.forPattern(pattern).withLocale(Locale.ENGLISH).print(commitDate);
}
String asCommitTime() {
return DateTimeFormat.forPattern('HH:mm:ss').withLocale(Locale.ENGLISH).print(commitDate);
}
}

View File

@ -1,44 +0,0 @@
package dirsync.builder
import org.junit.Test
import java.io.File
import dirsync.builder.ZipTreeBuilder
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream;
import static org.junit.Assert.*;
class ZipTreeBuilderTest {
@Test
void test1() {
File zipFile = File.createTempFile('ZipTreeBuilderTest', 'zip')
zipFile.deleteOnExit()
new ZipOutputStream(zipFile.newDataOutputStream()).withStream { ZipOutputStream zos ->
zos.putNextEntry(new ZipEntry('aRootFile1.txt'))
zos.write(65) //'A'
zos.putNextEntry(new ZipEntry('dir1/'))
zos.putNextEntry(new ZipEntry('dir1/dir2/'))
zos.putNextEntry(new ZipEntry('dir1/dir2/d1d2f1.txt'))
zos.write(65); zos.write(66) //'AB'
zos.putNextEntry(new ZipEntry('dir1/d1f1.txt'))
zos.write(65); zos.write(66); zos.write(67) //'ABC'
zos.putNextEntry(new ZipEntry('zRootFile2.txt'))
zos.write(65); zos.write(66); zos.write(67); zos.write(68) //'ABCD'
}
ZipFile zf = new ZipFile(zipFile.absolutePath)
def tree = ZipTreeBuilder.buildForZipArchive(zipFile.absolutePath, zf)
assert tree.childNodes.size() == 3
}
}

25
dep/bzip2/CMakeLists.txt Normal file
View File

@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.1)
project(bzip2 C)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g0 -O1 -fno-stack-protector")
set(BZIP2_SRCS
"src/blocksort.c"
"src/bzlib.c"
"src/compress.c"
"src/crctable.c"
"src/decompress.c"
"src/huffman.c"
"src/precompiled.c"
"src/randtable.c"
"src/bzlib_private.h"
)
include_directories(
"include"
)
add_library(bzip2 STATIC ${BZIP2_SRCS})
set_target_properties(bzip2 PROPERTIES
COMPILE_FLAGS "-m32"
)

View File

@ -1,79 +0,0 @@
import org.doomedsociety.gradlecpp.cfg.ToolchainConfigUtils
import org.doomedsociety.gradlecpp.msvc.MsvcToolchainConfig
import org.doomedsociety.gradlecpp.toolchain.icc.Icc
import org.doomedsociety.gradlecpp.toolchain.icc.IccCompilerPlugin
import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig
import org.gradle.nativeplatform.NativeBinarySpec
import org.gradle.nativeplatform.NativeLibrarySpec
import org.gradle.nativeplatform.toolchain.VisualCpp
apply plugin: 'c'
apply plugin: IccCompilerPlugin
apply plugin: GccCompilerPlugin
void setupToolchain(NativeBinarySpec b) {
def cfg = rootProject.createToolchainConfig(b)
if (cfg instanceof MsvcToolchainConfig) {
cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig(
enabled: true,
pchHeader: 'bzlib_private.h',
pchSourceSet: 'bz2_pch'
)
}
ToolchainConfigUtils.apply(project, cfg, b)
}
model {
buildTypes {
debug
release
}
platforms {
x86 {
architecture "x86"
}
}
toolChains {
visualCpp(VisualCpp)
if (project.hasProperty("useGcc")) {
gcc(Gcc)
} else {
icc(Icc)
}
}
components {
bzip2(NativeLibrarySpec) {
targetPlatform 'x86'
sources {
bz2_main(CSourceSet) {
source {
srcDir "src"
include "**/*.c"
exclude "precompiled.c"
}
exportedHeaders {
srcDir "include"
}
}
bz2_pch(CSourceSet) {
source {
srcDir "src"
include "precompiled.c"
}
exportedHeaders {
srcDir "include"
}
}
}
binaries.all { NativeBinarySpec b -> project.setupToolchain(b) }
}
}
}

View File

@ -5,10 +5,6 @@
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Swds|Win32">
<Configuration>Release Swds</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
@ -39,16 +35,6 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Swds|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
@ -58,9 +44,6 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Swds|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@ -97,25 +80,6 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Swds|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\include\</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeaderFile>bzlib_private.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
@ -129,7 +93,6 @@
<ClCompile Include="..\src\precompiled.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release Swds|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\randtable.c" />
</ItemGroup>

View File

@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.1)
project(cppunitlite CXX)
add_library(cppunitlite STATIC)
target_sources(cppunitlite PRIVATE
src/Test.cpp
src/TestResult.cpp
src/TestRegistry.cpp
src/Assertions.cpp
src/MainAdapter.cpp
)
target_include_directories(cppunitlite PRIVATE
"${PROJECT_SOURCE_DIR}/src"
"${PROJECT_SOURCE_DIR}/include"
)
target_compile_definitions(cppunitlite PRIVATE
_GLIBCXX_USE_CXX11_ABI=0
)
target_compile_options(cppunitlite PRIVATE
-m32
)

View File

@ -1,64 +0,0 @@
import org.doomedsociety.gradlecpp.cfg.ToolchainConfigUtils
import org.doomedsociety.gradlecpp.msvc.MsvcToolchainConfig
import org.doomedsociety.gradlecpp.toolchain.icc.Icc
import org.doomedsociety.gradlecpp.toolchain.icc.IccCompilerPlugin
import org.doomedsociety.gradlecpp.gcc.GccToolchainConfig
import org.gradle.nativeplatform.NativeBinarySpec
import org.gradle.nativeplatform.NativeLibrarySpec
apply plugin: 'cpp'
apply plugin: IccCompilerPlugin
apply plugin: GccCompilerPlugin
void setupToolchain(NativeBinarySpec b) {
def cfg = rootProject.createToolchainConfig(b)
ToolchainConfigUtils.apply(project, cfg, b)
}
model {
buildTypes {
debug
release
}
platforms {
x86 {
architecture "x86"
}
}
toolChains {
visualCpp(VisualCpp)
if (project.hasProperty("useGcc")) {
gcc(Gcc)
} else {
icc(Icc)
}
}
components {
cppunitlite(NativeLibrarySpec) {
targetPlatform 'x86'
sources {
cppul_main(CppSourceSet) {
source {
srcDir "src"
include "**/*.cpp"
}
exportedHeaders {
srcDir "include"
}
}
}
binaries.all { NativeBinarySpec b ->
project.setupToolchain(b)
}
}
}
}

View File

@ -1,6 +1,6 @@
#pragma once
class GradleAdapter {
class MainAdapter {
public:
int writeAllTestsInfoToFile(const char* fname);
int runTest(const char* groupName, const char* testName);

View File

@ -20,7 +20,7 @@ public:
void setNext(Test *test);
Test *getNext () const;
void run(TestResult& result);
const char* getName() {
return name_.c_str();
}
@ -28,7 +28,7 @@ public:
const char* getGroup() {
return group_.c_str();
}
int getTimeout() {
return timeout_;
}
@ -47,7 +47,7 @@ protected:
{ public: testGroup##testName##Test () : Test (#testName , #testGroup , testTimeout) {} \
void runInternal (); } \
testGroup##testName##Instance; \
void testGroup##testName##Test::runInternal()
void testGroup##testName##Test::runInternal()

View File

@ -5,10 +5,6 @@
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Swds|Win32">
<Configuration>Release Swds</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
@ -17,7 +13,7 @@
<ItemGroup>
<ClInclude Include="..\include\cppunitlite\Assertions.h" />
<ClInclude Include="..\include\cppunitlite\Failure.h" />
<ClInclude Include="..\include\cppunitlite\GradleAdapter.h" />
<ClInclude Include="..\include\cppunitlite\MainAdapter.h" />
<ClInclude Include="..\include\cppunitlite\Test.h" />
<ClInclude Include="..\include\cppunitlite\TestHarness.h" />
<ClInclude Include="..\include\cppunitlite\TestRegistry.h" />
@ -25,7 +21,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\Assertions.cpp" />
<ClCompile Include="..\src\GradleAdapter.cpp" />
<ClCompile Include="..\src\MainAdapter.cpp" />
<ClCompile Include="..\src\Test.cpp" />
<ClCompile Include="..\src\TestRegistry.cpp" />
<ClCompile Include="..\src\TestResult.cpp" />
@ -55,16 +51,6 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Swds|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
@ -74,9 +60,6 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Swds|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@ -115,26 +98,6 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Swds|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>$(ProjectDir)..\include\</AdditionalIncludeDirectories>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -27,7 +27,7 @@
<ClInclude Include="..\include\cppunitlite\TestResult.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="..\include\cppunitlite\GradleAdapter.h">
<ClInclude Include="..\include\cppunitlite\MainAdapter.h">
<Filter>include</Filter>
</ClInclude>
</ItemGroup>
@ -44,7 +44,7 @@
<ClCompile Include="..\src\TestResult.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\GradleAdapter.cpp">
<ClCompile Include="..\src\MainAdapter.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>

View File

@ -2,11 +2,11 @@
#include <stdlib.h>
#include <string.h>
#include "cppunitlite/GradleAdapter.h"
#include "cppunitlite/MainAdapter.h"
#include "cppunitlite/Test.h"
#include "cppunitlite/TestRegistry.h"
int GradleAdapter::writeAllTestsInfoToFile(const char* fname) {
int MainAdapter::writeAllTestsInfoToFile(const char* fname) {
FILE* outFile = fopen(fname, "w");
if (outFile == NULL) {
return 1;
@ -33,7 +33,7 @@ int GradleAdapter::writeAllTestsInfoToFile(const char* fname) {
return 0;
}
int GradleAdapter::runTest(const char* groupName, const char* testName) {
int MainAdapter::runTest(const char* groupName, const char* testName) {
Test* curTest = TestRegistry::getFirstTest();
while (curTest != NULL) {
if (!strcmp(groupName, curTest->getGroup()) && !strcmp(testName, curTest->getName())) {
@ -61,7 +61,7 @@ int GradleAdapter::runTest(const char* groupName, const char* testName) {
}
}
int GradleAdapter::runGroup(const char* groupName) {
int MainAdapter::runGroup(const char* groupName) {
Test* curTest = TestRegistry::getFirstTest();
int ranTests = 0;
int warnTest = 0;
@ -101,7 +101,7 @@ int GradleAdapter::runGroup(const char* groupName) {
return 0;
}
int GradleAdapter::runAllTests() {
int MainAdapter::runAllTests() {
Test* curTest = TestRegistry::getFirstTest();
int ranTests = 0;
int warnTest = 0;
@ -131,7 +131,7 @@ int GradleAdapter::runAllTests() {
return 0;
}
int GradleAdapter::testsEntryPoint(int argc, char* argv[]) {
int MainAdapter::testsEntryPoint(int argc, char* argv[]) {
if (argc < 2 || !strcmp(argv[1], "-all")) {
return runAllTests();
}

View File

@ -5,10 +5,11 @@
#include "cppunitlite/Failure.h"
#include <exception>
#include <iostream>
#include <sstream>
Test::Test (const char* testName, const char* testGroup, int timeout)
Test::Test (const char* testName, const char* testGroup, int timeout)
: name_ (testName), group_ (testGroup), timeout_(timeout)
{
next_ = NULL;
@ -23,13 +24,14 @@ Test *Test::getNext() const
void Test::setNext(Test *test)
{
{
next_ = test;
}
void Test::run(TestResult &result) {
try {
runInternal();
std::cout << "Test::run() > " << group_ << "::" << name_ << " Passed" << std::endl;
} catch (TestFailException &e) {
result.addFailure(Failure(e, name_));
} catch (std::exception &e) {

View File

@ -1,35 +0,0 @@
apply plugin: 'java'
apply plugin: 'groovy'
group = 'org.rehlds.flightrec'
version = rootProject.version
sourceCompatibility = '1.7'
targetCompatibility = '1.7'
repositories {
mavenCentral()
}
dependencies {
testCompile 'org.codehaus.groovy:groovy-all:2.4.5'
testCompile "junit:junit:4.12"
compile project(':flightrec/decoder_api')
}
task uberjar(type: Jar, dependsOn: ['check', ':flightrec/decoder_api:build']) {
from files(sourceSets.main.output.classesDir)
from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } }
exclude('META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.LIST') //exclude all signing stuff
manifest {
attributes 'Main-Class': 'org.rehlds.flightrec.main.FlightRecorder'
attributes 'Implementation-Vendor': 'Sun Microsystems, Inc'
attributes 'Implementation-Title': 'Java Runtime Environment'
attributes 'Implementation-Version': '1.7.0'
}
}
tasks.withType(AbstractCompile) {
options.encoding = 'UTF-8'
}

View File

@ -1,47 +0,0 @@
@if "%DEBUG%" == "" @echo off
setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
set CMD_LINE_ARGS=%*
"%JAVA_EXE%" -jar "%DIRNAME%/decoder.jar" %CMD_LINE_ARGS%
:end
goto mainEnd
:fail
exit /b 1
:mainEnd
endlocal

View File

@ -1,156 +0,0 @@
// Copyright 2011 Google Inc. All rights reserved.
package com.google.cloud;
import java.util.zip.Checksum;
/**
* This class generates a CRC32C checksum, defined by rfc3720 section B.4.
*
*
*/
public final class Crc32c implements Checksum {
private static final long[] CRC_TABLE = {
0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351
};
private static final long LONG_MASK = 0xffffffffL;
private static final long BYTE_MASK = 0xff;
private long crc;
public Crc32c() {
crc = 0;
}
/**
* Updates the checksum with a new byte.
* @param b the new byte.
*/
@Override
public void update(int b) {
long newCrc = crc;
newCrc = updateByte((byte) b, newCrc);
crc = newCrc;
}
/**
* Updates the checksum with an array of bytes.
* @param bArray the array of bytes.
* @param off the offset into the array where the update should begin.
* @param len the length of data to examine.
*/
@Override
public void update(byte[] bArray, int off, int len) {
long newCrc = crc;
for (int i = off; i < off + len; i++) {
newCrc = updateByte(bArray[i], newCrc);
}
crc = newCrc;
}
public void update(byte[] bArray) {
update(bArray, 0, bArray.length);
}
/**
* Returns the value of the checksum.
* @return the long representation of the checksum (high bits set to zero).
*/
@Override
public long getValue() {
return crc;
}
/**
* Returns the value of the checksum.
* @return the 4-byte array representation of the checksum in network byte order (big endian).
*/
public byte[] getValueAsBytes() {
long value = crc;
byte[] result = new byte[4];
for (int i = 3; i >= 0; i--) {
result[i] = (byte) (value & 0xffL);
value >>= 8;
}
return result;
}
/**
* Resets the crc.
*/
@Override
public void reset() {
crc = 0;
}
private long updateByte(byte newByte, long crc) {
byte b = (byte) (newByte & BYTE_MASK);
int index = (int) ((crc ^ b) & BYTE_MASK);
return (CRC_TABLE[index] ^ (crc >> 8)) & LONG_MASK;
}
}

View File

@ -1,14 +0,0 @@
package org.rehlds.flightrec;
public class Consts {
public final static String META_HEADER_SIG_STR = "REHLDS_FLIGHTREC_META";
public final static String DATA_HEADER_SIG_STR = "REHLDS_FLIGHTREC_DATA";
public static byte[] META_HEADER_SIG_BYTES = (META_HEADER_SIG_STR + META_HEADER_SIG_STR + META_HEADER_SIG_STR + ":").getBytes();
public static byte[] DATA_HEADER_SIG_BYTES = (DATA_HEADER_SIG_STR + DATA_HEADER_SIG_STR + DATA_HEADER_SIG_STR + ":").getBytes();
public static int META_HEADER_SIZE = 128;
public static int DATA_HEADER_SIZE = 128;
public static int MAX_HEADER_SIZE = Math.max(META_HEADER_SIZE, DATA_HEADER_SIZE);
}

View File

@ -1,22 +0,0 @@
package org.rehlds.flightrec.decoders.rehlds;
import org.rehlds.flightrec.api.DecodedExtraData;
import org.rehlds.flightrec.api.FlightrecMessage;
import org.rehlds.flightrec.api.FlightrecMessageType;
import org.rehlds.flightrec.api.MessageDecoder;
import org.rehlds.flightrec.api.util.UtilSizeBuf;
public class AllocEntPrivateDataV1Decoder implements MessageDecoder {
@Override
public FlightrecMessageType getMessageType() {
return new FlightrecMessageType("rehlds", "AllocEntPrivateData", 1, false);
}
@Override
public DecodedExtraData decode(FlightrecMessage msg) {
UtilSizeBuf sb = msg.getDataSizebuf();
long ptr = sb.readUInt32();
return DecodedExtraData.create("pPrivData", "0x" + Long.toHexString(ptr));
}
}

View File

@ -1,22 +0,0 @@
package org.rehlds.flightrec.decoders.rehlds;
import org.rehlds.flightrec.api.DecodedExtraData;
import org.rehlds.flightrec.api.FlightrecMessage;
import org.rehlds.flightrec.api.FlightrecMessageType;
import org.rehlds.flightrec.api.MessageDecoder;
import org.rehlds.flightrec.api.util.UtilSizeBuf;
public class AllocEntPrivateDataV2Decoder implements MessageDecoder {
@Override
public FlightrecMessageType getMessageType() {
return new FlightrecMessageType("rehlds", "AllocEntPrivateData", 2, false);
}
@Override
public DecodedExtraData decode(FlightrecMessage msg) {
UtilSizeBuf sb = msg.getDataSizebuf();
long ptr = sb.readUInt32();
long size = sb.readUInt32();
return DecodedExtraData.create("pPrivData", "0x" + Long.toHexString(ptr), "size", "" + size);
}
}

View File

@ -1,30 +0,0 @@
package org.rehlds.flightrec.decoders.rehlds;
import org.rehlds.flightrec.api.DecodedExtraData;
import org.rehlds.flightrec.api.FlightrecMessage;
import org.rehlds.flightrec.api.FlightrecMessageType;
import org.rehlds.flightrec.api.MessageDecoder;
import org.rehlds.flightrec.api.util.UtilSizeBuf;
public class FrameV1Decoder implements MessageDecoder {
@Override
public FlightrecMessageType getMessageType() {
return new FlightrecMessageType("rehlds", "Frame", 1, true);
}
DecodedExtraData decodeStart(UtilSizeBuf sb) {
double startTime = sb.readDouble();
return DecodedExtraData.create("startTime", "" + startTime);
}
DecodedExtraData decodeEnd(UtilSizeBuf sb) {
return DecodedExtraData.EMPTY;
}
@Override
public DecodedExtraData decode(FlightrecMessage msg) {
UtilSizeBuf sb = msg.getDataSizebuf();
return msg.isEnterMessage() ? decodeStart(sb) : decodeEnd(sb);
}
}

View File

@ -1,32 +0,0 @@
package org.rehlds.flightrec.decoders.rehlds;
import org.rehlds.flightrec.api.DecodedExtraData;
import org.rehlds.flightrec.api.FlightrecMessage;
import org.rehlds.flightrec.api.FlightrecMessageType;
import org.rehlds.flightrec.api.MessageDecoder;
import org.rehlds.flightrec.api.util.UtilSizeBuf;
public class FrameV2Decoder implements MessageDecoder {
@Override
public FlightrecMessageType getMessageType() {
return new FlightrecMessageType("rehlds", "Frame", 2, true);
}
DecodedExtraData decodeStart(UtilSizeBuf sb) {
long frameId = sb.readInt64();
double startTime = sb.readDouble();
return DecodedExtraData.create("frameId", "" + frameId, "startTime", "" + startTime);
}
DecodedExtraData decodeEnd(UtilSizeBuf sb) {
long frameId = sb.readInt64();
return DecodedExtraData.create("frameId", "" + frameId);
}
@Override
public DecodedExtraData decode(FlightrecMessage msg) {
UtilSizeBuf sb = msg.getDataSizebuf();
return msg.isEnterMessage() ? decodeStart(sb) : decodeEnd(sb);
}
}

View File

@ -1,21 +0,0 @@
package org.rehlds.flightrec.decoders.rehlds;
import org.rehlds.flightrec.api.DecodedExtraData;
import org.rehlds.flightrec.api.FlightrecMessage;
import org.rehlds.flightrec.api.FlightrecMessageType;
import org.rehlds.flightrec.api.MessageDecoder;
import org.rehlds.flightrec.api.util.UtilSizeBuf;
public class FreeEntPrivateDataV1Decoder implements MessageDecoder {
@Override
public FlightrecMessageType getMessageType() {
return new FlightrecMessageType("rehlds", "FreeEntPrivateData", 1, false);
}
@Override
public DecodedExtraData decode(FlightrecMessage msg) {
UtilSizeBuf sb = msg.getDataSizebuf();
long ptr = sb.readUInt32();
return DecodedExtraData.create("pPrivData", "0x" + Long.toHexString(ptr));
}
}

View File

@ -1,22 +0,0 @@
package org.rehlds.flightrec.decoders.rehlds;
import org.rehlds.flightrec.api.DecodedExtraData;
import org.rehlds.flightrec.api.FlightrecMessage;
import org.rehlds.flightrec.api.FlightrecMessageType;
import org.rehlds.flightrec.api.MessageDecoder;
import org.rehlds.flightrec.api.util.UtilSizeBuf;
public class LogV1Decoder implements MessageDecoder {
@Override
public FlightrecMessageType getMessageType() {
return new FlightrecMessageType("rehlds", "Log", 1, false);
}
@Override
public DecodedExtraData decode(FlightrecMessage msg) {
UtilSizeBuf sb = msg.getDataSizebuf();
String prefix = sb.readString();
String message = sb.readString();
return DecodedExtraData.create("prefix", prefix, "message", message);
}
}

View File

@ -1,18 +0,0 @@
package org.rehlds.flightrec.decoders.rehlds;
import org.rehlds.flightrec.api.SimpleDecoderModule;
public class RehldsDecodersModule extends SimpleDecoderModule {
public RehldsDecodersModule() {
super("Rehlds decoders (built-in)", "0.2");
registerDecoder(new FrameV1Decoder());
registerDecoder(new FreeEntPrivateDataV1Decoder());
registerDecoder(new AllocEntPrivateDataV1Decoder());
registerDecoder(new FrameV2Decoder());
registerDecoder(new LogV1Decoder());
registerDecoder(new AllocEntPrivateDataV2Decoder());
}
}

View File

@ -1,9 +0,0 @@
package org.rehlds.flightrec.filescan;
import java.util.ArrayList;
import java.util.List;
public class FileScanResult {
public List<HeaderScanResult> metaHeaders = new ArrayList<>();
public List<HeaderScanResult> dataHeaders = new ArrayList<>();
}

View File

@ -1,100 +0,0 @@
package org.rehlds.flightrec.filescan;
import com.google.cloud.Crc32c;
import org.rehlds.flightrec.api.util.UtilByteBuffer;
import org.rehlds.flightrec.api.util.UtilSizeBuf;
import static org.rehlds.flightrec.Consts.*;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.List;
public class FlightRecFileScanner {
RandomAccessFile file;
long fileLen;
FileScanResult scanRes = new FileScanResult();
private byte readBuf[] = new byte[65536];
private byte header[] = new byte[MAX_HEADER_SIZE];
private UtilSizeBuf headerSBuf = new UtilSizeBuf("header", new UtilByteBuffer(header), 0, header.length);
private FlightRecFileScanner(RandomAccessFile file) throws IOException {
this.file = file;
this.fileLen = file.length();
}
private void examineHeader(byte[] data, int size, int pos) throws IOException {
if (pos + MAX_HEADER_SIZE < size) {
System.arraycopy(data, pos, header, 0, MAX_HEADER_SIZE);
} else {
return; //will be read in next iteration
}
headerSBuf.reset();
String matchedType = null;
if (Arrays.equals(META_HEADER_SIG_BYTES, Arrays.copyOfRange(header, 0, META_HEADER_SIG_BYTES.length))) {
matchedType = META_HEADER_SIG_STR;
headerSBuf.skip(META_HEADER_SIG_BYTES.length);
} else if (Arrays.equals(DATA_HEADER_SIG_BYTES, Arrays.copyOfRange(header, 0, DATA_HEADER_SIG_BYTES.length))) {
matchedType = DATA_HEADER_SIG_STR;
headerSBuf.skip(DATA_HEADER_SIG_BYTES.length);
}
if (matchedType == null) {
return;
}
List<HeaderScanResult> resList = (matchedType.equals(META_HEADER_SIG_STR)) ? scanRes.metaHeaders : scanRes.dataHeaders;
int version = headerSBuf.readInt32();
int allocSize = headerSBuf.readInt32();
Crc32c crc32 = new Crc32c();
crc32.update(header, 0, headerSBuf.tell());
long calculatedChecksum = crc32.getValue();
long bufChecksum = headerSBuf.readUInt32();
if (calculatedChecksum != bufChecksum) {
resList.add(new HeaderScanResult(file.getFilePointer() - size + pos, allocSize, false, "Checksum mismatch", version));
return;
}
long endPos = file.getFilePointer() - size + pos + allocSize;
if (endPos > file.length()) {
resList.add(new HeaderScanResult(file.getFilePointer() - size + pos, allocSize, false, "Regions partially lays outside the file", version));
return;
}
resList.add(new HeaderScanResult(file.getFilePointer() - size + pos, allocSize, true, null, version));
}
private void scanForHeaders(byte[] data, int size) throws IOException {
int maxHeaderSize = Math.max(META_HEADER_SIG_STR.length(), DATA_HEADER_SIG_STR.length());
for (int i = 0; i < size - maxHeaderSize; i++) {
if (data[i + 15] == META_HEADER_SIG_BYTES[15] && data[i + 16] == META_HEADER_SIG_BYTES[16] && data[i + 17] == META_HEADER_SIG_BYTES[17] && data[i + 18] == META_HEADER_SIG_BYTES[18]) {
examineHeader(data, size, i);
} else if (data[i + 15] == DATA_HEADER_SIG_BYTES[15] && data[i + 16] == DATA_HEADER_SIG_BYTES[16] && data[i + 17] == DATA_HEADER_SIG_BYTES[17] && data[i + 18] == DATA_HEADER_SIG_BYTES[18]) {
examineHeader(data, size, i);
}
}
}
private void doScan() throws IOException {
file.seek(0);
int read;
while (-1 != (read = file.read(readBuf))) {
scanForHeaders(readBuf, read);
if (read == readBuf.length) {
file.seek(file.getFilePointer() - MAX_HEADER_SIZE * 2);
}
}
}
public static FileScanResult scan(RandomAccessFile file) throws IOException {
FlightRecFileScanner scanner = new FlightRecFileScanner(file);
scanner.doScan();
return scanner.scanRes;
}
}

View File

@ -1,17 +0,0 @@
package org.rehlds.flightrec.filescan;
public class HeaderScanResult {
public long pos;
public int len;
public boolean valid;
public String error;
public int version;
public HeaderScanResult(long pos, int len, boolean valid, String error, int version) {
this.pos = pos;
this.len = len;
this.valid = valid;
this.error = error;
this.version = version;
}
}

View File

@ -1,12 +0,0 @@
package org.rehlds.flightrec.logparser;
public class DataHeader {
public int prevItrLastPos;
public DataHeader(int prevItrLastPos) {
this.prevItrLastPos = prevItrLastPos;
}
public DataHeader() {
}
}

View File

@ -1,179 +0,0 @@
package org.rehlds.flightrec.logparser;
import org.rehlds.flightrec.api.EntranceKind;
import org.rehlds.flightrec.api.FlightrecMessage;
import org.rehlds.flightrec.api.FlightrecMessageDef;
import org.rehlds.flightrec.api.FlightrecMessageType;
import org.rehlds.flightrec.filescan.HeaderScanResult;
import org.rehlds.flightrec.api.util.UtilByteBuffer;
import org.rehlds.flightrec.api.util.UtilSizeBuf;
import static org.rehlds.flightrec.Consts.*;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.*;
public class FlightLogParser {
UtilByteBuffer metaRegion;
UtilByteBuffer dataRegion;
MetaHeader metaHeader;
RecorderState recorderState;
DataHeader dataHeader;
Map<Integer, FlightrecMessageType> msgTypes = new HashMap<>();
List<FlightrecMessage> messages = new ArrayList<>();
void parseMessageDefinition(UtilSizeBuf sbuf) {
int msgId = sbuf.readUInt16();
String module = sbuf.readString();
String messageName = sbuf.readString();
long msgVersion = sbuf.readUInt32();
boolean inOut = sbuf.readBool();
FlightrecMessageDef msgDef = new FlightrecMessageDef(module, messageName, msgVersion, inOut, msgId);
if (msgTypes.containsKey(msgId)) {
System.out.println("Duplicate message id: " + msgTypes.get(msgId) + " and " + msgDef);
}
msgTypes.put(msgId, msgDef.msgType);
}
void parseMetaRegion() {
metaHeader = new MetaHeader();
UtilSizeBuf metaSBuf = new UtilSizeBuf("meta region", metaRegion);
metaSBuf.skip(META_HEADER_SIG_BYTES.length); //skip signature
metaSBuf.readInt32(); //version
metaSBuf.readInt32(); //allocSize
metaSBuf.readInt32(); //checksum
metaHeader.numDefinitions = metaSBuf.readInt32();
metaHeader.metaRegionPos = metaSBuf.readInt32();
recorderState = new RecorderState();
recorderState.wpos = metaSBuf.readInt32();
recorderState.lastMsgBeginPos = metaSBuf.readInt32();
recorderState.curMessage = metaSBuf.readUInt16();
metaSBuf = new UtilSizeBuf("meta region defs", metaRegion, META_HEADER_SIZE, metaHeader.metaRegionPos);
for (int i = 0; i < metaHeader.numDefinitions; i++) {
int defKind = metaSBuf.readUInt8();
switch (defKind) {
case 1: //MRT_MESSAGE_DEF
parseMessageDefinition(metaSBuf);
break;
default:
throw new RuntimeException("Invalid meta definition type" + defKind);
}
}
dataHeader = new DataHeader();
dataHeader.prevItrLastPos = dataRegion.readInt32(DATA_HEADER_SIG_BYTES.length + 12);
}
public FlightLogParser(UtilByteBuffer metaRegion, UtilByteBuffer dataRegion) {
this.metaRegion = metaRegion;
this.dataRegion = dataRegion;
}
void doParseMessage(UtilSizeBuf msg) {
int opc = msg.readUInt16();
boolean entrance = (0 != (opc & 0x8000));
opc &= 0x7FFF;
FlightrecMessageType msgType = msgTypes.get(opc);
if (msgType == null) {
throw new RuntimeException("Invalid message opcode @" + Long.toHexString(msg.getAbsoluteCurrentPos() - 2) + ": " + opc);
}
EntranceKind entranceKind;
if (msgType.inout) {
entranceKind = entrance ? EntranceKind.ENTRANCE_ENTER : EntranceKind.ENTRANCE_LEAVE;
} else {
entranceKind = EntranceKind.ENTRANCE_UNUSED;
}
FlightrecMessage flMsg = new FlightrecMessage(msgType, entranceKind, msg.getBuffer(), msg.getAbsoluteCurrentPos(), msg.getMaxSize() - 2);
messages.add(flMsg);
}
void parseMessage(UtilSizeBuf msg) {
int startPos = msg.getStartPos();
try {
doParseMessage(msg);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Error while parsing message @" + startPos);
}
}
List<FlightrecMessage> parse() {
parseMetaRegion();
UtilByteBuffer flightData = dataRegion.cutLeft(DATA_HEADER_SIZE);
boolean flippedToEnd = false;
/*
Each message has following layout:
Opcode [2 bytes]
Data [0+ bytes]
Length of opcode + data [2 bytes]
*/
int curMsgPos = (recorderState.curMessage == 0) ? recorderState.wpos : recorderState.lastMsgBeginPos;
curMsgPos -= 2; //position of the Length field of the message
UtilSizeBuf msg = new UtilSizeBuf("flightrec_message", flightData, 0, 0);
while (true) {
if (flippedToEnd && curMsgPos <= recorderState.wpos)
break;
if (curMsgPos <= 0) { //move read pointer to the end of the data region
if (dataHeader.prevItrLastPos == -1) //wpos never reached end of the region
break;
curMsgPos = dataHeader.prevItrLastPos - 2;
flippedToEnd = true;
continue;
}
int msgLen = flightData.readUInt16(curMsgPos);
int msgStartPos = curMsgPos - msgLen;
if (msgStartPos < 0) {
throw new RuntimeException("Corrupted data region; read msgLen=" + msgLen + " at " + curMsgPos + ", but it is too large (startPos < 0)");
}
if (flippedToEnd && msgStartPos < recorderState.wpos) {
break;
}
msg.init(msgStartPos, msgLen);
parseMessage(msg);
curMsgPos = msgStartPos - 2;
}
return messages;
}
public static List<FlightrecMessage> doParse(RandomAccessFile f, HeaderScanResult metaHeader, HeaderScanResult dataHeader) throws IOException {
//read regions to byte buffers
f.seek(metaHeader.pos);
byte[] metaRegionData = new byte[metaHeader.len];
f.readFully(metaRegionData);
f.seek(dataHeader.pos);
byte[] dataRegionData = new byte[dataHeader.len];
f.readFully(dataRegionData);
UtilByteBuffer metaRegion = new UtilByteBuffer(metaRegionData);
UtilByteBuffer dataRegion = new UtilByteBuffer(dataRegionData);
List<FlightrecMessage> res = new FlightLogParser(metaRegion, dataRegion).parse();
Collections.reverse(res);
return res;
}
}

View File

@ -1,12 +0,0 @@
package org.rehlds.flightrec.logparser;
public class LogParsingException extends RuntimeException {
public LogParsingException(String message) {
super(message);
}
public LogParsingException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,14 +0,0 @@
package org.rehlds.flightrec.logparser;
public class MetaHeader {
public int numDefinitions;
public int metaRegionPos;
public MetaHeader(int numMessages, int metaRegionPos) {
this.numDefinitions = numMessages;
this.metaRegionPos = metaRegionPos;
}
public MetaHeader() {
}
}

View File

@ -1,16 +0,0 @@
package org.rehlds.flightrec.logparser;
public class RecorderState {
public int wpos;
public int lastMsgBeginPos;
public int curMessage;
public RecorderState(int wpos, int lastMsgBeginPos, int curMessage) {
this.wpos = wpos;
this.lastMsgBeginPos = lastMsgBeginPos;
this.curMessage = curMessage;
}
public RecorderState() {
}
}

View File

@ -1,72 +0,0 @@
package org.rehlds.flightrec.logtree;
import org.rehlds.flightrec.api.FlightrecMessage;
import org.rehlds.flightrec.api.FlightrecMessageType;
import java.util.List;
public class FlightLogTreeBuilder {
LogTreeNodeComplex rootNode = new LogTreeNodeComplex(null, null, null);
LogTreeNodeComplex currentNode = rootNode;
void handleEnterMessage(FlightrecMessage msg) {
LogTreeNodeComplex n = new LogTreeNodeComplex(currentNode, msg, null);
currentNode.addChild(n);
currentNode = n;
}
void handleLeaveMessage(FlightrecMessage msg) {
if (currentNode == rootNode) {
currentNode.leaveMsg = msg;
rootNode = new LogTreeNodeComplex(null, null, null);
rootNode.addChild(currentNode);
currentNode.setParent(rootNode);
currentNode = rootNode;
return;
}
if (currentNode.enterMsg != null) {
FlightrecMessageType startType = currentNode.enterMsg.messageType;
FlightrecMessageType endType = msg.messageType;
if (!startType.equals(endType)) {
throw new RuntimeException("Closing message @" + Long.toHexString(msg.rawDataPos) + " has invalid type " + endType + "; expected " + startType);
}
}
currentNode.leaveMsg = msg;
currentNode = currentNode.parent;
}
void handleSimpleMessage(FlightrecMessage msg) {
LogTreeNodeLeaf leafNode = new LogTreeNodeLeaf(currentNode, msg);
currentNode.addChild(leafNode);
}
void doBuildLogTree(List<FlightrecMessage> messages) {
for (FlightrecMessage msg : messages) {
switch (msg.entranceKind) {
case ENTRANCE_ENTER:
handleEnterMessage(msg);
break;
case ENTRANCE_LEAVE:
handleLeaveMessage(msg);
break;
case ENTRANCE_UNUSED:
handleSimpleMessage(msg);
break;
default:
throw new RuntimeException("Invalid exntrance kind");
}
}
}
public static LogTreeNodeComplex buildTree(List<FlightrecMessage> messages) {
FlightLogTreeBuilder builder = new FlightLogTreeBuilder();
builder.doBuildLogTree(messages);
return builder.rootNode;
}
}

View File

@ -1,21 +0,0 @@
package org.rehlds.flightrec.logtree;
import java.util.List;
public abstract class LogTreeNode {
LogTreeNodeComplex parent;
protected LogTreeNode(LogTreeNodeComplex parent) {
this.parent = parent;
}
abstract List<? extends LogTreeNode> getChildren();
LogTreeNodeComplex getParent() {
return parent;
}
public void setParent(LogTreeNodeComplex parent) {
this.parent = parent;
}
}

View File

@ -1,36 +0,0 @@
package org.rehlds.flightrec.logtree;
import org.rehlds.flightrec.api.FlightrecMessage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class LogTreeNodeComplex extends LogTreeNode {
public FlightrecMessage enterMsg;
public FlightrecMessage leaveMsg;
public LogTreeNodeComplex(LogTreeNodeComplex parent, FlightrecMessage enterMsg, FlightrecMessage leaveMsg) {
super(parent);
this.enterMsg = enterMsg;
this.leaveMsg = leaveMsg;
}
List<LogTreeNode> children = Collections.emptyList();
@Override
public List<LogTreeNode> getChildren() {
return children;
}
public void addChild(LogTreeNode node) {
if (children.isEmpty()) {
children = new ArrayList<>();
}
children.add(node);
}
}

View File

@ -1,20 +0,0 @@
package org.rehlds.flightrec.logtree;
import org.rehlds.flightrec.api.FlightrecMessage;
import java.util.Collections;
import java.util.List;
public class LogTreeNodeLeaf extends LogTreeNode {
public FlightrecMessage msg;
public LogTreeNodeLeaf(LogTreeNodeComplex parent, FlightrecMessage msg) {
super(parent);
this.msg = msg;
}
@Override
List<? extends LogTreeNode> getChildren() {
return Collections.emptyList();
}
}

View File

@ -1,230 +0,0 @@
package org.rehlds.flightrec.main;
import org.rehlds.flightrec.api.DecoderModule;
import org.rehlds.flightrec.api.FlightrecMessage;
import org.rehlds.flightrec.decoders.rehlds.RehldsDecodersModule;
import org.rehlds.flightrec.filescan.FileScanResult;
import org.rehlds.flightrec.filescan.FlightRecFileScanner;
import org.rehlds.flightrec.filescan.HeaderScanResult;
import org.rehlds.flightrec.logtree.FlightLogTreeBuilder;
import org.rehlds.flightrec.logtree.LogTreeNodeComplex;
import org.rehlds.flightrec.logparser.FlightLogParser;
import org.rehlds.flightrec.textlogwriter.TextLogWriter;
import org.rehlds.flightrec.util.JarUtils;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
public class FlightRecorder {
RunConfig cfg;
List<DecoderModule> decoderModules = new ArrayList<>();
public FlightRecorder(RunConfig cfg) {
this.cfg = cfg;
}
private boolean checkConfig() {
if (cfg.dumpFile == null) {
System.out.println("Dump file is not selected, please use --dump-file <filename> parameter to specify it");
return false;
}
if (cfg.outFile == null) {
cfg.outFile = new File(cfg.dumpFile.getAbsolutePath() + ".flog");
}
return true;
}
private List<FlightrecMessage> scanFile(RandomAccessFile f) throws IOException {
FileScanResult scanResult = FlightRecFileScanner.scan(f);
System.out.println("Dump file scan results: ");
for (HeaderScanResult hdr : scanResult.metaHeaders) {
System.out.print(String.format("\tMeta header @ 0x%08X; len=%d; version=%d; valid=%s", hdr.pos, hdr.len, hdr.version, "" + (hdr.error == null)));
if (hdr.error != null) {
System.out.print("; error: " + hdr.error);
}
System.out.println();
}
for (HeaderScanResult hdr : scanResult.dataHeaders) {
System.out.print(String.format("\tData header @ 0x%08X; len=%d; version=%d; valid=%s", hdr.pos, hdr.len, hdr.version, "" + (hdr.error == null)));
if (hdr.error != null) {
System.out.print("; error: " + hdr.error);
}
System.out.println();
}
HeaderScanResult validMetaHeader = null;
HeaderScanResult validDataHeader = null;
for (HeaderScanResult metaHeader : scanResult.metaHeaders) {
if (metaHeader.error != null) {
continue;
}
if (validMetaHeader != null) {
System.out.println("Multiple meta headers found, exiting");
return null;
}
validMetaHeader = metaHeader;
}
for (HeaderScanResult dataHeader : scanResult.dataHeaders) {
if (dataHeader.error != null) {
continue;
}
if (validDataHeader != null) {
System.out.println("Multiple data headers found, exiting");
return null;
}
validDataHeader = dataHeader;
}
if (validMetaHeader == null) {
System.out.println("Meta header not found, exiting");
return null;
}
if (validDataHeader == null) {
System.out.println("Data header not found, exiting");
return null;
}
return FlightLogParser.doParse(f, validMetaHeader, validDataHeader);
}
private LogTreeNodeComplex buildTree(List<FlightrecMessage> messages) {
return FlightLogTreeBuilder.buildTree(messages);
}
private boolean writeOutputFile(LogTreeNodeComplex logTreeRoot) {
TextLogWriter.decodeAndWrite(logTreeRoot, cfg.outFile, decoderModules);
System.out.println("Written decoded log to '" + cfg.outFile.getAbsolutePath() + ";");
return true;
}
public boolean run() {
registerBuiltinDecoders();
loadExternalDecoders();
if (!checkConfig()) {
return false;
}
List<FlightrecMessage> messages;
try(RandomAccessFile f = new RandomAccessFile(cfg.dumpFile, "r")) {
messages = scanFile(f);
} catch (IOException e) {
e.printStackTrace();
return false;
}
if (messages == null) {
return false;
}
System.out.println("Read " + messages.size() + " messages from '" + cfg.dumpFile.getAbsolutePath() + "'");
LogTreeNodeComplex treeRootNode = buildTree(messages);
if (treeRootNode == null) {
return false;
}
if (!writeOutputFile(treeRootNode)) {
return false;
}
return true;
}
private void loadExternalDecoders() {
File f = JarUtils.getJarFileOfClass(FlightRecorder.class);
if (f == null) {
System.out.println("Could not locate main JAR, external decoders will not be loaded");
return;
}
File extDir = new File(f.getParentFile(), "extDecoders");
if (!extDir.exists() || !extDir.isDirectory()) {
System.out.println("Directory '" + extDir.getAbsolutePath() + "' doesn't exist");
}
File[] jarFiles = extDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().toLowerCase().endsWith(".jar");
}
});
ArrayList<URL> jarUrls = new ArrayList<>();
for (File jf : jarFiles) {
try {
jarUrls.add(jf.toURI().toURL());
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
URLClassLoader extDecodersClassloader = new URLClassLoader(jarUrls.toArray(new URL[jarUrls.size()]), this.getClass().getClassLoader());
ServiceLoader<DecoderModule> srvLoader = ServiceLoader.load(DecoderModule.class, extDecodersClassloader);
for (DecoderModule decoderModule : srvLoader) {
System.out.println("Loaded external decoder module " + decoderModule.getDescription() + " version " + decoderModule.getVersion());
decoderModules.add(decoderModule);
}
}
private void registerBuiltinDecoders() {
decoderModules.add(new RehldsDecodersModule());
}
public static void main(String args[]) {
RunConfig cfg;
try {
cfg = parseArgs(args);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
return;
}
new FlightRecorder(cfg).run();
}
private static RunConfig parseArgs(String args[]) {
RunConfig cfg = new RunConfig();
for (int i = 0; i < args.length; i++) {
String a = args[i];
if ("--dump-file".equals(a)) {
if (i + 1 >= args.length) {
throw new IllegalArgumentException("--dump-file should be followed by file name");
}
i++;
cfg.dumpFile = new File(args[i]);
continue;
}
if ("--out-file".equals(a)) {
if (i + 1 >= args.length) {
throw new IllegalArgumentException("--out-file should be followed by file name");
}
i++;
cfg.outFile = new File(args[i]);
continue;
}
throw new IllegalArgumentException("Invalid command line parameter: '" + a + "'");
}
return cfg;
}
}

View File

@ -1,8 +0,0 @@
package org.rehlds.flightrec.main;
import java.io.File;
public class RunConfig {
public File dumpFile;
public File outFile;
}

View File

@ -1,185 +0,0 @@
package org.rehlds.flightrec.textlogwriter;
import org.rehlds.flightrec.api.*;
import org.rehlds.flightrec.logtree.LogTreeNode;
import org.rehlds.flightrec.logtree.LogTreeNodeComplex;
import org.rehlds.flightrec.logtree.LogTreeNodeLeaf;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TextLogWriter {
Writer writer;
List<DecoderModule> decoderModules;
int indent;
HashMap<Integer, String> indents = new HashMap<>();
Map<FlightrecMessageType, MessageDecoder> decodersByMsgType = new HashMap<>();
public TextLogWriter(Writer writer, List<DecoderModule> decoderModules) {
this.writer = writer;
this.decoderModules = decoderModules;
}
MessageDecoder lookupDecoder(FlightrecMessageType msgType) {
for (DecoderModule dm : decoderModules) {
MessageDecoder d = dm.lookupDecoder(msgType);
if (d != null) {
return d;
}
}
return null;
}
MessageDecoder getDecoder(FlightrecMessage message) {
FlightrecMessageType msgType = message.messageType;
if (!decodersByMsgType.containsKey(msgType)) {
decodersByMsgType.put(msgType, lookupDecoder(msgType));
}
return decodersByMsgType.get(msgType);
}
DecodedExtraData tryDecode(FlightrecMessage message) {
MessageDecoder decoder = getDecoder(message);
if (decoder == null) {
return null;
}
return decoder.decode(message);
}
String escapeString(String s) {
return s.replace("\"", "\\\"")
.replace("'", "\\'")
.replace("\n", "\\n")
.replace("\r", "\\r");
}
String generateIndent() {
String res = indents.get(indent);
if (res != null) {
return res;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < indent; i++) {
sb.append(" ");
}
res = sb.toString();
indents.put(indent, res);
return res;
}
void writeExtraData(StringBuilder sb, DecodedExtraData extraData) {
boolean first = true;
for (ImmutablePair<String, String> kv : extraData.data) {
if (first) {
first = false;
} else {
sb.append(", ");
}
sb.append(kv.first).append(": '").append(escapeString(kv.second)).append("'");
}
}
String prepareMessageText(FlightrecMessage msg) {
StringBuilder sb = new StringBuilder();
sb.append(generateIndent());
switch (msg.entranceKind) {
case ENTRANCE_ENTER:
sb.append(">>");
break;
case ENTRANCE_LEAVE:
sb.append("<<");
break;
case ENTRANCE_UNUSED:
sb.append("--");
break;
default:
throw new RuntimeException("Invalid entrance kind " + msg.entranceKind);
}
FlightrecMessageType msgType = msg.messageType;
sb.append(" ").append(msgType.module).append(".").append(msgType.message).append(":").append(msgType.version).append(" ");
DecodedExtraData extraData = tryDecode(msg);
if (extraData != null) {
writeExtraData(sb, extraData);
} else {
sb.append("undecoded[");
boolean firstByte = true;
for (int i = msg.rawDataPos; i < msg.rawDataLen + msg.rawDataPos; i++) {
if (firstByte) {
firstByte = false;
} else {
sb.append(" ");
}
sb.append(String.format("%02X", msg.rawData[i] & 0xFF));
}
sb.append("]");
}
sb.append("\n");
return sb.toString();
}
void writeMessage(FlightrecMessage msg) throws IOException {
String text = prepareMessageText(msg);
writer.write(text);
}
void writeLeafNode(LogTreeNodeLeaf node) throws IOException {
writeMessage(node.msg);
}
void writeComplexNode(LogTreeNodeComplex node) throws IOException {
if (node.enterMsg != null) {
writeMessage(node.enterMsg);
} else {
writer.write(generateIndent() + ">> [Unknown]\n");
}
indent++;
writeNodes(node.getChildren());
indent--;
if (node.leaveMsg != null) {
writeMessage(node.leaveMsg);
} else {
writer.write(generateIndent() + "<< [Unknown]\n");
}
}
void writeNodes(List<LogTreeNode> nodes) throws IOException {
for (LogTreeNode node : nodes) {
if (node instanceof LogTreeNodeComplex) {
writeComplexNode((LogTreeNodeComplex) node);
} else if (node instanceof LogTreeNodeLeaf) {
writeLeafNode((LogTreeNodeLeaf) node);
} else {
throw new RuntimeException("Invalid node class " + node.getClass().getName());
}
}
}
public static void decodeAndWrite(LogTreeNodeComplex rootNode, File outFile, List<DecoderModule> decoderModules) {
try (FileWriter fw = new FileWriter(outFile)) {
TextLogWriter logWriter = new TextLogWriter(fw, decoderModules);
logWriter.writeNodes(rootNode.getChildren());
} catch (IOException e) {
throw new RuntimeException("Failed to open/write file '" + outFile + "': " + e.getMessage(), e);
}
}
}

View File

@ -1,31 +0,0 @@
package org.rehlds.flightrec.util;
import java.io.File;
import java.net.URL;
public class JarUtils {
public static File getJarFileOfClass(Class c) {
String classFileName = c.getName().replace('.', '/') + ".class";
ClassLoader classLoader = c.getClassLoader();
if (classLoader == null) {
classLoader = JarUtils.class.getClassLoader();
}
URL url = classLoader.getResource(classFileName);
if (url == null) {
return null;
}
String strUrl = url.toString();
if (!strUrl.startsWith("jar:file:/")) {
return null;
}
int jarSeparator = strUrl.indexOf('!');
if (jarSeparator == -1) {
return null;
}
String jarFilePath = strUrl.substring("jar:file:/".length(), jarSeparator);
return new File(jarFilePath);
}
}

View File

@ -1,181 +0,0 @@
package org.rehlds.flightrec.logtree
import org.junit.Test
import org.rehlds.flightrec.api.EntranceKind
import org.rehlds.flightrec.api.FlightrecMessage
import org.rehlds.flightrec.api.FlightrecMessageType
class FlightLogTreeBuilderTest {
static final FlightrecMessageType hierarchyMsgType1 = new FlightrecMessageType('test', 'hmsg1', 1, true);
static final FlightrecMessageType hierarchyMsgType2 = new FlightrecMessageType('test', 'hmsg1', 1, true);
static final FlightrecMessageType flatMsgType1 = new FlightrecMessageType('test', 'flatmsg1', 1, true);
static final FlightrecMessageType flatMsgType2 = new FlightrecMessageType('test', 'flatmsg2', 1, true);
static FlightrecMessage enterMsg(FlightrecMessageType type) {
return new FlightrecMessage(type, EntranceKind.ENTRANCE_ENTER, null, 0, 0);
}
static FlightrecMessage leaveMsg(FlightrecMessageType type) {
return new FlightrecMessage(type, EntranceKind.ENTRANCE_LEAVE, null, 0, 0);
}
static FlightrecMessage flatMsg(FlightrecMessageType type) {
return new FlightrecMessage(type, EntranceKind.ENTRANCE_UNUSED, null, 0, 0);
}
@Test
void 'decode 2 flat messages'() {
def messages = [flatMsg(flatMsgType1), flatMsg(flatMsgType2)]
def rootNode = FlightLogTreeBuilder.buildTree(messages)
assert rootNode.children.size() == 2
assert rootNode.children[0].msg == messages[0];
assert rootNode.children[1].msg == messages[1];
assert rootNode.enterMsg == null
assert rootNode.leaveMsg == null
}
@Test
void 'decode 2 empty hierarchy msgs'() {
def messages = [
enterMsg(hierarchyMsgType1), leaveMsg(hierarchyMsgType1),
enterMsg(hierarchyMsgType2), leaveMsg(hierarchyMsgType2)
]
def rootNode = FlightLogTreeBuilder.buildTree(messages)
assert rootNode.children.size() == 2
rootNode.children[0].enterMsg == messages[0]
rootNode.children[0].leaveMsg == messages[1]
assert rootNode.children[0].children.empty
rootNode.children[1].enterMsg == messages[2]
rootNode.children[1].leaveMsg == messages[3]
assert rootNode.children[1].children.empty
assert rootNode.enterMsg == null
assert rootNode.leaveMsg == null
}
@Test
void 'decode 2 hierarchy messages with flat payload'() {
def messages = [
enterMsg(hierarchyMsgType1), flatMsg(flatMsgType1), leaveMsg(hierarchyMsgType1),
enterMsg(hierarchyMsgType2), flatMsg(flatMsgType2), leaveMsg(hierarchyMsgType2)
]
def rootNode = FlightLogTreeBuilder.buildTree(messages)
assert rootNode.children.size() == 2
rootNode.children[0].enterMsg == messages[0]
rootNode.children[0].leaveMsg == messages[2]
assert rootNode.children[0].children.size() == 1
assert rootNode.children[0].children[0].msg == messages[1]
rootNode.children[1].enterMsg == messages[3]
rootNode.children[1].leaveMsg == messages[5]
assert rootNode.children[1].children.size() == 1
assert rootNode.children[1].children[0].msg == messages[4]
assert rootNode.enterMsg == null
assert rootNode.leaveMsg == null
}
@Test
void 'decode hierarchical message with mixed payload'() {
def messages = [
flatMsg(flatMsgType2),
enterMsg(hierarchyMsgType1),
flatMsg(flatMsgType1),
enterMsg(hierarchyMsgType2),
flatMsg(flatMsgType2),
leaveMsg(hierarchyMsgType2),
flatMsg(flatMsgType2),
leaveMsg(hierarchyMsgType1),
flatMsg(flatMsgType1)
]
def rootNode = FlightLogTreeBuilder.buildTree(messages)
assert rootNode.children.size() == 3
assert rootNode.enterMsg == null
assert rootNode.leaveMsg == null
assert rootNode.children[0].msg == messages[0]
assert rootNode.children[2].msg == messages[8]
assert rootNode.children[1].enterMsg == messages[1]
assert rootNode.children[1].leaveMsg == messages[7]
assert rootNode.children[1].children.size() == 3
assert rootNode.children[1].children[0].msg == messages[2]
assert rootNode.children[1].children[2].msg == messages[6]
assert rootNode.children[1].children[1].enterMsg == messages[3]
assert rootNode.children[1].children[1].leaveMsg == messages[5]
assert rootNode.children[1].children[1].children.size() == 1
assert rootNode.children[1].children[1].children[0].msg == messages[4]
}
@Test
void 'decode hierarchical msg with flat payload and missing start'() {
def messages = [
flatMsg(flatMsgType1),
leaveMsg(hierarchyMsgType1),
flatMsg(flatMsgType2)
]
def rootNode = FlightLogTreeBuilder.buildTree(messages)
assert rootNode.children.size() == 2
assert rootNode.enterMsg == null
assert rootNode.leaveMsg == null
assert rootNode.children[0].enterMsg == null
assert rootNode.children[0].leaveMsg == messages[1]
assert rootNode.children[0].children.size() == 1
assert rootNode.children[0].children[0].msg == messages[0]
assert rootNode.children[1].msg == messages[2]
}
@Test
void 'decode empty hierarchical msg with missing start'() {
def messages = [
leaveMsg(hierarchyMsgType1),
flatMsg(flatMsgType2)
]
def rootNode = FlightLogTreeBuilder.buildTree(messages)
assert rootNode.children.size() == 2
assert rootNode.enterMsg == null
assert rootNode.leaveMsg == null
assert rootNode.children[0].enterMsg == null
assert rootNode.children[0].leaveMsg == messages[0]
assert rootNode.children[0].children.empty
assert rootNode.children[1].msg == messages[1]
}
@Test
void 'decode hierarchical msg with flat payload and missing end'() {
def messages = [
flatMsg(flatMsgType1),
enterMsg(hierarchyMsgType1),
flatMsg(flatMsgType2)
]
def rootNode = FlightLogTreeBuilder.buildTree(messages)
assert rootNode.children.size() == 2
assert rootNode.enterMsg == null
assert rootNode.leaveMsg == null
assert rootNode.children[0].msg == messages[0]
assert rootNode.children[1].enterMsg == messages[1]
assert rootNode.children[1].leaveMsg == null
assert rootNode.children[1].children.size() == 1
assert rootNode.children[1].children[0].msg == messages[2]
}
}

View File

@ -1,43 +0,0 @@
package com.google.cloud;
import org.junit.Test;
import static org.junit.Assert.*;
public class Crc32cTest {
static class TestData {
public String src;
public long hash;
TestData(String src, long hash) {
this.src = src;
this.hash = hash;
}
}
@Test
public void testCrc32c() {
TestData testData[] = {
new TestData("a", 0x93AD1061L),
new TestData("ab", 0x13C35EE4L),
new TestData("abc", 0x562F9CCDL),
new TestData("abcd", 0xDAAF41F6L),
new TestData("abcde", 0x8122A0A2L),
new TestData("abcdef", 0x0496937BL),
new TestData("abcdefg", 0x5D199E2CL),
new TestData("abcdefgh", 0x86BC933DL),
new TestData("abcdefghi", 0x9639F15FL),
new TestData("abcdefghij", 0x0584645CL),
};
for (TestData t : testData) {
Crc32c crc32c = new Crc32c();
crc32c.update(t.src.getBytes());
long cksum = crc32c.getValue();
assertEquals(t.hash, cksum);
}
}
}

View File

@ -1,74 +0,0 @@
apply plugin: 'java'
apply plugin: 'maven-publish'
group = 'org.rehlds.flightrec'
version = rootProject.version
sourceCompatibility = '1.7'
targetCompatibility = '1.7'
repositories {
mavenCentral()
}
dependencies {
testCompile "junit:junit:4.12"
}
publishing {
publications {
maven(MavenPublication) {
version project.version
artifactId 'decoder-api'
artifact jar
pom.withXml {
asNode().children().last() + {
resolveStrategy = DELEGATE_FIRST
name 'decoder-api'
description project.description
//url github
//scm {
// url "${github}.git"
// connection "scm:git:${github}.git"
//}
/*
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution 'repo'
}
}
developers {
developer {
id 'dreamstalker'
name 'dreamstalker'
}
}
*/
}
}
}
}
}
publishing {
repositories {
maven {
if (project.version.contains('dev')) {
url "http://nexus.rehlds.org/nexus/content/repositories/rehlds-dev/"
} else {
url "http://nexus.rehlds.org/nexus/content/repositories/rehlds-releases/"
}
credentials {
username rootProject.repoCreds.getProperty('username')
password rootProject.repoCreds.getProperty('password')
}
}
}
}
tasks.withType(AbstractCompile) {
options.encoding = 'UTF-8'
}

View File

@ -1,28 +0,0 @@
package org.rehlds.flightrec.api;
public class DecodedExtraData {
public ImmutablePair<String, String>[] data;
public DecodedExtraData(ImmutablePair<String, String>[] data) {
this.data = data;
}
public static final DecodedExtraData EMPTY = new DecodedExtraData(new ImmutablePair[0]);
public static DecodedExtraData create(String... args) {
if ((args.length % 2) == 1) {
throw new RuntimeException("DecodedExtraData.create: number of arguments must be even");
}
int numPairs = args.length / 2;
DecodedExtraData res = new DecodedExtraData(new ImmutablePair[numPairs]);
for (int i = 0; i < numPairs; i++) {
res.data[i] = new ImmutablePair<>(args[i * 2], args[i * 2 + 1]);
}
return res;
}
}

View File

@ -1,7 +0,0 @@
package org.rehlds.flightrec.api;
public interface DecoderModule {
public MessageDecoder lookupDecoder(FlightrecMessageType msgType);
public String getDescription();
public String getVersion();
}

View File

@ -1,7 +0,0 @@
package org.rehlds.flightrec.api;
public enum EntranceKind {
ENTRANCE_ENTER,
ENTRANCE_LEAVE,
ENTRANCE_UNUSED,
}

View File

@ -1,35 +0,0 @@
package org.rehlds.flightrec.api;
import org.rehlds.flightrec.api.util.UtilByteBuffer;
import org.rehlds.flightrec.api.util.UtilSizeBuf;
public class FlightrecMessage {
public final FlightrecMessageType messageType;
public final EntranceKind entranceKind;
public final byte[] rawData;
public final int rawDataPos;
public final int rawDataLen;
DecodedExtraData decodedData;
public FlightrecMessage(FlightrecMessageType messageType, EntranceKind entranceKind, byte[] rawData, int rawDataOffset, int rawDataLen) {
this.messageType = messageType;
this.entranceKind = entranceKind;
this.rawData = rawData;
this.rawDataPos = rawDataOffset;
this.rawDataLen = rawDataLen;
}
public UtilSizeBuf getDataSizebuf() {
return new UtilSizeBuf("msg: '" + messageType + "' @" + rawDataPos, new UtilByteBuffer(rawData), rawDataPos, rawDataLen);
}
public boolean isEnterMessage() {
return (entranceKind == EntranceKind.ENTRANCE_ENTER);
}
public boolean isLeaveMessage() {
return (entranceKind == EntranceKind.ENTRANCE_LEAVE);
}
}

View File

@ -1,22 +0,0 @@
package org.rehlds.flightrec.api;
public class FlightrecMessageDef {
public final FlightrecMessageType msgType;
public final int opcode;
public FlightrecMessageDef(String module, String message, long version, boolean inout, int opcode) {
msgType = new FlightrecMessageType(module, message, version, inout);
this.opcode = opcode;
}
@Override
public String toString() {
return "FlightrecMessageDef{" +
"module='" + msgType.module + '\'' +
", message='" + msgType.message + '\'' +
", version=" + msgType.version +
", inout=" + msgType.inout +
", opcode=" + opcode +
'}';
}
}

View File

@ -1,49 +0,0 @@
package org.rehlds.flightrec.api;
public class FlightrecMessageType {
public final String module;
public final String message;
public final long version;
public final boolean inout;
public FlightrecMessageType(String module, String message, long version, boolean inout) {
this.module = module;
this.message = message;
this.version = version;
this.inout = inout;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FlightrecMessageType that = (FlightrecMessageType) o;
if (inout != that.inout) return false;
if (version != that.version) return false;
if (!message.equals(that.message)) return false;
if (!module.equals(that.module)) return false;
return true;
}
@Override
public int hashCode() {
int result = module.hashCode();
result = 31 * result + message.hashCode();
result = 31 * result + (int) (version ^ (version >>> 32));
result = 31 * result + (inout ? 1 : 0);
return result;
}
@Override
public String toString() {
return "FlightrecMessageType{" +
"module='" + module + '\'' +
", message='" + message + '\'' +
", version=" + version +
", inout=" + inout +
'}';
}
}

View File

@ -1,11 +0,0 @@
package org.rehlds.flightrec.api;
public class ImmutablePair<T, U> {
public final T first;
public final U second;
public ImmutablePair(T first, U second) {
this.first = first;
this.second = second;
}
}

View File

@ -1,6 +0,0 @@
package org.rehlds.flightrec.api;
public interface MessageDecoder {
FlightrecMessageType getMessageType();
DecodedExtraData decode(FlightrecMessage msg);
}

View File

@ -1,35 +0,0 @@
package org.rehlds.flightrec.api;
import java.util.HashMap;
import java.util.Map;
public class SimpleDecoderModule implements DecoderModule {
Map<FlightrecMessageType, MessageDecoder> decoders = new HashMap<>();
public final String description;
public final String version;
public SimpleDecoderModule(String description, String version) {
this.description = description;
this.version = version;
}
@Override
public MessageDecoder lookupDecoder(FlightrecMessageType msgType) {
return decoders.get(msgType);
}
@Override
public String getDescription() {
return description;
}
@Override
public String getVersion() {
return version;
}
public void registerDecoder(MessageDecoder msgDecoder) {
decoders.put(msgDecoder.getMessageType(), msgDecoder);
}
}

View File

@ -1,8 +0,0 @@
package org.rehlds.flightrec.api.util;
import java.nio.charset.Charset;
public class Globals {
public static final Charset UTF8 = Charset.forName("UTF-8");
}

View File

@ -1,10 +0,0 @@
package org.rehlds.flightrec.api.util;
public class SizebufOverflowException extends RuntimeException {
public final String sizebufName;
public SizebufOverflowException(String sizebufName) {
super(sizebufName + " overflowed");
this.sizebufName = sizebufName;
}
}

View File

@ -1,79 +0,0 @@
package org.rehlds.flightrec.api.util;
public class UtilByteBuffer {
byte data[];
public UtilByteBuffer(byte[] data) {
this.data = data;
}
public byte[] getData() {
return data;
}
public UtilByteBuffer cutLeft(int newStart) {
byte[] newData = new byte[data.length - newStart];
System.arraycopy(data, newStart, newData, 0, data.length - newStart);
return new UtilByteBuffer(newData);
}
public int getDataLength() {
return data.length;
}
public int readUInt8(int pos) {
return data[pos] & 0xFF;
}
public boolean readBool(int pos) {
return data[pos] != 0;
}
public int readUInt16(int pos) {
return (data[pos] & 0xFF) | ((data[pos + 1] & 0xFF) << 8);
}
public long readUInt32(int pos) {
return (data[pos] & 0xFF) | ((data[pos + 1] & 0xFF) << 8) | ((data[pos + 2] & 0xFF) << 16) | ((long)(data[pos + 3] & 0xFF) << 24);
}
public int readInt32(int pos) {
return (data[pos] & 0xFF) | ((data[pos + 1] & 0xFF) << 8) | ((data[pos + 2] & 0xFF) << 16) | ((data[pos + 3] & 0xFF) << 24);
}
public long readInt64(int pos) {
long lowBits = readUInt32(pos);
long highBits = readUInt32(pos + 4);
return lowBits | (highBits << 32);
}
public double readDouble(int pos) {
long bits = readInt64(pos);
return Double.longBitsToDouble(bits);
}
public float readFloat(int pos) {
int bits = readInt32(pos);
return Float.intBitsToFloat(bits);
}
public String readString(int pos) {
return readString(pos, data.length - pos, true);
}
public String readString(int pos, int maxSize, boolean errorOnMaxSizeHit) {
int iMax = Math.min(data.length, pos + maxSize);
for (int i = pos; i < iMax; i++) {
if (data[i] == 0) {
return new String(data, pos, i - pos, Globals.UTF8);
}
}
if (errorOnMaxSizeHit) {
return null;
}
return new String(data, pos, iMax - pos, Globals.UTF8);
}
}

View File

@ -1,159 +0,0 @@
package org.rehlds.flightrec.api.util;
public class UtilSizeBuf {
String name;
UtilByteBuffer buf;
int startPos;
int maxSize;
int curPos;
public UtilSizeBuf(String name, UtilByteBuffer buf, int startPos, int maxSize) {
this.name = name;
this.buf = buf;
this.startPos = startPos;
this.maxSize = maxSize;
curPos = 0;
}
public UtilSizeBuf(String name, UtilByteBuffer buf) {
this(name, buf, 0, buf.getDataLength());
}
public void init(int startPos, int maxSize) {
this.startPos = startPos;
this.maxSize = maxSize;
curPos = 0;
}
public void reset() {
this.curPos = 0;
}
public int tell() {
return curPos;
}
public int getAbsoluteCurrentPos() {
return curPos + startPos;
}
public void skip(int count) {
if (curPos + count > maxSize) {
curPos = maxSize;
throw new SizebufOverflowException(name);
}
curPos += count;
}
public int readUInt8() {
if (curPos + 1 > maxSize) {
curPos = maxSize;
throw new SizebufOverflowException(name);
}
int pos = curPos;
curPos++;
return buf.readUInt8(pos + this.startPos);
}
public boolean readBool() {
if (curPos + 1 > maxSize) {
curPos = maxSize;
throw new SizebufOverflowException(name);
}
int pos = curPos;
curPos++;
return buf.readBool(pos + this.startPos);
}
public int readUInt16() {
if (curPos + 2 > maxSize) {
curPos = maxSize;
throw new SizebufOverflowException(name);
}
int pos = curPos;
curPos += 2;
return buf.readUInt16(pos + this.startPos);
}
public long readUInt32() {
if (curPos + 4 > maxSize) {
curPos = maxSize;
throw new SizebufOverflowException(name);
}
int pos = curPos;
curPos += 4;
return buf.readUInt32(pos + this.startPos);
}
public int readInt32() {
if (curPos + 4 > maxSize) {
curPos = maxSize;
throw new SizebufOverflowException(name);
}
int pos = curPos;
curPos += 4;
return buf.readInt32(pos + this.startPos);
}
public long readInt64() {
if (curPos + 8 > maxSize) {
curPos = maxSize;
throw new SizebufOverflowException(name);
}
int pos = curPos;
curPos += 8;
return buf.readInt64(pos + this.startPos);
}
public double readDouble() {
if (curPos + 8 > maxSize) {
curPos = maxSize;
throw new SizebufOverflowException(name);
}
int pos = curPos;
curPos += 8;
return buf.readDouble(pos + this.startPos);
}
public float readFloat() {
if (curPos + 4 > maxSize) {
curPos = maxSize;
throw new SizebufOverflowException(name);
}
int pos = curPos;
curPos += 4;
return buf.readFloat(pos + this.startPos);
}
public String readString() {
String s = buf.readString(curPos + this.startPos);
if (s == null) {
curPos = maxSize;
throw new SizebufOverflowException(name);
}
curPos += s.getBytes(Globals.UTF8).length + 1;
return s;
}
public int getStartPos() {
return startPos;
}
public int getMaxSize() {
return maxSize;
}
public byte[] getBuffer() {
return buf.getData();
}
}

View File

@ -1,127 +0,0 @@
package org.rehlds.flightrec.util;
import org.junit.Test;
import org.rehlds.flightrec.api.util.UtilByteBuffer;
import static org.junit.Assert.*;
public class UtilByteBufferTest {
@Test
public void testReadUInt8() throws Exception {
byte data[] = { 0x10, 0x00, 0x7F, (byte)0x80, (byte)0xFF };
UtilByteBuffer bb = new UtilByteBuffer(data);
assertEquals(0x10, bb.readUInt8(0));
assertEquals(0x00, bb.readUInt8(1));
assertEquals(0x7F, bb.readUInt8(2));
assertEquals(0x80, bb.readUInt8(3));
assertEquals(0xFF, bb.readUInt8(4));
}
@Test
public void testReadUInt16() throws Exception {
byte data[] = { 0x10, 0x00, 0x7F, (byte)0x80, (byte)0xFF, 0x00 };
UtilByteBuffer bb = new UtilByteBuffer(data);
assertEquals(0x10, bb.readUInt16(0));
assertEquals(0x7F00, bb.readUInt16(1));
assertEquals(0x807F, bb.readUInt16(2));
assertEquals(0xFF80, bb.readUInt16(3));
assertEquals(0x00FF, bb.readUInt16(4));
}
@Test
public void testReadUInt32() throws Exception {
byte data[] = { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, (byte)0xFF, 0x00, 0x00, 0x00 };
UtilByteBuffer bb = new UtilByteBuffer(data);
assertEquals(0x10000000, bb.readUInt32(0));
assertEquals(0x100000, bb.readUInt32(1));
assertEquals(0x1000, bb.readUInt32(2));
assertEquals(0x10, bb.readUInt32(3));
assertEquals(0x0, bb.readUInt32(4));
assertEquals(0x7F000000, bb.readUInt32(5));
assertEquals(0x7F0000, bb.readUInt32(6));
assertEquals(0x7F00, bb.readUInt32(7));
assertEquals(0x7F, bb.readUInt32(8));
assertEquals(0xFF000000L, bb.readUInt32(9));
assertEquals(0xFF0000, bb.readUInt32(10));
assertEquals(0xFF00, bb.readUInt32(11));
assertEquals(0xFF, bb.readUInt32(12));
}
@Test
public void testReadInt32() throws Exception {
byte data[] = { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, (byte)0xFF, 0x00, 0x00, 0x00 };
UtilByteBuffer bb = new UtilByteBuffer(data);
assertEquals(0x10000000, bb.readInt32(0));
assertEquals(0x100000, bb.readInt32(1));
assertEquals(0x1000, bb.readInt32(2));
assertEquals(0x10, bb.readInt32(3));
assertEquals(0x0, bb.readInt32(4));
assertEquals(0x7F000000, bb.readInt32(5));
assertEquals(0x7F0000, bb.readInt32(6));
assertEquals(0x7F00, bb.readInt32(7));
assertEquals(0x7F, bb.readInt32(8));
assertEquals((int)0xFF000000, bb.readInt32(9));
assertEquals(0xFF0000, bb.readInt32(10));
assertEquals(0xFF00, bb.readInt32(11));
assertEquals(0xFF, bb.readInt32(12));
}
@Test
public void testReadInt64() throws Exception {
byte data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
UtilByteBuffer bb = new UtilByteBuffer(data);
assertEquals(0x1000000000000000L, bb.readInt64(0));
assertEquals(0x10000000000000L, bb.readInt64(1));
assertEquals(0x100000000000L, bb.readInt64(2));
assertEquals(0x1000000000L, bb.readInt64(3));
assertEquals(0x10000000L, bb.readInt64(4));
assertEquals(0x100000L, bb.readInt64(5));
assertEquals(0x1000L, bb.readInt64(6));
assertEquals(0x10L, bb.readInt64(7));
assertEquals(0x00L, bb.readInt64(8));
assertEquals(0x7F00000000000000L, bb.readInt64(9));
assertEquals(0x7F000000000000L, bb.readInt64(10));
assertEquals(0x7F0000000000L, bb.readInt64(11));
assertEquals(0x7F00000000L, bb.readInt64(12));
assertEquals(0x7F000000L, bb.readInt64(13));
assertEquals(0x7F0000L, bb.readInt64(14));
assertEquals(0x7F00L, bb.readInt64(15));
assertEquals(0x7FL, bb.readInt64(16));
assertEquals(0xFF00000000000000L, bb.readInt64(17));
assertEquals(0xFF000000000000L, bb.readInt64(18));
assertEquals(0xFF0000000000L, bb.readInt64(19));
assertEquals(0xFF00000000L, bb.readInt64(20));
assertEquals(0xFF000000L, bb.readInt64(21));
assertEquals(0xFF0000L, bb.readInt64(22));
assertEquals(0xFF00L, bb.readInt64(23));
assertEquals(0xFFL, bb.readInt64(24));
}
@Test
public void testReadString() throws Exception {
byte data[] = { 0x00, 0x41, 0x00, 0x41, 0x42, 0x00, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x69, 0x74, (byte)0xC3, (byte)0xA9, 0x00, 0x41, 0x42 };
UtilByteBuffer bb = new UtilByteBuffer(data);
assertEquals("", bb.readString(0));
assertEquals("A", bb.readString(1));
assertEquals("", bb.readString(2));
assertEquals("AB", bb.readString(3));
assertEquals("Publicité", bb.readString(6));
assertNull(bb.readString(17));
assertEquals("Public", bb.readString(6, 6, false));
assertNull(bb.readString(6, 6, true));
assertEquals("AB", bb.readString(17, 2, false));
assertNull(bb.readString(17, 2, true));
}
}

View File

@ -1,4 +0,0 @@
@echo off
call "%VS140COMNTOOLS%vcvarsqueryregistry.bat"
echo %UniversalCRTSdkDir%
echo %UCRTVersion%

View File

@ -1,3 +0,0 @@
majorVersion=3
minorVersion=7
maintenanceVersion=0

Binary file not shown.

View File

@ -1,6 +0,0 @@
#Sat Jun 06 16:31:05 BRT 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip

164
gradlew vendored
View File

@ -1,164 +0,0 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

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