2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-01-14 15:48:04 +03:00

Add project FileSystem_Stdio

This commit is contained in:
s1lent 2017-12-05 22:55:45 +07:00
parent dab2663e6c
commit 0daf12924d
No known key found for this signature in database
GPG Key ID: 0FE401DC73916B5C
38 changed files with 7896 additions and 958 deletions

View File

@ -38,6 +38,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Director", "..\rehlds\HLTV\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Proxy", "..\rehlds\HLTV\Proxy\msvc\Proxy.vcxproj", "{ADDFF069-D39D-4A1B-87C9-85A62B980547}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "filesystem_stdio", "..\rehlds\filesystem\FileSystem_Stdio\msvc\filesystem_stdio.vcxproj", "{A428392F-52FB-489E-87D8-623528C7F4F9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug Play|Win32 = Debug Play|Win32
@ -251,6 +253,28 @@ Global
{ADDFF069-D39D-4A1B-87C9-85A62B980547}.Test Fixes|Win32.Build.0 = Release|Win32
{ADDFF069-D39D-4A1B-87C9-85A62B980547}.Tests|Win32.ActiveCfg = Release|Win32
{ADDFF069-D39D-4A1B-87C9-85A62B980547}.Tests|Win32.Build.0 = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug Play|Win32.ActiveCfg = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug Play|Win32.Build.0 = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug Record|Win32.ActiveCfg = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug Record|Win32.Build.0 = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug Swds Play|Win32.ActiveCfg = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug Swds Play|Win32.Build.0 = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug Swds|Win32.ActiveCfg = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug Swds|Win32.Build.0 = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug|Win32.ActiveCfg = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug|Win32.Build.0 = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Release Play|Win32.ActiveCfg = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Release Play|Win32.Build.0 = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Release Swds Play|Win32.ActiveCfg = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Release Swds Play|Win32.Build.0 = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Release Swds|Win32.ActiveCfg = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Release Swds|Win32.Build.0 = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Release|Win32.ActiveCfg = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Release|Win32.Build.0 = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Test Fixes|Win32.ActiveCfg = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Test Fixes|Win32.Build.0 = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Tests|Win32.ActiveCfg = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Tests|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -62,6 +62,10 @@ task publishPrepareFiles {
_copyFile('publish/director.dll', 'publish/publishRoot/bin/win32/valve/dlls/director.dll')
_copyFile('publish/director.so', 'publish/publishRoot/bin/linux32/valve/dlls/director.so')
// FileSystem binaries
_copyFile('publish/filesystem_stdio.dll', 'publish/publishRoot/bin/win32/filesystem_stdio.dll')
_copyFile('publish/filesystem_stdio.so', 'publish/publishRoot/bin/linux32/filesystem_stdio.so')
// hlsdk
project.file('publish/publishRoot/hlsdk').mkdirs()
copy {

View File

@ -0,0 +1,158 @@
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.doomedsociety.gradlecpp.GradleCppUtils
import org.gradle.nativeplatform.NativeBinarySpec
import org.gradle.nativeplatform.NativeLibrarySpec
import org.gradle.nativeplatform.toolchain.VisualCpp
apply plugin: 'cpp'
apply plugin: IccCompilerPlugin
apply plugin: GccCompilerPlugin
void setupToolchain(NativeBinarySpec b) {
boolean useGcc = project.hasProperty("useGcc")
def cfg = rootProject.createToolchainConfig(b);
cfg.projectInclude(project, '/../..', '/src', '/../../common', '/../../public', '/../../public/rehlds');
cfg.singleDefines 'USE_BREAKPAD_HANDLER'
if (cfg instanceof MsvcToolchainConfig) {
cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig(
enabled: true,
pchHeader: 'precompiled.h',
pchSourceSet: 'filesystem_pch'
);
cfg.singleDefines('_CRT_SECURE_NO_WARNINGS')
cfg.compilerOptions.args '/Ob2', '/Oi', '/GF'
}
else if (cfg instanceof GccToolchainConfig) {
if (!useGcc) {
cfg.compilerOptions.pchConfig = new GccToolchainConfig.PrecompilerHeaderOptions(
enabled: true,
pchSourceSet: 'filesystem_pch'
);
}
cfg.compilerOptions.languageStandard = 'c++11'
cfg.defines([
'_strdup': 'strdup',
'_stricmp': 'strcasecmp',
'_strnicmp': 'strncasecmp',
'_vsnprintf': 'vsnprintf',
'_snprintf': 'snprintf',
'_unlink': 'unlink',
]);
if (useGcc) {
// Produce code optimized for the most common IA32/AMD64/EM64T processors.
// As new processors are deployed in the marketplace, the behavior of this option will change.
cfg.compilerOptions.args '-mtune=generic', '-Wno-write-strings', '-msse3', '-flto'
} else {
cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp'
}
cfg.compilerOptions.args '-fno-exceptions'
cfg.compilerOptions.interProceduralOptimizations = false;
cfg.linkerOptions.interProceduralOptimizations = false;
def funcToWrap = [
"freopen", "fopen", "fopen64", "open", "open64", "creat", "access",
"stat", "lstat", "scandir", "opendir", "__xstat", "__lxstat", "__xstat64", "__lxstat64",
"chmod", "chown", "lchown", "symlink", "link", "mknod", "mount", "unlink",
"mkfifo", "rename", "utime", "utimes", "mkdir", "rmdir"
];
funcToWrap.each {
cfg.linkerOptions.args "-Wl,-wrap," + it
}
}
ToolchainConfigUtils.apply(project, cfg, b);
}
model {
buildTypes {
release
}
platforms {
x86 {
architecture "x86"
}
}
toolChains {
visualCpp(VisualCpp) {
}
if (project.hasProperty("useGcc")) {
gcc(Gcc)
} else {
icc(Icc)
}
}
components {
filesystem(NativeLibrarySpec) {
targetPlatform 'x86'
baseName 'filesystem_stdio'
sources {
filesystem_main(CppSourceSet) {
source {
srcDir "src"
include "**/*.cpp"
exclude "precompiled.cpp"
}
}
filesystem_pch(CppSourceSet) {
source {
srcDir "src"
include "precompiled.cpp"
}
}
}
binaries.all {
NativeBinarySpec b -> project.setupToolchain(b)
}
}
}
}
task buildFinalize << {
if (GradleCppUtils.windows) {
return;
}
binaries.withType(SharedLibraryBinarySpec) {
def sharedBinary = it.getSharedLibraryFile();
if (sharedBinary.exists()) {
sharedBinary.renameTo(new File(sharedBinary.getParent() + "/" + sharedBinary.getName().replaceFirst("^lib", "")));
}
}
}
task buildFixes {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
task buildRelease {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
}
}
build.finalizedBy(buildFinalize);
buildFixes.finalizedBy(buildFinalize);
buildRelease.finalizedBy(buildFinalize);
// prevent static lib building
binaries.withType(StaticLibraryBinarySpec) { binary ->
buildable = false
}

View File

@ -0,0 +1,39 @@
@echo OFF
::
:: Post-build auto-deploy script
:: Create and fill PublishPath.txt file with path to deployment folder
:: I.e. PublishPath.txt should contain one line with a folder path
:: Call it so:
:: IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")
::
SET targetDir=%~1
SET targetName=%~2
SET targetExt=%~3
SET projectDir=%~4
SET destination=
IF NOT EXIST "%projectDir%\PublishPath.txt" (
ECHO No deployment path specified. Create PublishPath.txt near PostBuild.bat with paths on separate lines for auto deployment.
exit /B 0
)
FOR /f "tokens=* delims= usebackq" %%a IN ("%projectDir%\PublishPath.txt") DO (
ECHO Deploying to: %%a
IF NOT "%%a" == "" (
copy /Y "%targetDir%%targetName%%targetExt%" "%%a"
IF NOT ERRORLEVEL 1 (
IF EXIST "%targetDir%%targetName%.pdb" (
copy /Y "%targetDir%%targetName%.pdb" "%%a"
)
) ELSE (
ECHO PostBuild.bat ^(27^) : warning : Can't copy '%targetName%%targetExt%' to deploy path '%%a'
)
)
)
IF "%%a" == "" (
ECHO No deployment path specified.
)
exit /B 0

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "filesystem_stdio", "filesystem_stdio.vcxproj", "{A428392F-52FB-489E-87D8-623528C7F4F9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug|Win32.ActiveCfg = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Debug|Win32.Build.0 = Debug|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Release|Win32.ActiveCfg = Release|Win32
{A428392F-52FB-489E-87D8-623528C7F4F9}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,174 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{A428392F-52FB-489E-87D8-623528C7F4F9}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>filesystem_stdio</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '12.0'">v120_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140_xp</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<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>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_WINDOWS;USE_BREAKPAD_HANDLER;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(ProjectDir)..\src;$(ProjectDir)..\..\..\;$(ProjectDir)..\..\..\common;$(ProjectDir)..\..\..\public;$(ProjectDir)..\..\..\public\rehlds;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<WholeProgramOptimization>false</WholeProgramOptimization>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<MinimalRebuild>false</MinimalRebuild>
<FunctionLevelLinking>
</FunctionLevelLinking>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
</CustomBuildStep>
<CustomBuildStep>
<Message>Force build to run Pre-Build event</Message>
</CustomBuildStep>
<CustomBuildStep>
<Outputs>build.always.run</Outputs>
</CustomBuildStep>
<CustomBuildStep>
<Inputs>build.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MinSpace</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;_WINDOWS;USE_BREAKPAD_HANDLER;_CRT_SECURE_NO_WARNINGS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(ProjectDir)..\src;$(ProjectDir)..\..\..\;$(ProjectDir)..\..\..\common;$(ProjectDir)..\..\..\public;$(ProjectDir)..\..\..\public\rehlds;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild.bat" (CALL "$(ProjectDir)PostBuild.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
</CustomBuildStep>
<CustomBuildStep>
<Message>Force build to run Pre-Build event</Message>
</CustomBuildStep>
<CustomBuildStep>
<Outputs>build.always.run</Outputs>
</CustomBuildStep>
<CustomBuildStep>
<Inputs>build.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\hookers\filesystem\hooklist.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\hookers\filesystem\main.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\BaseFileSystem.cpp" />
<ClCompile Include="..\src\filesystem_helpers.cpp" />
<ClCompile Include="..\src\FileSystem_Stdio.cpp" />
<ClCompile Include="..\src\linux_support.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\pathmatch.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\precompiled.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\hookers\filesystem\hooklist.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\src\BaseFileSystem.h" />
<ClInclude Include="..\src\filesystem_helpers.h" />
<ClInclude Include="..\src\FileSystem_Stdio.h" />
<ClInclude Include="..\src\linux_support.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\src\precompiled.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="src">
<UniqueIdentifier>{3f7611e3-cf43-4956-a8a1-b6efbcf1a63d}</UniqueIdentifier>
</Filter>
<Filter Include="hookers">
<UniqueIdentifier>{cacc7b07-9ac2-42d5-bba3-14c061a19d11}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\BaseFileSystem.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\FileSystem_Stdio.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\linux_support.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\pathmatch.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\precompiled.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\public_amalgamation.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\filesystem_helpers.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\hookers\filesystem\hooklist.cpp">
<Filter>hookers</Filter>
</ClCompile>
<ClCompile Include="..\..\..\hookers\filesystem\main.cpp">
<Filter>hookers</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\BaseFileSystem.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\linux_support.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\precompiled.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\filesystem_helpers.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\..\hookers\filesystem\hooklist.h">
<Filter>hookers</Filter>
</ClInclude>
<ClInclude Include="..\src\FileSystem_Stdio.h">
<Filter>src</Filter>
</ClInclude>
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,378 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include <FileSystem.h>
#include "filesystem_helpers.h"
#ifdef _WIN32
#include <direct.h> // mkdir
#else
#include <unistd.h> // unlink
#include "linux_support.h"
// undo the prepended "_" 's
#define _chmod chmod
#define _stat stat
#define _alloca alloca
#define _S_IFDIR S_IFDIR
#define HANDLE int
#define INVALID_HANDLE_VALUE ((HANDLE)~0)
#endif // _WIN32
#include "utlsymbol.h"
class CBaseFileSystem: public IFileSystem {
public:
CBaseFileSystem();
virtual ~CBaseFileSystem() {};
// Mount and unmount the filesystem
virtual void Mount();
virtual void Unmount();
// opens a file
// if pathID is NULL, all paths will be searched for the file
virtual FileHandle_t Open(const char *pFileName, const char *pOptions, const char *pathID = 0L);
// open a file but force the data to come from the steam cache, NOT from disk
virtual FileHandle_t OpenFromCacheForRead(const char *pFileName, const char *pOptions, const char *pathID = 0L);
virtual void Close(FileHandle_t file);
virtual void Seek(FileHandle_t file, int pos, FileSystemSeek_t seekType);
virtual size_t Tell(FileHandle_t file);
virtual size_t Size(FileHandle_t file);
virtual size_t Size(const char *pFileName);
virtual bool IsOk(FileHandle_t file);
virtual void Flush(FileHandle_t file);
virtual bool EndOfFile(FileHandle_t file);
virtual int Read(void* pOutput, int size, FileHandle_t file);
virtual int Write(void const* pInput, int size, FileHandle_t file);
virtual char *ReadLine(char *pOutput, int maxChars, FileHandle_t file);
virtual int FPrintf(FileHandle_t file, const char *fmt, ...);
// direct filesystem buffer access
// returns a handle to a buffer containing the file data
// this is the optimal way to access the complete data for a file,
// since the file preloader has probably already got it in memory
virtual void *GetReadBuffer(FileHandle_t file, int *outBufferSize, bool failIfNotInCache);
virtual void ReleaseReadBuffer(FileHandle_t file, void *readBuffer);
// Gets the current working directory
virtual bool GetCurrentDirectory(char* pDirectory, int maxlen);
// this isn't implementable on STEAM as is.
virtual void CreateDirHierarchy(const char *path, const char *pathID);
// File I/O and info
virtual bool IsDirectory(const char *pFileName);
virtual const char *GetLocalPath(const char *pFileName, char *pLocalPath, int localPathBufferSize);
// Deletes a file
virtual void RemoveFile(const char *pRelativePath, const char *pathID);
// Remove all search paths (including write path?)
virtual void RemoveAllSearchPaths();
// Add paths in priority order (mod dir, game dir, ....)
// If one or more .pak files are in the specified directory, then they are
// added after the file system path
// If the path is the relative path to a .bsp file, then any previous .bsp file
// override is cleared and the current .bsp is searched for an embedded PAK file
// and this file becomes the highest priority search path (i.e., it's looked at first
// even before the mod's file system path).
virtual void AddSearchPath(const char *pPath, const char *pathID);
virtual bool RemoveSearchPath(const char *pPath);
virtual bool FileExists(const char *pFileName);
virtual long GetFileTime(const char *pFileName);
virtual void FileTimeToString(char* pStrip, int maxCharsIncludingTerminator, long fileTime);
// FindFirst/FindNext
virtual const char *FindFirst(const char *pWildCard, FileFindHandle_t *pHandle, const char *pathID = 0L);
virtual const char *FindNext(FileFindHandle_t handle);
virtual bool FindIsDirectory(FileFindHandle_t handle);
virtual void FindClose(FileFindHandle_t handle);
// Note: This is sort of a secondary feature; but it's really useful to have it here
virtual char *ParseFile(char* pFileBytes, char* pToken, bool* pWasQuoted);
// Returns true on success (based on current list of search paths, otherwise false if it can't be resolved)
virtual bool FullPathToRelativePath(const char *pFullpath, char *pRelative);
// Dump to printf/OutputDebugString the list of files that have not been closed
virtual void PrintOpenedFiles();
virtual void SetWarningFunc(WarningFunc_t pfnWarning);
virtual void SetWarningLevel(FileWarningLevel_t level);
// interface for custom pack files > 4Gb
virtual bool AddPackFile(const char *fullpath, const char *pathID);
FILE *Trace_FOpen(const char *filename, const char *options, bool bFromCache = false);
void Trace_FClose(FILE *fp);
void Trace_DumpUnclosedFiles();
// Purpose: Functions implementing basic file system behavior.
virtual FILE *FS_fopen(const char *filename, const char *options, bool bFromCache = false) = 0;
virtual void FS_fclose(FILE *fp) = 0;
virtual void FS_fseek(FILE *fp, int64_t pos, FileSystemSeek_t seekType) = 0;
virtual size_t FS_ftell(FILE *fp) = 0;
virtual int FS_feof(FILE *fp) = 0;
virtual size_t FS_fread(void *dest, size_t count, size_t size, FILE *fp) = 0;
virtual size_t FS_fwrite(const void *src, size_t count, size_t size, FILE *fp) = 0;
virtual size_t FS_vfprintf(FILE *fp, const char *fmt, va_list list) = 0;
virtual int FS_ferror(FILE *fp) = 0;
virtual int FS_fflush(FILE *fp) = 0;
virtual char *FS_fgets(char *dest, int destSize, FILE *fp) = 0;
virtual int FS_stat(const char *path, struct _stat *buf) = 0;
virtual HANDLE FS_FindFirstFile(char *findname, WIN32_FIND_DATA *dat) = 0;
virtual bool FS_FindNextFile(HANDLE handle, WIN32_FIND_DATA *dat) = 0;
virtual bool FS_FindClose(HANDLE handle) = 0;
virtual bool IsThreadSafe() = 0;
virtual bool IsFileImmediatelyAvailable(const char *pFileName) = 0;
protected:
// structures for building pack files
#pragma pack(1)
typedef struct
{
char name[56];
int filepos;
int filelen;
} packfile_t;
typedef struct
{
char id[4];
int dirofs;
int dirlen;
} packheader_t;
typedef struct
{
char name[112];
int64_t filepos;
int64_t filelen;
} packfile64_t;
typedef struct
{
char id[4];
int64_t dirofs;
int64_t dirlen;
} packheader64_t;
typedef struct
{
char id[8];
int64_t packheaderpos;
int64_t originalfilesize;
} packappenededheader_t;
#pragma pack()
// A Pack file directory entry:
class CPackFileEntry
{
public:
CUtlSymbol m_Name;
int64_t m_nPosition;
int64_t m_nLength;
};
class CFileHandle
{
public:
FILE* m_pFile;
bool m_bPack;
bool m_bErrorFlagged;
int64_t m_nStartOffset;
int64_t m_nLength;
long m_nFileTime;
};
enum { MAX_FILES_IN_PACK = 32768 };
class CSearchPath
{
public:
CSearchPath();
~CSearchPath();
// Path ID ("game", "mod", "gamebin") accessors.
void SetPathID(CUtlSymbol id);
const CUtlSymbol &GetPathID() const;
// Search path (c:\hl\hl) accessors.
void SetPath(CUtlSymbol id);
const CUtlSymbol &GetPath() const;
void SetWritePath(bool st);
bool IsAllowWrite() const;
bool IsPackFile() const;
bool IsMapPath() const;
private:
friend class CBaseFileSystem;
CUtlSymbol m_Path;
CUtlSymbol m_PathID;
bool m_bIsMapPath;
bool m_bIsPackFile;
long m_lPackFileTime;
CFileHandle* m_hPackFile;
int m_nNumPackFiles;
size_t m_iCurSearchFile;
bool m_bAllowWrite;
enum { MAX_ENTRY_PATH = 32 };
// Entries to the individual files stored inside the pack file.
CUtlRBTree<CPackFileEntry, int> m_PackFiles;
static bool PackFileLessFunc(CPackFileEntry const &src1, CPackFileEntry const &src2);
};
// Purpose: For tracking unclosed files
// NOTE: The symbol table could take up memory that we don't want to eat here.
// In that case, we shouldn't store them in a table, or we should store them as locally allocates stings
// so we can control the size
class COpenedFile
{
public:
COpenedFile();
~COpenedFile();
COpenedFile(COpenedFile const &src);
bool operator==(COpenedFile const &src) const;
void SetName(char const *name);
const char *GetName();
FILE *m_pFile;
char *m_pName;
};
struct FindData_t
{
WIN32_FIND_DATA m_FindData;
int m_CurrentSearchPathID;
int m_LimitedPathID;
CUtlVector<char> m_WildCardString;
HANDLE m_FindHandle;
};
virtual void AddSearchPathNoWrite(const char *pPath, const char *pathID);
void AddSearchPathInternal(const char *pPath, const char *pathID, bool bAllowWrite);
void Warning(FileWarningLevel_t level, const char *fmt, ...);
void FixSlashes(char *str);
void FixPath(char *str);
void StripFilename(char *path);
CSearchPath *GetWritePath(const char *pathID);
FileHandle_t FindFile(CSearchPath *path, const char *pFileName, const char *pOptions, bool bFromCache = false);
int FastFindFileSize(CSearchPath *path, const char *pFileName);
void RemoveAllMapSearchPaths();
void AddPackFiles(const char *pPath);
bool AddPackFileFromPath(const char *pPath, const char *pakfile, bool bCheckForAppendedPack, const char *pathID);
bool PreparePackFile(CSearchPath &packfile, int64_t offsetofpackinmetafile);
bool Prepare64BitPackFile(CSearchPath &packfile, int64_t offsetofpackinmetafile);
const char *SearchPakFile(const char *pWildCard, int currentSearchPathID, bool first = true);
bool FileInSearchPaths(const char *pSearchWildcard, const char *pFileName, int minSearchPathID, int maxSearchPathID);
bool FindNextFileHelper(FindData_t *pFindData);
const char *FindFirstHelper(const char *pWildCard, FileFindHandle_t *pHandle, int searchPath, FindData_t *pFindData);
public:
static CBaseFileSystem *s_pFileSystem;
protected:
CUtlVector<COpenedFile> m_OpenedFiles;
static bool OpenedFileLessFunc(COpenedFile const &src1, COpenedFile const &src2);
CUtlVector<FILE *> m_PackFileHandles;
CUtlVector<FindData_t> m_FindData;
CUtlVector<CSearchPath> m_SearchPaths;
FileWarningLevel_t m_fwLevel;
WarningFunc_t m_pfnWarning;
int m_nOpenCount;
};
// singleton accessor
CBaseFileSystem *BaseFileSystem();
// Inlines
inline void CBaseFileSystem::CSearchPath::SetPathID(CUtlSymbol sym)
{
m_PathID = sym;
}
inline const CUtlSymbol &CBaseFileSystem::CSearchPath::GetPathID() const
{
return m_PathID;
}
inline void CBaseFileSystem::CSearchPath::SetPath(CUtlSymbol id)
{
m_Path = id;
}
inline const CUtlSymbol &CBaseFileSystem::CSearchPath::GetPath() const
{
return m_Path;
}
inline void CBaseFileSystem::CSearchPath::SetWritePath(bool st)
{
m_bAllowWrite = st;
}
inline bool CBaseFileSystem::CSearchPath::IsAllowWrite() const
{
return m_bAllowWrite;
}
inline bool CBaseFileSystem::CSearchPath::IsPackFile() const
{
return m_bIsPackFile;
}
inline bool CBaseFileSystem::CSearchPath::IsMapPath() const
{
return m_bIsMapPath;
}

View File

@ -0,0 +1,232 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
CFileSystem_Stdio::CFileSystem_Stdio()
{
m_bMounted = false;
}
CFileSystem_Stdio::~CFileSystem_Stdio()
{
RemoveAllSearchPaths();
Trace_DumpUnclosedFiles();
}
void CFileSystem_Stdio::Mount()
{
m_bMounted = true;
CBaseFileSystem::Mount();
}
void CFileSystem_Stdio::Unmount()
{
m_bMounted = false;
CBaseFileSystem::Unmount();
}
// low-level filesystem wrapper
FILE *CFileSystem_Stdio::FS_fopen(const char *filename, const char *options, bool bFromCache)
{
FILE *tst = fopen(filename, options);
#ifndef _WIN32
if (!tst && !Q_strchr(options, 'w') && !Q_strchr(options, '+')) {
const char *file = findFileInDirCaseInsensitive(filename);
tst = fopen(filename, options);
}
#endif // _WIN32
return tst;
}
void CFileSystem_Stdio::FS_fclose(FILE *fp)
{
fclose(fp);
}
void CFileSystem_Stdio::FS_fseek(FILE *fp, int64_t pos, FileSystemSeek_t seekType)
{
fseek(fp, pos, seekType);
}
size_t CFileSystem_Stdio::FS_ftell(FILE *fp)
{
return ftell(fp);
}
int CFileSystem_Stdio::FS_feof(FILE *fp)
{
return feof(fp);
}
size_t CFileSystem_Stdio::FS_fread(void *dest, size_t count, size_t size, FILE *fp)
{
return fread(dest, count, size, fp);
}
size_t CFileSystem_Stdio::FS_fwrite(const void *src, size_t count, size_t size, FILE *fp)
{
return fwrite(src, count, size, fp);
}
size_t CFileSystem_Stdio::FS_vfprintf(FILE *fp, const char *fmt, va_list list)
{
return vfprintf(fp, fmt, list);
}
int CFileSystem_Stdio::FS_ferror(FILE *fp)
{
return ferror(fp);
}
int CFileSystem_Stdio::FS_fflush(FILE *fp)
{
return fflush(fp);
}
char *CFileSystem_Stdio::FS_fgets(char *dest, int destSize, FILE *fp)
{
return fgets(dest, destSize, fp);
}
int CFileSystem_Stdio::FS_stat(const char *path, struct _stat *buf)
{
int rt = _stat(path, buf);
#ifndef _WIN32
if (rt == -1)
{
const char *file = findFileInDirCaseInsensitive(path);
if (file) {
rt = _stat(file, buf);
}
}
#endif // _WIN32
return rt;
}
HANDLE CFileSystem_Stdio::FS_FindFirstFile(char *findname, WIN32_FIND_DATA *dat)
{
return ::FindFirstFile(findname, dat);
}
bool CFileSystem_Stdio::FS_FindNextFile(HANDLE handle, WIN32_FIND_DATA *dat)
{
return (::FindNextFile(handle, dat) != 0);
}
bool CFileSystem_Stdio::FS_FindClose(HANDLE handle)
{
return (::FindClose(handle) != 0);
}
bool CFileSystem_Stdio::IsThreadSafe()
{
return true;
}
bool CFileSystem_Stdio::IsFileImmediatelyAvailable(const char *pFileName)
{
return true;
}
void CFileSystem_Stdio::GetLocalCopy(const char *pFileName)
{
;
}
void CFileSystem_Stdio::LogLevelLoadFinished(const char *name)
{
;
}
void CFileSystem_Stdio::LogLevelLoadStarted(const char *name)
{
;
}
int CFileSystem_Stdio::HintResourceNeed(const char *hintlist, int forgetEverything)
{
return 0;
}
int CFileSystem_Stdio::PauseResourcePreloading()
{
return 0;
}
int CFileSystem_Stdio::ResumeResourcePreloading()
{
return 0;
}
int CFileSystem_Stdio::SetVBuf(FileHandle_t stream, char *buffer, int mode, long size)
{
CFileHandle *fh = reinterpret_cast<CFileHandle *>(stream);
if (!fh) {
Warning(FILESYSTEM_WARNING, "FS: Tried to SetVBuf NULL file handle!\n");
return 0;
}
return setvbuf(fh->m_pFile, buffer, mode, size);
}
void CFileSystem_Stdio::GetInterfaceVersion(char *p, int maxlen)
{
Q_strncpy(p, "Stdio", maxlen);
}
WaitForResourcesHandle_t CFileSystem_Stdio::WaitForResources(const char *resourcelist)
{
return (WaitForResourcesHandle_t)FILESYSTEM_INVALID_HANDLE;
}
bool CFileSystem_Stdio::GetWaitForResourcesProgress(WaitForResourcesHandle_t handle, float *progress, bool *complete)
{
if (progress) *progress = 0;
if (complete) *complete = true;
return false;
}
void CFileSystem_Stdio::CancelWaitForResources(WaitForResourcesHandle_t handle)
{
;
}
bool CFileSystem_Stdio::IsAppReadyForOfflinePlay(int appID)
{
return true;
}
#ifndef HOOK_FILESYSTEM
EXPOSE_SINGLE_INTERFACE(CFileSystem_Stdio, IFileSystem, FILESYSTEM_INTERFACE_VERSION);
#endif // HOOK_FILESYSTEM

View File

@ -0,0 +1,91 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "BaseFileSystem.h"
#include "linux_support.h"
class CFileSystem_Stdio: public CBaseFileSystem
{
public:
CFileSystem_Stdio();
virtual ~CFileSystem_Stdio();
// Mount and unmount the filesystem
virtual void Mount();
virtual void Unmount();
virtual void GetLocalCopy(const char *pFileName);
virtual void LogLevelLoadStarted(const char *name);
virtual void LogLevelLoadFinished(const char *name);
virtual int HintResourceNeed(const char *hintlist, int forgetEverything);
virtual int PauseResourcePreloading();
virtual int ResumeResourcePreloading();
virtual int SetVBuf(FileHandle_t stream, char *buffer, int mode, long size);
virtual void GetInterfaceVersion(char *p, int maxlen);
// starts waiting for resources to be available
// returns FILESYSTEM_INVALID_HANDLE if there is nothing to wait on
virtual WaitForResourcesHandle_t WaitForResources(const char *resourcelist);
// get progress on waiting for resources; progress is a float [0, 1], complete is true on the waiting being done
// returns false if no progress is available
// any calls after complete is true or on an invalid handle will return false, 0.0f, true
virtual bool GetWaitForResourcesProgress(WaitForResourcesHandle_t handle, float *progress /* out */ , bool *complete /* out */);
// cancels a progress call
virtual void CancelWaitForResources(WaitForResourcesHandle_t handle);
// returns true if the appID has all its caches fully preloaded
virtual bool IsAppReadyForOfflinePlay(int appID);
protected:
// implementation of CBaseFileSystem virtual functions
virtual FILE *FS_fopen(const char *filename, const char *options, bool bFromCache = false);
virtual void FS_fclose(FILE *fp);
virtual void FS_fseek(FILE *fp, int64_t pos, FileSystemSeek_t seekType);
virtual size_t FS_ftell(FILE *fp);
virtual int FS_feof(FILE *fp);
virtual size_t FS_fread(void *dest, size_t count, size_t size, FILE *fp);
virtual size_t FS_fwrite(const void *src, size_t count, size_t size, FILE *fp);
virtual size_t FS_vfprintf(FILE *fp, const char *fmt, va_list list);
virtual int FS_ferror(FILE *fp);
virtual int FS_fflush(FILE *fp);
virtual char *FS_fgets(char *dest, int destSize, FILE *fp);
virtual int FS_stat(const char *path, struct _stat *buf);
virtual HANDLE FS_FindFirstFile(char *findname, WIN32_FIND_DATA *dat);
virtual bool FS_FindNextFile(HANDLE handle, WIN32_FIND_DATA *dat);
virtual bool FS_FindClose(HANDLE handle);
virtual bool IsThreadSafe();
virtual bool IsFileImmediatelyAvailable(const char *pFileName);
private:
bool m_bMounted;
};

View File

@ -0,0 +1,178 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
// wordbreak parsing set
characterset_t g_BreakSet, g_BreakSetIncludingColons;
void InitializeCharacterSets()
{
static bool s_CharacterSetInitialized = false;
if (!s_CharacterSetInitialized)
{
CharacterSetBuild(&g_BreakSet, "{}()'");
CharacterSetBuild(&g_BreakSetIncludingColons, "{}()':");
s_CharacterSetInitialized = true;
}
}
const char *ParseFile(const char *pFileBytes, char *pToken, bool *pWasQuoted, characterset_t *pCharSet)
{
if (pWasQuoted)
*pWasQuoted = false;
if (!pFileBytes)
return nullptr;
InitializeCharacterSets();
// YWB: Ignore colons as token separators in COM_Parse
static const bool com_ignorecolons = false;
characterset_t &breaks = pCharSet ? *pCharSet : (com_ignorecolons ? g_BreakSet : g_BreakSetIncludingColons);
int c;
int len = 0;
pToken[0] = '\0';
skipwhite:
// skip whitespace
while ((c = *pFileBytes) <= ' ')
{
if (c == 0)
{
// end of file;
return nullptr;
}
pFileBytes++;
}
// skip // comments till the next line
if (c == '/' && pFileBytes[1] == '/')
{
while (*pFileBytes && *pFileBytes != '\n')
pFileBytes++;
goto skipwhite; // start over new line
}
// skip c-style comments
if (c == '/' && pFileBytes[1] == '*')
{
// Skip "/*"
pFileBytes += 2;
while (*pFileBytes)
{
if (*pFileBytes == '*' && pFileBytes[1] == '/')
{
pFileBytes += 2;
break;
}
pFileBytes++;
}
goto skipwhite;
}
// handle quoted strings specially: copy till the end or another quote
if (c == '\"')
{
if (pWasQuoted)
*pWasQuoted = true;
pFileBytes++; // skip starting quote
while (true)
{
c = *pFileBytes++; // get char and advance
if (!c) // EOL
{
pToken[len] = '\0';
return pFileBytes - 1; // we are done with that, but return data to show that token is present
}
if (c == '\"') // closing quote
{
pToken[len] = '\0';
return pFileBytes;
}
pToken[len++] = c;
}
}
// parse single characters
if (IN_CHARACTERSET(breaks, c))
{
pToken[len++] = c;
pToken[len] = '\0';
return pFileBytes + 1;
}
// parse a regular word
do
{
pToken[len++] = c;
pFileBytes++;
c = *pFileBytes;
if (IN_CHARACTERSET(breaks, c))
break;
}
while (c > 32);
pToken[len] = '\0';
return pFileBytes;
}
char *ParseFile(char *pFileBytes, char *pToken, bool *pWasQuoted)
{
return const_cast<char *>(ParseFile(static_cast<const char *>(pFileBytes), pToken, pWasQuoted));
}
void NORETURN FileSystem_SysError(const char *fmt, ...)
{
va_list argptr;
static char string[8192];
va_start(argptr, fmt);
vsnprintf(string, sizeof(string), fmt, argptr);
va_end(argptr);
printf("%s\n", string);
FILE* fl = fopen("filesystem_error.txt", "w");
fprintf(fl, "%s\n", string);
fclose(fl);
int *null = 0;
*null = 0;
exit(-1);
}

View File

@ -0,0 +1,36 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "tier0/characterset.h"
// Call until it returns nullptr. Each time you call it, it will parse out a token.
struct characterset_t;
const char *ParseFile(const char *pFileBytes, char *pToken, bool *pWasQuoted, characterset_t *pCharSet = nullptr);
char *ParseFile(char *pFileBytes, char *pToken, bool *pWasQuoted); // (same exact thing as the const version)
void NORETURN FileSystem_SysError(const char *fmt, ...);

View File

@ -0,0 +1,258 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
#if !defined(_WIN32)
char selectBuf[PATH_MAX];
int FileSelect(const struct dirent *ent)
{
const char *mask = selectBuf;
const char *name = ent->d_name;
//printf("Test:%s %s\n", mask, name);
if (!Q_strcmp(name, ".") || !Q_strcmp(name, ".."))
return 0;
if (!Q_strcmp(selectBuf, "*.*"))
return 1;
while (*mask && *name)
{
if (*mask == '*')
{
mask++; // move to the next char in the mask
if (!*mask) // if this is the end of the mask its a match
{
return 1;
}
while (*name && toupper(*name) != toupper(*mask))
{
// while the two don't meet up again
name++;
}
if (!*name)
{
// end of the name
break;
}
}
else if (*mask != '?')
{
if (toupper(*mask) != toupper(*name))
{
// mismatched!
return 0;
}
else
{
mask++;
name++;
if (!*mask && !*name)
{
// if its at the end of the buffer
return 1;
}
}
}
// mask is "?", we don't care
else
{
mask++;
name++;
}
}
// both of the strings are at the end
return (!*mask && !*name);
}
int FillDataStruct(FIND_DATA *dat)
{
char szFileName[MAX_PATH];
struct stat fileStat;
if (dat->numMatches < 0)
return -1;
Q_strlcpy(szFileName, dat->cDir);
Q_strlcat(szFileName, "/");
Q_strlcat(szFileName, dat->namelist[dat->numMatches]->d_name);
Q_strlcpy(dat->cFileName, dat->namelist[dat->numMatches]->d_name);
if (!stat(szFileName, &fileStat))
{
dat->dwFileAttributes = fileStat.st_mode;
}
else
{
dat->dwFileAttributes = 0;
}
// printf("%s\n", dat->namelist[dat->numMatches]->d_name);
free(dat->namelist[dat->numMatches]);
dat->numMatches--;
return 1;
}
int FindFirstFile(char *fileName, FIND_DATA *dat)
{
char nameStore[PATH_MAX];
char *dir = nullptr;
int n, iret = -1;
Q_strlcpy(nameStore, fileName);
if (Q_strrchr(nameStore, '/'))
{
dir = nameStore;
while (Q_strrchr(dir, '/'))
{
struct stat dirChk;
// zero this with the dir name
dir = Q_strrchr(nameStore, '/');
*dir = '\0';
dir = nameStore;
stat(dir, &dirChk);
if (S_ISDIR(dirChk.st_mode))
{
break;
}
}
}
else
{
// couldn't find a dir seperator...
return -1;
}
if (Q_strlen(dir) > 0)
{
Q_strlcpy(selectBuf, fileName + Q_strlen(dir) + 1);
Q_strlcpy(dat->cDir, dir);
n = scandir(dir, &dat->namelist, FileSelect, alphasort);
if (n < 0)
{
// silently return, nothing interesting
printf("scandir failed:%s\n", dir);
}
else
{
// n is the number of matches
dat->numMatches = n - 1;
iret = FillDataStruct(dat);
if (iret < 0)
{
free(dat->namelist);
}
}
}
// printf("Returning: %i \n", iret);
return iret;
}
bool FindNextFile(int handle, FIND_DATA *dat)
{
if (dat->numMatches < 0)
{
free(dat->namelist);
return false; // no matches left
}
FillDataStruct(dat);
return true;
}
bool FindClose(int handle)
{
return true;
}
static char fileName[MAX_PATH];
int CheckName(const struct dirent *dir)
{
return !Q_stricmp(dir->d_name, fileName);
}
const char *findFileInDirCaseInsensitive(const char *file)
{
const char *dirSep = Q_strrchr(file, '/');
if (!dirSep)
{
dirSep = Q_strrchr(file, '\\');
if (!dirSep)
{
return nullptr;
}
}
char *dirName = static_cast<char *>(alloca(((dirSep - file) + 1) * sizeof(char)));
if (!dirName) {
return nullptr;
}
Q_strncpy(dirName, file, dirSep - file);
dirName[dirSep - file] = '\0';
struct dirent **namelist;
int n;
Q_strlcpy(fileName, dirSep + 1);
n = scandir(dirName, &namelist, CheckName, alphasort);
if (n > 0)
{
while (n > 1)
{
// free the malloc'd strings
free(namelist[n]);
n--;
}
Q_snprintf(fileName, sizeof(fileName), "%s/%s", dirName, namelist[0]->d_name);
free(namelist[0]);
return fileName;
}
else
{
Q_strlcpy(fileName, file);
Q_strlwr(fileName);
return fileName;
}
}
#endif // #if !defined(_WIN32)

View File

@ -0,0 +1,62 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#ifndef _WIN32
#include <ctype.h> // tolower()
#include <limits.h> // PATH_MAX define
#include <string.h> // strcmp, strcpy
#include <sys/stat.h> // stat()
#include <unistd.h>
#include <dirent.h> // scandir()
#include <stdlib.h>
#include <stdio.h>
#define FILE_ATTRIBUTE_DIRECTORY S_IFDIR
typedef struct
{
// public data
int dwFileAttributes;
char cFileName[MAX_PATH]; // the file name returned from the call
int numMatches;
struct dirent **namelist;
char cDir[MAX_PATH];
} FIND_DATA;
#define WIN32_FIND_DATA FIND_DATA
int FindFirstFile(char *findName, FIND_DATA *dat);
bool FindNextFile(int handle, FIND_DATA *dat);
bool FindClose(int handle);
const char *findFileInDirCaseInsensitive(const char *file);
#endif // _WIN32

View File

@ -0,0 +1,898 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
* ------------------------------------------------------------------------------------
* This file implements the --wrap for ld on linux that lets file i/o api's
* behave as if it were running on a case insensitive file system. Unfortunately,
* this is needed by both steam2 and steam3. It was decided to check the source
* into both locations, otherwise someone would find the .o and have no idea
* where to go for the source if it was in the 'other' tree. Also, because this
* needs to be linked into every elf binary, the .o is checked in for Steam3 so that it is
* always available. In Steam2 it sits with the PosixWin32.cpp implementation and gets
* compiled along side of it through the make system. If you are reading this in Steam3,
* you will probably want to actually make your changes in steam2 and do a baseless merge
* to the steam3 copy.
*
* HOWTO: Add a new function. Add the function with _WRAP to the makefiles as noted below.
* Add the implementation to pathmatch.cpp - probably mimicking the existing functions.
* Build steam2 and copy to matching steam3/client. Take the pathmatch.o from steam 2
* and check it in to steam3 (in the location noted below). Full rebuild (re-link really)
* of steam3. Test steam and check in.
*
* If you are looking at updating this file, please update the following as needed:
*
* STEAM2.../Projects/GazelleProto/Client/Engine/obj/RELEASE_NORMAL/libsteam_linux/Common/Misc/pathmatch.o
* This is where steam2 builds the pathmatch.o out to.
*
* STEAM2.../Projects/GazelleProto/Makefile.shlib.base - contains _WRAP references
* STEAM2.../Projects/Common/Misc/pathmatch.cpp - Where the source is checked in, keep in sync with:
* STEAM3.../src/common/pathmatch.cpp - should be identical to previous file, but discoverable in steam3.
* STEAM3.../src/lib/linux32/release/pathmatch.o - steam3 checked in version
* STEAM3.../src/devtools/makefile_base_posix.mak - look for the _WRAP references
* ------------------------------------------------------------------------------------
*/
#include "precompiled.h"
#ifndef _WIN32
#include <stdint.h>
#include <strings.h>
#include <getopt.h>
#include <signal.h>
#include <dirent.h>
#include <sys/mount.h>
#include <fcntl.h>
#include <utime.h>
// Enable to do pathmatch caching. Beware: this code isn't threadsafe.
// #define DO_PATHMATCH_CACHE
#ifdef DO_PATHMATCH_CACHE
#include <map>
#endif
#ifdef UTF8_PATHMATCH
#define Q_stricmp utf8casecmp
#endif
static bool s_bShowDiag;
#define DEBUG_MSG(...) if (s_bShowDiag) fprintf(stderr, ##__VA_ARGS__)
#define DEBUG_BREAK() __asm__ __volatile__ ("int $3")
#define _COMPILE_TIME_ASSERT(pred) switch(0) {case 0:case pred:;}
#define WRAP(fn, ret, ...)\
ret __real_##fn(__VA_ARGS__);\
ret __wrap_##fn(__VA_ARGS__)
#define CALL(fn) __real_##fn
// Needed by pathmatch code
extern "C" int __real_access(const char *pathname, int mode);
extern "C" DIR *__real_opendir(const char *name);
// UTF-8 work from PhysicsFS: http://icculus.org/physfs/
// Even if it wasn't under the zlib license, Ryan wrote all this code originally.
#define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF
#define UNICODE_BOGUS_CHAR_CODEPOINT '?'
inline __attribute__((always_inline)) static uint32_t utf8codepoint(const char **_str)
{
const char *str = *_str;
uint32_t retval = 0;
uint32_t octet = (uint32_t)((uint8_t)*str);
uint32_t octet2, octet3, octet4;
// null terminator, end of string.
if (octet == 0)
return 0;
// one octet char: 0 to 127
else if (octet < 128)
{
(*_str)++; // skip to next possible start of codepoint.
return octet;
}
else if ((octet > 127) && (octet < 192)) // bad (starts with 10xxxxxx).
{
// Apparently each of these is supposed to be flagged as a bogus
// char, instead of just resyncing to the next valid codepoint.
(*_str)++; // skip to next possible start of codepoint.
return UNICODE_BOGUS_CHAR_VALUE;
}
else if (octet < 224) // two octets
{
octet -= (128 + 64);
octet2 = (uint32_t)((uint8_t)*(++str));
if ((octet2 & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
*_str += 2; // skip to next possible start of codepoint.
retval = ((octet << 6) | (octet2 - 128));
if ((retval >= 0x80) && (retval <= 0x7FF))
return retval;
}
else if (octet < 240) // three octets
{
octet -= (128 + 64 + 32);
octet2 = (uint32_t)((uint8_t)*(++str));
if ((octet2 & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet3 = (uint32_t)((uint8_t)*(++str));
if ((octet3 & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
*_str += 3; // skip to next possible start of codepoint.
retval = (((octet << 12)) | ((octet2 - 128) << 6) | ((octet3 - 128)));
// There are seven "UTF-16 surrogates" that are illegal in UTF-8.
switch (retval)
{
case 0xD800:
case 0xDB7F:
case 0xDB80:
case 0xDBFF:
case 0xDC00:
case 0xDF80:
case 0xDFFF:
return UNICODE_BOGUS_CHAR_VALUE;
}
// 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge.
if ((retval >= 0x800) && (retval <= 0xFFFD))
return retval;
}
else if (octet < 248) // four octets
{
octet -= (128 + 64 + 32 + 16);
octet2 = (uint32_t)((uint8_t)*(++str));
if ((octet2 & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet3 = (uint32_t)((uint8_t)*(++str));
if ((octet3 & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet4 = (uint32_t)((uint8_t)*(++str));
if ((octet4 & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
*_str += 4; // skip to next possible start of codepoint.
retval = (((octet << 18)) | ((octet2 - 128) << 12) | ((octet3 - 128) << 6) | ((octet4 - 128)));
if ((retval >= 0x10000) && (retval <= 0x10FFFF))
return retval;
}
// Five and six octet sequences became illegal in rfc3629.
// We throw the codepoint away, but parse them to make sure we move
// ahead the right number of bytes and don't overflow the buffer.
else if (octet < 252) // five octets
{
octet = (uint32_t)((uint8_t)*(++str));
if ((octet & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t)((uint8_t)*(++str));
if ((octet & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t)((uint8_t)*(++str));
if ((octet & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t)((uint8_t)*(++str));
if ((octet & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
*_str += 5; // skip to next possible start of codepoint.
return UNICODE_BOGUS_CHAR_VALUE;
}
else // six octets
{
octet = (uint32_t)((uint8_t)*(++str));
if ((octet & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t)((uint8_t)*(++str));
if ((octet & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t)((uint8_t)*(++str));
if ((octet & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t)((uint8_t)*(++str));
if ((octet & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t)((uint8_t)*(++str));
if ((octet & (128 + 64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
*_str += 6; // skip to next possible start of codepoint.
return UNICODE_BOGUS_CHAR_VALUE;
}
return UNICODE_BOGUS_CHAR_VALUE;
}
typedef struct CaseFoldMapping
{
uint32_t from;
uint32_t to0;
uint32_t to1;
uint32_t to2;
} CaseFoldMapping;
typedef struct CaseFoldHashBucket
{
const uint8_t count;
const CaseFoldMapping *list;
} CaseFoldHashBucket;
#include "pathmatch_casefolding.h"
inline static void locate_case_fold_mapping(const uint32_t from, uint32_t *to)
{
const uint8_t hashed = ((from ^ (from >> 8)) & 0xFF);
const CaseFoldHashBucket *bucket = &case_fold_hash[hashed];
const CaseFoldMapping *mapping = bucket->list;
uint32_t i;
for (i = 0; i < bucket->count; i++, mapping++)
{
if (mapping->from == from)
{
to[0] = mapping->to0;
to[1] = mapping->to1;
to[2] = mapping->to2;
return;
}
}
// Not found...there's no remapping for this codepoint.
to[0] = from;
to[1] = 0;
to[2] = 0;
}
inline static uint32_t *fold_utf8(const char *str)
{
uint32_t *retval = new uint32_t[(Q_strlen(str) * 3) + 1];
uint32_t *dst = retval;
while (*str)
{
const char ch = *str;
if (ch & 0x80) // high bit set? UTF-8 sequence!
{
uint32_t fold[3];
locate_case_fold_mapping(utf8codepoint(&str), fold);
*(dst++) = fold[0];
if (fold[1])
{
*(dst++) = fold[1];
if (fold[2])
*(dst++) = fold[2];
}
}
// simple ASCII test.
else
{
*(dst++) = (uint32_t) (((ch >= 'A') && (ch <= 'Z')) ? ch + 32 : ch);
str++;
}
}
*dst = 0;
return retval;
}
inline static int utf8casecmp_loop(const uint32_t *folded1, const uint32_t *folded2)
{
while (true)
{
const uint32_t ch1 = *(folded1++);
const uint32_t ch2 = *(folded2++);
if (ch1 < ch2)
return -1;
else if (ch1 > ch2)
return 1;
else if (ch1 == 0)
{
// complete match.
return 0;
}
}
}
static int utf8casecmp(const char *str1, const char *str2)
{
uint32_t *folded1 = fold_utf8(str1);
uint32_t *folded2 = fold_utf8(str2);
const int retval = utf8casecmp_loop(folded1, folded2);
delete[] folded1;
delete[] folded2;
return retval;
}
// Simple object to help make sure a DIR* from opendir
// gets closed when it goes out of scope.
class CDirPtr
{
public:
CDirPtr() { m_pDir = nullptr; }
CDirPtr(DIR *pDir) : m_pDir(pDir) {}
~CDirPtr() { Close(); }
void operator=(DIR *pDir) { Close(); m_pDir = pDir; }
operator DIR *() { return m_pDir; }
operator bool() { return m_pDir != nullptr; }
private:
void Close() { if (m_pDir) closedir(m_pDir); }
DIR *m_pDir;
};
// Object used to temporarily slice a path into a smaller componentent
// and then repair it when going out of scope. Typically used as an unnamed
// temp object that is a parameter to a function.
class CDirTrimmer
{
public:
CDirTrimmer(char *pPath, size_t nTrimIdx)
{
m_pPath = pPath;
m_idx = nTrimIdx;
m_c = m_pPath[nTrimIdx];
m_pPath[nTrimIdx] = '\0';
}
~CDirTrimmer() { m_pPath[m_idx] = m_c; }
operator const char *() { return m_pPath; }
private:
size_t m_idx;
char *m_pPath;
char m_c;
};
enum PathMod_t
{
kPathUnchanged,
kPathLowered,
kPathChanged,
kPathFailed,
};
static bool Descend(char *pPath, size_t nStartIdx, bool bAllowBasenameMismatch, size_t nLevel = 0)
{
DEBUG_MSG("(%zu) Descend: %s, (%s), %s\n", nLevel, pPath, pPath + nStartIdx, bAllowBasenameMismatch ? "true" : "false ");
// We assume up through nStartIdx is valid and matching
size_t nNextSlash = nStartIdx + 1;
// path might be a dir
if (pPath[nNextSlash] == '\0') {
return true;
}
bool bIsDir = false; // is the new component a directory for certain?
while (pPath[nNextSlash] != '\0' && pPath[nNextSlash] != '/') {
nNextSlash++;
}
// Modify the pPath string
if (pPath[nNextSlash] == '/') {
bIsDir = true;
}
// See if we have an immediate match
if (__real_access(CDirTrimmer(pPath, nNextSlash), F_OK) == 0)
{
if (!bIsDir) {
return true;
}
bool bRet = Descend(pPath, nNextSlash, bAllowBasenameMismatch, nLevel + 1);
if (bRet) {
return true;
}
}
// Start enumerating dirents
CDirPtr spDir;
if (nStartIdx)
{
// we have a path
spDir = __real_opendir(CDirTrimmer(pPath, nStartIdx));
nStartIdx++;
}
else
{
// we either start at root or cwd
const char *pRoot = ".";
if (*pPath == '/')
{
pRoot = "/";
nStartIdx++;
}
spDir = __real_opendir(pRoot);
}
errno = 0;
struct dirent *pEntry = spDir ? readdir(spDir) : nullptr;
char *pszComponent = pPath + nStartIdx;
size_t cbComponent = nNextSlash - nStartIdx;
while (pEntry)
{
DEBUG_MSG("\t(%zu) comparing %s with %s\n", nLevel, pEntry->d_name, (const char *)CDirTrimmer(pszComponent, cbComponent));
// the candidate must match the target, but not be a case-identical match (we would
// have looked there in the short-circuit code above, so don't look again)
bool bMatches = (Q_stricmp(CDirTrimmer(pszComponent, cbComponent), pEntry->d_name) == 0 &&
Q_strcmp(CDirTrimmer(pszComponent, cbComponent), pEntry->d_name) != 0);
if (bMatches)
{
char *pSrc = pEntry->d_name;
char *pDst = &pPath[nStartIdx];
// found a match; copy it in.
while (*pSrc && (*pSrc != '/')) {
*pDst++ = *pSrc++;
}
if (!bIsDir)
return true;
if (Descend(pPath, nNextSlash, bAllowBasenameMismatch, nLevel + 1))
return true;
// If descend fails, try more directories
}
pEntry = readdir(spDir);
}
if (bIsDir) {
DEBUG_MSG("(%zu) readdir failed to find '%s' in '%s'\n", nLevel, (const char *)CDirTrimmer(pszComponent, cbComponent), (const char *)CDirTrimmer(pPath, nStartIdx));
}
// Sometimes it's ok for the filename portion to not match
// since we might be opening for write. Note that if
// the filename matches case insensitive, that will be
// preferred over preserving the input name
if (!bIsDir && bAllowBasenameMismatch) {
return true;
}
return false;
}
char *GetSteamContentPath()
{
char szContentLink[4096];
Q_snprintf(szContentLink, sizeof(szContentLink), "%s/.steam/steam", getenv("HOME"));
char *pszContentPath = realpath(szContentLink, nullptr);
if (pszContentPath) {
Q_strcat(pszContentPath, "/");
}
else {
pszContentPath = Q_strdup("/");
}
return pszContentPath;
}
#ifdef DO_PATHMATCH_CACHE
typedef std::map<std::string, std::pair<std::string, time_t> > resultCache_t;
typedef std::map<std::string, std::pair<std::string, time_t> >::iterator resultCacheItr_t;
static resultCache_t resultCache;
static const int k_cMaxCacheLifetimeSeconds = 2;
#endif // DO_PATHMATCH_CACHE
PathMod_t pathmatch(const char *pszIn, char **ppszOut, bool bAllowBasenameMismatch, char *pszOutBuf, size_t OutBufLen)
{
static const char *s_pszDbgPathMatch = getenv("DBG_PATHMATCH");
s_bShowDiag = (s_pszDbgPathMatch != nullptr);
*ppszOut = nullptr;
if (__real_access(pszIn, F_OK) == 0)
return kPathUnchanged;
#ifdef DO_PATHMATCH_CACHE
resultCacheItr_t cachedResult = resultCache.find(pszIn);
if (cachedResult != resultCache.end())
{
unsigned int age = time(nullptr) - cachedResult->second.second;
const char *pszResult = cachedResult->second.first.c_str();
if (pszResult[0] != '\0' || age <= k_cMaxCacheLifetimeSeconds)
{
if (pszResult[0] != '\0')
{
*ppszOut = Q_strdup(pszResult);
DEBUG_MSG("Cached '%s' -> '%s'\n", pszIn, *ppszOut);
return kPathChanged;
}
else
{
DEBUG_MSG("Cached '%s' -> kPathFailed\n", pszIn);
return kPathFailed;
}
}
else if (age <= k_cMaxCacheLifetimeSeconds)
{
DEBUG_MSG("Rechecking '%s' - cache is %u seconds old\n", pszIn, age);
}
}
#endif // DO_PATHMATCH_CACHE
char *pPath;
if (Q_strlen(pszIn) >= OutBufLen)
{
pPath = Q_strdup(pszIn);
}
else
{
Q_strncpy(pszOutBuf, pszIn, OutBufLen);
pPath = pszOutBuf;
}
if (pPath)
{
// optimization, if the path contained steam somewhere
// assume the path up through the component with 'steam' in
// is valid (because we almost certainly obtained it
// progamatically
size_t nStartIdx = 0;
static char *pszSteamPath = nullptr;
static size_t nSteamPathLen = 0;
if (!pszSteamPath)
{
pszSteamPath = GetSteamContentPath();
nSteamPathLen = Q_strlen(pszSteamPath);
}
// optimization, if the path contained steam somewhere
// assume the path up through the component with 'steam' in
// is valid (because we almost certainly obtained it
// progamatically
if (strncasecmp(pPath, pszSteamPath, nSteamPathLen) == 0)
{
nStartIdx = nSteamPathLen - 1;
Q_memcpy(pPath, pszSteamPath, nStartIdx);
}
char *p = pPath;
// Try the lower casing of the remaining path
char *pBasename = p + nStartIdx;
while (*p)
{
if (*p == '/') {
pBasename = p + 1;
}
*p = tolower(*p);
p++;
}
if (__real_access(pPath, F_OK) == 0)
{
*ppszOut = pPath;
DEBUG_MSG("Lowered '%s' -> '%s'\n", pszIn, pPath);
return kPathLowered;
}
// path didn't match lowered successfully, restore the basename
// if bAllowBasenameMismatch was true
if (bAllowBasenameMismatch && *pBasename)
{
const char *pSrc = pszIn + (pBasename - pPath);
while (*pBasename)
{
*pBasename++ = *pSrc++;
}
}
if (s_pszDbgPathMatch && strcasestr(s_pszDbgPathMatch, pszIn))
{
DEBUG_MSG("Breaking '%s' in '%s'\n", pszIn, s_pszDbgPathMatch);
DEBUG_BREAK();
}
bool bSuccess = Descend(pPath, nStartIdx, bAllowBasenameMismatch);
if (bSuccess)
{
*ppszOut = pPath;
DEBUG_MSG("Matched '%s' -> '%s'\n", pszIn, pPath);
}
else
{
DEBUG_MSG("Unmatched %s\n", pszIn);
}
#ifndef DO_PATHMATCH_CACHE
return bSuccess ? kPathChanged : kPathFailed;
#else
time_t now = time(nullptr);
if (bSuccess)
{
resultCache[pszIn] = std::make_pair(*ppszOut, now);
return kPathChanged;
}
else
{
resultCache[pszIn] = std::make_pair("", now);
return kPathFailed;
}
#endif // DO_PATHMATCH_CACHE
}
return kPathFailed;
}
// Wrapper object that manages the 'typical' usage cases of pathmatch()
class CWrap
{
public:
CWrap(const char *pSuppliedPath, bool bAllowMismatchedBasename)
: m_pSuppliedPath(pSuppliedPath), m_pBestMatch(nullptr)
{
m_eResult = pathmatch(m_pSuppliedPath, &m_pBestMatch, bAllowMismatchedBasename, m_BestMatchBuf, sizeof(m_BestMatchBuf));
if (m_pBestMatch == nullptr)
{
m_pBestMatch = const_cast<char *>(m_pSuppliedPath);
}
}
~CWrap()
{
if ((m_pBestMatch != m_pSuppliedPath) && (m_pBestMatch != m_BestMatchBuf))
free(m_pBestMatch);
}
const char *GetBest() const { return m_pBestMatch; }
const char *GetOriginal() const { return m_pSuppliedPath; }
PathMod_t GetMatchResult() const { return m_eResult; }
operator const char*() { return GetBest(); }
private:
const char *m_pSuppliedPath;
char *m_pBestMatch;
char m_BestMatchBuf[512];
PathMod_t m_eResult;
};
extern "C" {
char *SteamRealPath(char *szOrigPath, char *szFinalPath, uint uiFinalPathCapacity)
{
char *szMatchPath = nullptr;
char szRealPath[MAX_PATH];
char szPathMatchBuf[MAX_PATH];
if (uiFinalPathCapacity > sizeof(szRealPath) || !uiFinalPathCapacity || !szFinalPath)
return nullptr;
PathMod_t pmStat = pathmatch(szOrigPath, &szMatchPath, true, szPathMatchBuf, sizeof(szPathMatchBuf));
if (pmStat != kPathFailed)
{
if (realpath(szMatchPath ? szMatchPath : szOrigPath, szRealPath) == szRealPath)
{
Q_strncpy(szFinalPath, szRealPath, uiFinalPathCapacity);
return szFinalPath;
}
}
return nullptr;
}
WRAP(freopen, FILE *, const char *path, const char *mode, FILE *stream)
{
// if mode does not have w, a, or +, it's open for read.
bool bAllowBasenameMismatch = strpbrk(mode, "wa+") != nullptr;
CWrap mpath(path, bAllowBasenameMismatch);
return CALL(freopen)(mpath, mode, stream);
}
WRAP(fopen, FILE *, const char *path, const char *mode)
{
// if mode does not have w, a, or +, it's open for read.
bool bAllowBasenameMismatch = strpbrk(mode, "wa+") != nullptr;
CWrap mpath(path, bAllowBasenameMismatch);
return CALL(fopen)(mpath, mode);
}
WRAP(fopen64, FILE *, const char *path, const char *mode)
{
// if mode does not have w, a, or +, it's open for read.
bool bAllowBasenameMismatch = strpbrk(mode, "wa+") != nullptr;
CWrap mpath(path, bAllowBasenameMismatch);
return CALL(fopen64)(mpath, mode);
}
WRAP(open, int, const char *pathname, int flags, mode_t mode)
{
bool bAllowBasenameMismatch = ((flags & (O_WRONLY | O_RDWR)) != 0);
CWrap mpath(pathname, bAllowBasenameMismatch);
return CALL(open)(mpath, flags, mode);
}
WRAP(open64, int, const char *pathname, int flags, mode_t mode)
{
bool bAllowBasenameMismatch = ((flags & (O_WRONLY | O_RDWR)) != 0);
CWrap mpath(pathname, bAllowBasenameMismatch);
return CALL(open64)(mpath, flags, mode);
}
int __wrap_creat(const char *pathname, mode_t mode)
{
return __wrap_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
}
int __wrap_access(const char *pathname, int mode)
{
return __real_access(CWrap(pathname, false), mode);
}
WRAP(stat, int, const char *path, struct stat *buf)
{
return CALL(stat)(CWrap(path, false), buf);
}
WRAP(lstat, int, const char *path, struct stat *buf)
{
return CALL(lstat)(CWrap(path, false), buf);
}
WRAP(scandir, int, const char *dirp, struct dirent ***namelist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **))
{
return CALL(scandir)(CWrap(dirp, false), namelist, filter, compar);
}
WRAP(opendir, DIR *, const char *name)
{
return CALL(opendir)(CWrap(name, false));
}
WRAP(__xstat, int, int __ver, __const char *__filename, struct stat *__stat_buf)
{
return CALL(__xstat)(__ver, CWrap(__filename, false), __stat_buf);
}
WRAP(__lxstat, int, int __ver, __const char *__filename, struct stat *__stat_buf)
{
return CALL(__lxstat)(__ver, CWrap(__filename, false), __stat_buf);
}
WRAP(__xstat64, int, int __ver, __const char *__filename, struct stat *__stat_buf)
{
return CALL(__xstat64)(__ver, CWrap(__filename, false), __stat_buf);
}
WRAP(__lxstat64, int, int __ver, __const char *__filename, struct stat *__stat_buf)
{
return CALL(__lxstat64)(__ver, CWrap(__filename, false), __stat_buf);
}
WRAP(chmod, int, const char *path, mode_t mode)
{
return CALL(chmod)(CWrap(path, false), mode);
}
WRAP(chown, int, const char *path, uid_t owner, gid_t group)
{
return CALL(chown)(CWrap(path, false), owner, group);
}
WRAP(lchown, int, const char *path, uid_t owner, gid_t group)
{
return CALL(lchown)(CWrap(path, false), owner, group);
}
WRAP(symlink, int, const char *oldpath, const char *newpath)
{
return CALL(symlink)(CWrap(oldpath, false), CWrap(newpath, true));
}
WRAP(link, int, const char *oldpath, const char *newpath)
{
return CALL(link)(CWrap(oldpath, false), CWrap(newpath, true));
}
WRAP(mknod, int, const char *pathname, mode_t mode, dev_t dev)
{
return CALL(mknod)(CWrap(pathname, true), mode, dev);
}
WRAP(mount, int, const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data)
{
return CALL(mount)(CWrap(source, false), CWrap(target, false), filesystemtype, mountflags, data);
}
WRAP(unlink, int, const char *pathname)
{
return CALL(unlink)(CWrap(pathname, false));
}
WRAP(mkfifo, int, const char *pathname, mode_t mode)
{
return CALL(mkfifo)(CWrap(pathname, true), mode);
}
WRAP(rename, int, const char *oldpath, const char *newpath)
{
return CALL(rename)(CWrap(oldpath, false), CWrap(newpath, true));
}
WRAP(utime, int, const char *filename, const struct utimbuf *times)
{
return CALL(utime)(CWrap(filename, false), times);
}
WRAP(utimes, int, const char *filename, const struct timeval times[2])
{
return CALL(utimes)(CWrap(filename, false), times);
}
//WRAP(realpath, char *, const char *path, char *resolved_path)
//{
// return CALL(realpath)(CWrap(path, true), resolved_path);
//}
WRAP(mkdir, int, const char *pathname, mode_t mode)
{
return CALL(mkdir)(CWrap(pathname, true), mode);
}
WRAP(rmdir, char *, const char *pathname)
{
return CALL(rmdir)(CWrap(pathname, false));
}
}; // extern "C"
#endif // _WIN32

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"

View File

@ -0,0 +1,40 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "osconfig.h"
#include "archtypes.h"
#include "interface.h"
#include "strtools.h"
// Hooks stuff
#include "hookers/filesystem/hooklist.h"
// FileSystem stuff
#include "FileSystem_Stdio.h"

View File

@ -0,0 +1,7 @@
#include "precompiled.h"
#include "interface.cpp"
#include "utlsymbol.cpp"
#include "tier0/dbg.cpp"
#include "tier0/characterset.cpp"

View File

@ -0,0 +1,5 @@
evaluationDependsOn(':rehlds/filesystem/FileSystem_Stdio');
task build {
dependsOn project(':rehlds/filesystem/FileSystem_Stdio').tasks.build
}

View File

@ -0,0 +1,182 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
// Hooks stuff
#include "hookers/memory.cpp"
#include "hookers/hooker.cpp"
//#define Mem_region
//#define BaseFileSystem_region
//#define CUtlSymbol_Region
//#define Function_References_region
//#define Data_References_region
FunctionHook g_FunctionHooks[] =
{
// DO NOT DISABLE, other functions depends on memory allocation routines
#ifndef Mem_region
#ifdef _WIN32
HOOK_SYMBOLDEF(0x01D06F5E, "_malloca", malloc_wrapper),
HOOK_SYMBOLDEF(0x01D067CA, "_free", free_wrapper),
HOOK_SYMBOLDEF(0x01D07098, "realloc", realloc_wrapper),
HOOK_SYMBOLDEF(0x01D06F70, "__nh_malloc", __nh_malloc_wrapper),
#endif //_WIN32
#endif // Mem_region
#ifndef BaseFileSystem_region
HOOK_DEF(0x01D01080, MethodThunk<CFileSystem_Stdio>::Destructor),
HOOK_DEF(0x01D01010, (MethodThunk<CFileSystem_Stdio>::Constructor)),
// virtual functions - CFileSystem_Stdio
HOOK_VIRTUAL_DEF(0x01D05340, CFileSystem_Stdio::Mount),
HOOK_VIRTUAL_DEF(0x01D011C0, CFileSystem_Stdio::Unmount),
HOOK_VIRTUAL_DEF(0x01D05510, CFileSystem_Stdio::GetLocalCopy),
HOOK_VIRTUAL_DEF(0x01D05520, CFileSystem_Stdio::LogLevelLoadStarted),
HOOK_VIRTUAL_DEF(0x01D05530, CFileSystem_Stdio::LogLevelLoadFinished),
HOOK_VIRTUAL_DEF(0x01D05540, CFileSystem_Stdio::HintResourceNeed),
HOOK_VIRTUAL_DEF(0x01D05550, CFileSystem_Stdio::PauseResourcePreloading),
HOOK_VIRTUAL_DEF(0x01D05560, CFileSystem_Stdio::ResumeResourcePreloading),
HOOK_VIRTUAL_DEF(0x01D05570, CFileSystem_Stdio::SetVBuf),
HOOK_VIRTUAL_DEF(0x01D055B0, CFileSystem_Stdio::GetInterfaceVersion),
HOOK_VIRTUAL_DEF(0x01D055D0, CFileSystem_Stdio::WaitForResources),
HOOK_VIRTUAL_DEF(0x01D055E0, CFileSystem_Stdio::GetWaitForResourcesProgress),
HOOK_VIRTUAL_DEF(0x01D05600, CFileSystem_Stdio::CancelWaitForResources),
HOOK_VIRTUAL_DEF(0x01D05610, CFileSystem_Stdio::IsAppReadyForOfflinePlay),
// virtual functions - BaseFileSystem
HOOK_SYMBOL_VIRTUAL_EX(0x01D01AF0, CFileSystem_Stdio, Open),
HOOK_SYMBOL_VIRTUAL_EX(0x01D01CC0, CFileSystem_Stdio, OpenFromCacheForRead),
HOOK_SYMBOL_VIRTUAL_EX(0x01D01D50, CFileSystem_Stdio, Close),
HOOK_SYMBOL_VIRTUAL_EX(0x01D01DD0, CFileSystem_Stdio, Seek),
HOOK_SYMBOL_VIRTUAL_EX(0x01D01EA0, CFileSystem_Stdio, Tell),
HOOK_SYMBOL_VIRTUAL_EX(0x01D01EF0, CFileSystem_Stdio, Size, size_t (FileHandle_t)),
HOOK_SYMBOL_VIRTUAL_EX(0x01D01F30, CFileSystem_Stdio, Size, size_t (const char *)),
HOOK_SYMBOL_VIRTUAL_EX(0x01D02310, CFileSystem_Stdio, IsOk),
HOOK_SYMBOL_VIRTUAL_EX(0x01D02370, CFileSystem_Stdio, Flush),
HOOK_SYMBOL_VIRTUAL_EX(0x01D02150, CFileSystem_Stdio, EndOfFile),
HOOK_SYMBOL_VIRTUAL_EX(0x01D021E0, CFileSystem_Stdio, Read),
HOOK_SYMBOL_VIRTUAL_EX(0x01D02240, CFileSystem_Stdio, Write),
HOOK_SYMBOL_VIRTUAL_EX(0x01D023B0, CFileSystem_Stdio, ReadLine),
HOOK_SYMBOL_VIRTUAL_EX(0x01D02290, CFileSystem_Stdio, FPrintf),
HOOK_SYMBOL_VIRTUAL_EX(0x01D022F0, CFileSystem_Stdio, GetReadBuffer),
HOOK_SYMBOL_VIRTUAL_EX(0x01D02300, CFileSystem_Stdio, ReleaseReadBuffer),
HOOK_SYMBOL_VIRTUAL_EX(0x01D012B0, CFileSystem_Stdio, GetCurrentDirectory),
HOOK_SYMBOL_VIRTUAL_EX(0x01D012B0, CFileSystem_Stdio, GetCurrentDirectory),
HOOK_SYMBOL_VIRTUAL_EX(0x01D011D0, CFileSystem_Stdio, CreateDirHierarchy),
HOOK_SYMBOL_VIRTUAL_EX(0x01D01680, CFileSystem_Stdio, IsDirectory),
HOOK_SYMBOL_VIRTUAL_EX(0x01D024A0, CFileSystem_Stdio, GetLocalPath),
HOOK_SYMBOL_VIRTUAL_EX(0x01D02400, CFileSystem_Stdio, RemoveFile),
HOOK_SYMBOL_VIRTUAL_EX(0x01D042B0, CFileSystem_Stdio, RemoveAllSearchPaths),
HOOK_SYMBOL_VIRTUAL_EX(0x01D01320, CFileSystem_Stdio, AddSearchPath),
HOOK_SYMBOL_VIRTUAL_EX(0x01D014E0, CFileSystem_Stdio, RemoveSearchPath),
HOOK_SYMBOL_VIRTUAL_EX(0x01D01AA0, CFileSystem_Stdio, FileExists),
HOOK_SYMBOL_VIRTUAL_EX(0x01D04000, CFileSystem_Stdio, GetFileTime),
HOOK_SYMBOL_VIRTUAL_EX(0x01D04060, CFileSystem_Stdio, FileTimeToString),
HOOK_SYMBOL_VIRTUAL_EX(0x01D036B0, CFileSystem_Stdio, FindFirst),
HOOK_SYMBOL_VIRTUAL_EX(0x01D03DB0, CFileSystem_Stdio, FindNext),
HOOK_SYMBOL_VIRTUAL_EX(0x01D03DF0, CFileSystem_Stdio, FindIsDirectory),
HOOK_SYMBOL_VIRTUAL_EX(0x01D03E10, CFileSystem_Stdio, FindClose),
HOOK_SYMBOL_VIRTUAL_EX(0x01D03EF0, CFileSystem_Stdio, ParseFile),
HOOK_SYMBOL_VIRTUAL_EX(0x01D04130, CFileSystem_Stdio, FullPathToRelativePath),
HOOK_SYMBOL_VIRTUAL_EX(0x01D012A0, CFileSystem_Stdio, PrintOpenedFiles),
HOOK_SYMBOL_VIRTUAL_EX(0x01D04090, CFileSystem_Stdio, SetWarningFunc),
HOOK_SYMBOL_VIRTUAL_EX(0x01D040A0, CFileSystem_Stdio, SetWarningLevel),
HOOK_SYMBOL_VIRTUAL_EX(0x01D02A20, CFileSystem_Stdio, AddPackFile),
HOOK_SYMBOL_VIRTUAL_EX(0x01D01300, CFileSystem_Stdio, AddSearchPathNoWrite),
// non-virtual functions - BaseFileSystem
HOOK_DEF(0x01D02780, CBaseFileSystem::Trace_FOpen),
HOOK_DEF(0x01D028A0, CBaseFileSystem::Trace_FClose),
HOOK_DEF(0x01D029E0, CBaseFileSystem::Trace_DumpUnclosedFiles),
HOOK_DEF(0x01D01340, CBaseFileSystem::AddSearchPathInternal),
HOOK_DEF(0x01D040B0, CBaseFileSystem::Warning),
HOOK_DEF(0x01D04350, CBaseFileSystem::FixSlashes),
HOOK_DEF(0x01D04370, CBaseFileSystem::FixPath),
//HOOK_DEF(0x01D04320, CBaseFileSystem::StripFilename), // NOXREF
HOOK_DEF(0x01D01610, CBaseFileSystem::GetWritePath),
HOOK_DEF(0x01D01790, CBaseFileSystem::FindFile),
HOOK_DEF(0x01D01F70, CBaseFileSystem::FastFindFileSize),
//HOOK_DEF(0x01D034B0, CBaseFileSystem::RemoveAllMapSearchPaths), // NOXREF
HOOK_DEF(0x01D033A0, CBaseFileSystem::AddPackFiles),
HOOK_DEF(0x01D02A40, CBaseFileSystem::AddPackFileFromPath),
HOOK_DEF(0x01D02D20, CBaseFileSystem::PreparePackFile),
HOOK_DEF(0x01D03070, CBaseFileSystem::Prepare64BitPackFile),
HOOK_DEF(0x01D03510, CBaseFileSystem::SearchPakFile),
//HOOK_DEF(0x01D039B0, CBaseFileSystem::FileInSearchPaths), // NOXREF
HOOK_DEF(0x01D03B70, CBaseFileSystem::FindNextFileHelper),
HOOK_DEF(0x01D03890, CBaseFileSystem::FindFirstHelper),
#endif // BaseFileSystem_region
#ifndef CUtlSymbol_Region
//HOOK_DEF(0x01D05AA0, MethodThunk<CUtlSymbolTable>::Destructor), // NOXREF
HOOK_DEF(0x01D05A30, (MethodThunk<CUtlSymbolTable, int, int, bool>::Constructor), void(int, int, bool)),
HOOK_DEF(0x01D05C50, CUtlSymbolTable::AddString),
HOOK_DEF(0x01D05B10, CUtlSymbolTable::Find),
HOOK_DEF(0x01D05DA0, CUtlSymbolTable::String),
//HOOK_DEF(0x0, CUtlSymbolTable::RemoveAll), // NOXREF
HOOK_DEF(0x01D05960, CUtlSymbolTable::SymLess),
HOOK_DEF(0x01D059E0, CUtlSymbolTable::SymLessi),
HOOK_DEF(0x01D05890, (MethodThunk<CUtlSymbol, const char *>::Constructor), void(const char *)),
HOOK_DEF(0x01D05830, CUtlSymbol::Initialize), // Don't touch it
HOOK_DEF(0x01D05880, CUtlSymbol::CurrTable), // Don't touch it
HOOK_DEF(0x01D058C0, CUtlSymbol::String),
//HOOK_DEF(0x01D058E0, CUtlSymbol::operator==, bool (const char *) const), // NOXREF
#endif // CUtlSymbol_Region
{ NULL, NULL, NULL },
};
AddressRef g_FunctionRefs[] =
{
#ifndef Function_References_region
#endif // Function_References_region
{ NULL, NULL, NULL },
};
AddressRef g_DataRefs[] =
{
#ifndef Data_References_region
//GLOBALVAR_LINK(0x01D1B020, "CBaseFileSystem::s_pFileSystem", CBaseFileSystem::s_pFileSystem),
GLOBALVAR_LINK(0x01D1B0B8, "g_LessCtx", pg_LessCtx),
#endif // Data_References_region
{ NULL, NULL, NULL },
};

View File

@ -0,0 +1,42 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#ifdef HOOK_FILESYSTEM
#define rehlds_syserror FileSystem_SysError
#define g_LessCtx (*pg_LessCtx)
#include "hookers/memory.h"
#include "hookers/helper.h"
#include "hookers/hooker.h"
extern struct LessCtx_t g_LessCtx;
#endif // HOOK_FILESYSTEM

View File

@ -0,0 +1,86 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
#if defined(HOOK_FILESYSTEM)
const char *ORIGINAL_FILESYSTEM_DLL_NAME = "filesystem_stdio2.dll";
CSysModule *g_pOriginalFileSystemModule = nullptr;
CreateInterfaceFn g_OriginalFileSystemFactory = nullptr;
IFileSystem *g_pOriginalFileSystem = nullptr;
IBaseInterface *CreateFileSystemInterface()
{
if (g_pOriginalFileSystem) {
return g_pOriginalFileSystem;
}
if (g_pOriginalFileSystemModule)
{
g_OriginalFileSystemFactory = (CreateInterfaceFn)Sys_GetFactory(g_pOriginalFileSystemModule);
if (g_OriginalFileSystemFactory)
{
int returnCode = 0;
g_pOriginalFileSystem = (IFileSystem *)g_OriginalFileSystemFactory(FILESYSTEM_INTERFACE_VERSION, &returnCode);
return g_pOriginalFileSystem;
}
}
return nullptr;
}
EXPOSE_INTERFACE_FN(CreateFileSystemInterface, IFileSystem, FILESYSTEM_INTERFACE_VERSION);
// DLL entry point
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
g_pOriginalFileSystemModule = (CSysModule *)LoadLibrary(ORIGINAL_FILESYSTEM_DLL_NAME);
size_t addr = (size_t)Sys_GetProcAddress(ORIGINAL_FILESYSTEM_DLL_NAME, CREATEINTERFACE_PROCNAME);
HookModule("hlds.exe", addr);
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
if (g_pOriginalFileSystemModule)
{
Sys_UnloadModule(g_pOriginalFileSystemModule);
g_pOriginalFileSystemModule = nullptr;
g_OriginalFileSystemFactory = nullptr;
g_pOriginalFileSystem = nullptr;
}
}
return TRUE;
}
#endif // #if defined(HOOK_FILESYSTEM)

View File

@ -8,7 +8,7 @@
#include <array>
#include <utility>
#if defined(HOOK_ENGINE) || defined(HOOK_HLTV)
#if defined(HOOK_ENGINE) || defined(HOOK_HLTV) || defined(HOOK_FILESYSTEM)
#define private public
#define protected public
@ -116,6 +116,9 @@ namespace MsvcMethod {
return (vIndexGetter->*vIndexGetterFunction)();
}
template <typename TMethod, typename T>
TMethod &declmethod(TMethod T::*method);
template <typename TMethod, typename T>
std::enable_if_t<Detail::is_function_v<TMethod>, std::uintptr_t>
GetVirtualAddress(TMethod T::*method)
@ -145,15 +148,16 @@ namespace MsvcMethod {
} // namespace MsvcMethod
#ifdef _MSC_VER
#define GLOBALVAR_LINK(offset, symbol, var, ...) { offset, #symbol, (size_t)&##var, __VA_ARGS__ }
#define HOOK_SYMBOLDEF(offset, symbol, func, ...) { offset, #symbol, MsvcMethod::GetAddress<__VA_ARGS__>(&func) }
#define HOOK_SYMBOL_VIRTUAL_DEF(offset, symbol, func, ...) { offset, #symbol, MsvcMethod::GetVirtualAddress<__VA_ARGS__>(&func) }
#define GLOBALVAR_LINK(offset, symbol, var, ...) { offset, #symbol, (size_t)&##var, __VA_ARGS__ }
#define HOOK_SYMBOLDEF(offset, symbol, func, ...) { offset, #symbol, MsvcMethod::GetAddress<__VA_ARGS__>(&func) }
#define HOOK_SYMBOL_VIRTUAL_DEF(offset, symbol, func, ...) { offset, #symbol, MsvcMethod::GetVirtualAddress<__VA_ARGS__>(&func) }
#define HOOK_SYMBOL_VIRTUAL_EX(offset, class, func, ...) { offset, #class#func, MsvcMethod::GetVirtualAddress<std::remove_reference<decltype(MsvcMethod::declmethod<__VA_ARGS__>(&class::func))>::type, class>(&class::func) }
#define HOOK_DEF(offset, func, ...) HOOK_SYMBOLDEF(offset, func, func, __VA_ARGS__)
#define HOOK_VIRTUAL_DEF(offset, func, ...) HOOK_SYMBOL_VIRTUAL_DEF(offset, func, func, __VA_ARGS__)
#define HOOK_DEF(offset, func, ...) HOOK_SYMBOLDEF(offset, func, func, __VA_ARGS__)
#define HOOK_VIRTUAL_DEF(offset, func, ...) HOOK_SYMBOL_VIRTUAL_DEF(offset, func, func, __VA_ARGS__)
#else
#error Hooking stuff is only available using MSVC compiler.
#endif // _MSC_VER
#endif // #if defined(HOOK_ENGINE) || defined(HOOK_HLTV)
#endif // #if defined(HOOK_ENGINE) || defined(HOOK_HLTV) || defined(HOOK_FILESYSTEM)

View File

@ -64,20 +64,22 @@ enum
typedef enum
{
FILESYSTEM_WARNING = -1, // A problem!
FILESYSTEM_WARNING_QUIET = 0, // Don't print anything
FILESYSTEM_WARNING_REPORTUNCLOSED, // On shutdown, report names of files left unclosed
FILESYSTEM_WARNING_REPORTUSAGE, // Report number of times a file was opened, closed
FILESYSTEM_WARNING_REPORTALLACCESSES // Report all open/close events to console (!slow!)
} FileWarningLevel_t;
#define FILESYSTEM_INVALID_HANDLE (FileHandle_t)0
const FileHandle_t FILESYSTEM_INVALID_HANDLE = nullptr;
#endif // FILESYSTEM_INTERNAL_H
// turn off any windows defines
#undef GetCurrentDirectory
// Purpose: Main file system interface
class IFileSystem : public IBaseInterface
class IFileSystem: public IBaseInterface
{
public:
// Mount and unmount the filesystem
@ -114,10 +116,10 @@ public:
virtual void Close(FileHandle_t file) = 0;
virtual void Seek(FileHandle_t file, int pos, FileSystemSeek_t seekType) = 0;
virtual unsigned int Tell(FileHandle_t file) = 0;
virtual size_t Tell(FileHandle_t file) = 0;
virtual unsigned int Size(FileHandle_t file) = 0;
virtual unsigned int Size(const char *pFileName) = 0;
virtual size_t Size(FileHandle_t file) = 0;
virtual size_t Size(const char *pFileName) = 0;
virtual long GetFileTime(const char *pFileName) = 0;
virtual void FileTimeToString(char *pStrip, int maxCharsIncludingTerminator, long fileTime) = 0;
@ -130,7 +132,7 @@ public:
virtual int Read(void *pOutput, int size, FileHandle_t file) = 0;
virtual int Write(void const *pInput, int size, FileHandle_t file) = 0;
virtual char *ReadLine(char *pOutput, int maxChars, FileHandle_t file) = 0;
virtual int FPrintf(FileHandle_t file, char *pFormat, ...) = 0;
virtual int FPrintf(FileHandle_t file, const char *fmt, ...) = 0;
// direct filesystem buffer access
// returns a handle to a buffer containing the file data

View File

@ -70,7 +70,7 @@ public:
//
// Use this if you want to write the factory function.
#define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName)\
static InterfaceReg __g_Create##className##_reg(functionName, versionName);
static InterfaceReg __g_Create##interfaceName##_reg(functionName, versionName);
#define EXPOSE_INTERFACE(className, interfaceName, versionName)\
static IBaseInterface *__Create##className##_interface() {return (interfaceName *)new className;}\

View File

@ -0,0 +1,50 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include <string.h>
#include "characterset.h"
// Builds a simple lookup table of a group of important characters
// Input : *pParseGroup - pointer to the buffer for the group
// *pGroupString - null terminated list of characters to flag
void CharacterSetBuild(characterset_t *pSetBuffer, const char *pszSetString)
{
int i = 0;
// Test our pointers
if (!pSetBuffer || !pszSetString)
return;
memset(pSetBuffer->set, 0, sizeof(pSetBuffer->set));
while (pszSetString[i])
{
pSetBuffer->set[pszSetString[i]] = 1;
i++;
}
}

View File

@ -0,0 +1,46 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
struct characterset_t
{
char set[256];
};
// This is essentially a strpbrk() using a precalculated lookup table
//
// Builds a simple lookup table of a group of important characters
// Input : *pSetBuffer - pointer to the buffer for the group
// *pSetString - list of characters to flag
extern void CharacterSetBuild(characterset_t *pSetBuffer, const char *pSetString);
// Input : *pSetBuffer - pre-build group buffer
// character - character to lookup
// Output : int - 1 if the character was in the set
#define IN_CHARACTERSET(SetBuffer, character) ((SetBuffer).set[(character)])

View File

@ -45,12 +45,12 @@
// Usage model for the Dbg library
//
// 1. Spew.
//
//
// Spew can be used in a static and a dynamic mode. The static
// mode allows us to display assertions and other messages either only
// in debug builds, or in non-release builds. The dynamic mode allows us to
// turn on and off certain spew messages while the application is running.
//
//
// Static Spew messages:
//
// Assertions are used to detect and warn about invalid states
@ -65,14 +65,14 @@
// AssertFloatEquals( f, 5.0f, 1e-3 );
//
// The first will simply report that an assertion failed on a particular
// code file and line. The second version will display a print-f formatted message
// code file and line. The second version will display a print-f formatted message
// along with the file and line, the third will display a generic message and
// will also cause the function BadFunc to be executed, and the last two
// will report an error if f is not equal to 5 (the last one asserts within
// a particular tolerance).
//
// To use a warning, use
//
//
// Warning("Oh I feel so %s all over\n", "yummy");
//
// Warning will do its magic in only Debug builds. To perform spew in *all*
@ -86,24 +86,24 @@
//
// Dynamic Spew messages
//
// It is possible to dynamically turn spew on and off. Dynamic spew is
// identified by a spew group and priority level. To turn spew on for a
// particular spew group, use SpewActivate( "group", level ). This will
// cause all spew in that particular group with priority levels <= the
// level specified in the SpewActivate function to be printed. Use DSpew
// It is possible to dynamically turn spew on and off. Dynamic spew is
// identified by a spew group and priority level. To turn spew on for a
// particular spew group, use SpewActivate( "group", level ). This will
// cause all spew in that particular group with priority levels <= the
// level specified in the SpewActivate function to be printed. Use DSpew
// to perform the spew:
//
// DWarning( "group", level, "Oh I feel even yummier!\n" );
//
// Priority level 0 means that the spew will *always* be printed, and group
// '*' is the default spew group. If a DWarning is encountered using a group
// whose priority has not been set, it will use the priority of the default
// group. The priority of the default group is initially set to 0.
// '*' is the default spew group. If a DWarning is encountered using a group
// whose priority has not been set, it will use the priority of the default
// group. The priority of the default group is initially set to 0.
//
// Spew output
//
//
// The output of the spew system can be redirected to an externally-supplied
// function which is responsible for outputting the spew. By default, the
// function which is responsible for outputting the spew. By default, the
// spew is simply printed using printf.
//
// To redirect spew output, call SpewOutput.
@ -113,8 +113,8 @@
// This will cause OutputFunc to be called every time a spew message is
// generated. OutputFunc will be passed a spew type and a message to print.
// It must return a value indicating whether the debugger should be invoked,
// whether the program should continue running, or whether the program
// should abort.
// whether the program should continue running, or whether the program
// should abort.
//
// 2. Code activation
//
@ -126,10 +126,10 @@
// int x = 5;
// ++x;
// }
// );
// );
//
// Code can be activated based on the dynamic spew groups also. Use
//
//
// DBG_DCODE( "group", level,
// { int x = 5; ++x; }
// );
@ -254,7 +254,7 @@ SpewRetval_t _DSpewMessage(char const *pGroupName, int level, char const* pMsg
#define Assert( _exp ) _Assert( _exp )
#define AssertMsg( _exp, _msg ) _AssertMsg( _exp, _msg )
#define AssertFunc( _exp, _f ) _AssertFunc( _exp, _f )
#define AssertEquals( _exp, _expectedValue ) _AssertEquals( _exp, _expectedValue )
#define AssertEquals( _exp, _expectedValue ) _AssertEquals( _exp, _expectedValue )
#define AssertFloatEquals( _exp, _expectedValue, _tol ) _AssertFloatEquals( _exp, _expectedValue, _tol )
#define Verify( _exp ) _Assert( _exp )
@ -336,7 +336,7 @@ void DevLog(char const *pMsg, ...);
#define DBG_CODE( _code ) if (0) ; else { _code }
#define DBG_DCODE( _g, _l, _code ) if (IsSpewActive( _g, _l )) { _code } else {}
#define DBG_BREAK() DebuggerBreak() /* defined in platform.h */
#define DBG_BREAK() DebuggerBreak() /* defined in platform.h */
#else /* not _DEBUG */

View File

@ -59,18 +59,18 @@ public:
bool operator!=(const Iterator_t it) const { return m_index != it.m_index; }
};
Iterator_t First() const { return Iterator_t(IsIdxValid(0) ? 0 : InvalidIndex()); }
Iterator_t Next(const Iterator_t &it) const { return Iterator_t(IsIdxValid(it.index + 1) ? it.index + 1 : InvalidIndex()); }
I GetIndex(const Iterator_t &it) const { return it.index; }
bool IsIdxAfter(I i, const Iterator_t &it) const { return i > it.index; }
bool IsValidIterator(const Iterator_t &it) const { return IsIdxValid(it.index); }
Iterator_t InvalidIterator() const { return Iterator_t(InvalidIndex()); }
Iterator_t First() const { return Iterator_t(IsIdxValid(0) ? 0 : InvalidIndex()); }
Iterator_t Next(const Iterator_t &it) const { return Iterator_t(IsIdxValid(it.index + 1) ? it.index + 1 : InvalidIndex()); }
I GetIndex(const Iterator_t &it) const { return it.index; }
bool IsIdxAfter(I i, const Iterator_t &it) const { return i > it.index; }
bool IsValidIterator(const Iterator_t &it) const { return IsIdxValid(it.index); }
Iterator_t InvalidIterator() const { return Iterator_t(InvalidIndex()); }
// element access
T& Element(I i);
T const& Element(I i) const;
T& operator[](I i);
T const& operator[](I i) const;
T& Element(I i);
T const& Element(I i) const;
T& operator[](I i);
T const& operator[](I i) const;
// Can we use this index?
bool IsIdxValid(I i) const;
@ -116,7 +116,7 @@ private:
int m_nGrowSize;
};
// constructor, destructor
// Constructor, Destructor
template <class T, class I>
CUtlMemory<T, I>::CUtlMemory(int nGrowSize, int nInitSize) : m_pMemory(0),
m_nAllocationCount(nInitSize), m_nGrowSize(nGrowSize)
@ -170,7 +170,7 @@ void CUtlMemory<T, I>::SetExternalBuffer(T *pMemory, int numElements)
m_nGrowSize = EXTERNAL_BUFFER_MARKER;
}
// element access
// Element access
template <class T, class I>
inline T& CUtlMemory<T, I>::operator[](I i)
{
@ -199,7 +199,7 @@ inline T const& CUtlMemory<T, I>::Element(I i) const
return m_pMemory[i];
}
// is the memory externally allocated?
// Is the memory externally allocated?
template <class T, class I>
bool CUtlMemory<T, I>::IsExternallyAllocated() const
{
@ -329,6 +329,7 @@ void CUtlMemory<T, I>::Purge()
free((void *)m_pMemory);
m_pMemory = 0;
}
m_nAllocationCount = 0;
}
}

File diff suppressed because it is too large Load Diff

152
rehlds/public/utlsymbol.cpp Normal file
View File

@ -0,0 +1,152 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "utlsymbol.h"
LessCtx_t g_LessCtx;
CUtlSymbolTable *CUtlSymbol::s_pSymbolTable = nullptr;
void CUtlSymbol::Initialize()
{
// necessary to allow us to create global symbols
static bool symbolsInitialized = false;
if (!symbolsInitialized)
{
s_pSymbolTable = new CUtlSymbolTable;
symbolsInitialized = true;
}
}
CUtlSymbolTable *CUtlSymbol::CurrTable()
{
Initialize();
return s_pSymbolTable;
}
CUtlSymbol::CUtlSymbol(const char *pStr)
{
m_Id = CurrTable()->AddString(pStr);
}
const char *CUtlSymbol::String() const
{
return CurrTable()->String(m_Id);
}
// Checks if the symbol matches a string
bool CUtlSymbol::operator==(const char *pStr) const
{
if (m_Id == UTL_INVAL_SYMBOL)
return false;
return Q_strcmp(String(), pStr) == 0;
}
bool CUtlSymbolTable::SymLess(const unsigned int &i1, const unsigned int &i2)
{
const char *str1 = (i1 == INVALID_STRING_INDEX) ? g_LessCtx.m_pUserString : g_LessCtx.m_pTable->StringFromIndex(i1);
const char *str2 = (i2 == INVALID_STRING_INDEX) ? g_LessCtx.m_pUserString : g_LessCtx.m_pTable->StringFromIndex(i2);
return Q_strcmp(str1, str2) < 0;
}
bool CUtlSymbolTable::SymLessi(const unsigned int &i1, const unsigned int &i2)
{
const char *str1 = (i1 == INVALID_STRING_INDEX) ? g_LessCtx.m_pUserString : g_LessCtx.m_pTable->StringFromIndex(i1);
const char *str2 = (i2 == INVALID_STRING_INDEX) ? g_LessCtx.m_pUserString : g_LessCtx.m_pTable->StringFromIndex(i2);
return Q_stricmp(str1, str2) < 0;
}
// Constructor, Destructor
CUtlSymbolTable::CUtlSymbolTable(int growSize, int initSize, bool caseInsensitive) :
m_Lookup(growSize, initSize, caseInsensitive ? SymLess : SymLessi),
m_StringPools(MAX_STRING_POOL_SIZE)
{
;
}
CUtlSymbolTable::~CUtlSymbolTable()
{
// Release the stringpool string data
RemoveAll();
}
CUtlSymbol CUtlSymbolTable::Find(const char *pString)
{
if (!pString)
return CUtlSymbol();
// Store a special context used to help with insertion
g_LessCtx.m_pUserString = pString;
g_LessCtx.m_pTable = this;
// Passing this special invalid symbol makes the comparison function
// use the string passed in the context
UtlSymId_t idx = m_Lookup.Find(INVALID_STRING_INDEX);
return CUtlSymbol(idx);
}
// Finds and/or creates a symbol based on the string
CUtlSymbol CUtlSymbolTable::AddString(const char *pString)
{
if (!pString)
return CUtlSymbol(UTL_INVAL_SYMBOL);
// Find a pool with space for this string, or allocate a new one
CUtlSymbol id = Find(pString);
if (id.IsValid())
return id;
// Add a new pool
int len = Q_strlen(pString) + 1;
int stridx = m_StringPools.AddMultipleToTail(len);
Q_memcpy(&m_StringPools[stridx], pString, len);
// Didn't find, insert the string into the vector
UtlSymId_t idx = m_Lookup.Insert(stridx);
return CUtlSymbol(idx);
}
// Look up the string associated with a particular symbol
const char *CUtlSymbolTable::String(CUtlSymbol id) const
{
if (!id.IsValid())
return "";
Assert(m_Lookup.IsValidIndex((UtlSymId_t)id));
return StringFromIndex(m_Lookup[id]);
}
// Remove all symbols in the table
void CUtlSymbolTable::RemoveAll()
{
m_Lookup.RemoveAll();
m_StringPools.RemoveAll();
}

113
rehlds/public/utlsymbol.h Normal file
View File

@ -0,0 +1,113 @@
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#pragma once
#include "utlrbtree.h"
#include "utlvector.h"
class CUtlSymbolTable;
using UtlSymId_t = unsigned short;
const int MAX_STRING_POOL_SIZE = 256;
const UtlSymId_t UTL_INVAL_SYMBOL = ((UtlSymId_t)~0);
const unsigned int INVALID_STRING_INDEX = -1;
struct LessCtx_t
{
const char *m_pUserString;
CUtlSymbolTable *m_pTable;
LessCtx_t() : m_pUserString(0), m_pTable(0) {}
};
class CUtlSymbol
{
public:
// constructor, destructor
CUtlSymbol() : m_Id(UTL_INVAL_SYMBOL) {}
CUtlSymbol(UtlSymId_t id) : m_Id(id) {}
CUtlSymbol(const char *pStr);
CUtlSymbol(CUtlSymbol const &sym) : m_Id(sym.m_Id) {}
// operator=
CUtlSymbol &operator=(CUtlSymbol const &src)
{
m_Id = src.m_Id;
return *this;
}
// operator==
bool operator==(CUtlSymbol const &src) const { return m_Id == src.m_Id; }
bool operator==(const char *pStr) const;
// Is valid?
bool IsValid() const { return m_Id != UTL_INVAL_SYMBOL; }
operator UtlSymId_t() const { return m_Id; } // Gets at the symbol
const char *String() const; // Gets the string associated with the symbol
protected:
static void Initialize(); // Initializes the symbol table
static CUtlSymbolTable *CurrTable(); // returns the current symbol table
UtlSymId_t m_Id;
static CUtlSymbolTable *s_pSymbolTable;
};
class CUtlSymbolTable
{
public:
// constructor, destructor
CUtlSymbolTable(int growSize = 0, int initSize = 32, bool caseInsensitive = false);
~CUtlSymbolTable();
CUtlSymbol AddString(const char *pString); // Finds and/or creates a symbol based on the string
CUtlSymbol Find(const char *pString); // Finds the symbol for pString
const char *String(CUtlSymbol id) const; // Look up the string associated with a particular symbol
void RemoveAll(); // Remove all symbols in the table
public:
static bool SymLess(const unsigned int &i1, const unsigned int &i2);
static bool SymLessi(const unsigned int &i1, const unsigned int &i2);
private:
const char *StringFromIndex(const UtlSymId_t &index) const;
protected:
CUtlRBTree<unsigned int, UtlSymId_t> m_Lookup;
CUtlVector<char> m_StringPools;
};
inline const char *CUtlSymbolTable::StringFromIndex(const UtlSymId_t &index) const
{
Assert(index < m_StringPools.Count());
return &m_StringPools[index];
}

View File

@ -1,24 +1,34 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// A growable memory class.
//=============================================================================
/*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#ifndef UTLVECTOR_H
#define UTLVECTOR_H
#ifdef _WIN32
#pragma once
#endif
#include "utlmemory.h"
#include "tier0/platform.h"
template<class T>
class CUtlVector
@ -27,22 +37,29 @@ public:
typedef T ElemType_t;
// constructor, destructor
CUtlVector( int growSize = 0, int initSize = 0 );
CUtlVector( T* pMemory, int numElements );
CUtlVector(int growSize = 0, int initSize = 0);
CUtlVector(T *pMemory, int numElements);
~CUtlVector();
// features C++11 ranged based for
T *begin() { return &m_Memory[0]; }
T *end() { return &m_Memory[m_Size - 1]; }
T const *begin() const { return &m_Memory[0]; }
T const *end() const { return &m_Memory[m_Size - 1]; }
// Copy the array.
CUtlVector<T>& operator=( const CUtlVector<T> &other );
CUtlVector<T> &operator=(const CUtlVector<T> &other);
// element access
T& operator[]( int i );
T const& operator[]( int i ) const;
T& Element( int i );
T const& Element( int i ) const;
T &operator[](int i);
T const &operator[](int i) const;
T &Element(int i);
T const &Element(int i) const;
// Gets the base address (can change when adding elements!)
T* Base();
T const* Base() const;
T *Base();
T const *Base() const;
// Returns the number of elements in the vector
// SIZE IS DEPRECATED!
@ -50,54 +67,54 @@ public:
int Size() const; // don't use me!
// Is element index valid?
bool IsValidIndex( int i ) const;
static int InvalidIndex( void );
bool IsValidIndex(int i) const;
static int InvalidIndex(void);
// Adds an element, uses default constructor
int AddToHead();
int AddToTail();
int InsertBefore( int elem );
int InsertAfter( int elem );
int InsertBefore(int elem);
int InsertAfter(int elem);
// Adds an element, uses copy constructor
int AddToHead( T const& src );
int AddToTail( T const& src );
int InsertBefore( int elem, T const& src );
int InsertAfter( int elem, T const& src );
int AddToHead(T const &src);
int AddToTail(T const &src);
int InsertBefore(int elem, T const &src);
int InsertAfter(int elem, T const &src);
// Adds multiple elements, uses default constructor
int AddMultipleToHead( int num );
int AddMultipleToTail( int num, const T *pToCopy=NULL );
int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL ); // If pToCopy is set, then it's an array of length 'num' and
int InsertMultipleAfter( int elem, int num );
int AddMultipleToHead(int num);
int AddMultipleToTail(int num, const T *pToCopy = nullptr);
int InsertMultipleBefore(int elem, int num, const T *pToCopy = nullptr); // If pToCopy is set, then it's an array of length 'num' and
int InsertMultipleAfter(int elem, int num);
// Calls RemoveAll() then AddMultipleToTail.
void SetSize( int size );
void SetCount( int count );
void SetSize(int size);
void SetCount(int count);
// Calls SetSize and copies each element.
void CopyArray( T const *pArray, int size );
void CopyArray(T const *pArray, int size);
// Add the specified array to the tail.
int AddVectorToTail( CUtlVector<T> const &src );
int AddVectorToTail(CUtlVector<T> const &src);
// Finds an element (element needs operator== defined)
int Find( T const& src ) const;
int Find(T const &src) const;
bool HasElement( T const& src );
bool HasElement(T const &src);
// Makes sure we have enough memory allocated to store a requested # of elements
void EnsureCapacity( int num );
void EnsureCapacity(int num);
// Makes sure we have at least this many elements
void EnsureCount( int num );
void EnsureCount(int num);
// Element removal
void FastRemove( int elem ); // doesn't preserve order
void Remove( int elem ); // preserves order, shifts elements
void FindAndRemove( T const& src ); // removes first occurrence of src, preserves order, shifts elements
void RemoveMultiple( int elem, int num ); // preserves order, shifts elements
void RemoveAll(); // doesn't deallocate memory
void FastRemove(int elem); // doesn't preserve order
void Remove(int elem); // preserves order, shifts elements
void FindAndRemove(T const &src); // removes first occurrence of src, preserves order, shifts elements
void RemoveMultiple(int elem, int num); // preserves order, shifts elements
void RemoveAll(); // doesn't deallocate memory
// Memory deallocation
void Purge();
@ -106,19 +123,18 @@ public:
void PurgeAndDeleteElements();
// Set the size by which it grows when it needs to allocate more memory.
void SetGrowSize( int size );
void SetGrowSize(int size);
protected:
// Can't copy this unless we explicitly do it!
CUtlVector( CUtlVector const& vec ) { assert(0);
}
CUtlVector(CUtlVector const &vec) { Assert(0); }
// Grows the vector
void GrowVector( int num = 1 );
void GrowVector(int num = 1);
// Shifts elements....
void ShiftElementsRight( int elem, int num = 1 );
void ShiftElementsLeft( int elem, int num = 1 );
void ShiftElementsRight(int elem, int num = 1);
void ShiftElementsLeft(int elem, int num = 1);
// For easier access to the elements through the debugger
void ResetDbgInfo();
@ -131,444 +147,408 @@ protected:
T *m_pElements;
};
//-----------------------------------------------------------------------------
// For easier access to the elements through the debugger
//-----------------------------------------------------------------------------
template< class T >
template <class T>
inline void CUtlVector<T>::ResetDbgInfo()
{
m_pElements = m_Memory.Base();
}
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
template< class T >
inline CUtlVector<T>::CUtlVector( int growSize, int initSize ) :
template <class T>
inline CUtlVector<T>::CUtlVector(int growSize, int initSize) :
m_Memory(growSize, initSize), m_Size(0)
{
ResetDbgInfo();
}
template< class T >
inline CUtlVector<T>::CUtlVector( T* pMemory, int numElements ) :
template <class T>
inline CUtlVector<T>::CUtlVector(T *pMemory, int numElements) :
m_Memory(pMemory, numElements), m_Size(0)
{
ResetDbgInfo();
}
template< class T >
template <class T>
inline CUtlVector<T>::~CUtlVector()
{
Purge();
}
template<class T>
inline CUtlVector<T>& CUtlVector<T>::operator=( const CUtlVector<T> &other )
template <class T>
inline CUtlVector<T> &CUtlVector<T>::operator=(const CUtlVector<T> &other)
{
CopyArray( other.Base(), other.Count() );
CopyArray(other.Base(), other.Count());
return *this;
}
//-----------------------------------------------------------------------------
// element access
//-----------------------------------------------------------------------------
template< class T >
inline T& CUtlVector<T>::operator[]( int i )
template <class T>
inline T &CUtlVector<T>::operator[](int i)
{
assert( IsValidIndex(i) );
Assert(IsValidIndex(i));
return m_Memory[i];
}
template< class T >
inline T const& CUtlVector<T>::operator[]( int i ) const
template <class T>
inline T const &CUtlVector<T>::operator[](int i) const
{
assert( IsValidIndex(i) );
Assert(IsValidIndex(i));
return m_Memory[i];
}
template< class T >
inline T& CUtlVector<T>::Element( int i )
template <class T>
inline T &CUtlVector<T>::Element(int i)
{
assert( IsValidIndex(i) );
Assert(IsValidIndex(i));
return m_Memory[i];
}
template< class T >
inline T const& CUtlVector<T>::Element( int i ) const
template <class T>
inline T const &CUtlVector<T>::Element(int i) const
{
assert( IsValidIndex(i) );
Assert(IsValidIndex(i));
return m_Memory[i];
}
//-----------------------------------------------------------------------------
// Gets the base address (can change when adding elements!)
//-----------------------------------------------------------------------------
template< class T >
inline T* CUtlVector<T>::Base()
template <class T>
inline T *CUtlVector<T>::Base()
{
return m_Memory.Base();
}
template< class T >
inline T const* CUtlVector<T>::Base() const
template <class T>
inline T const *CUtlVector<T>::Base() const
{
return m_Memory.Base();
}
//-----------------------------------------------------------------------------
// Count
//-----------------------------------------------------------------------------
template< class T >
template <class T>
inline int CUtlVector<T>::Size() const
{
return m_Size;
}
template< class T >
template <class T>
inline int CUtlVector<T>::Count() const
{
return m_Size;
}
//-----------------------------------------------------------------------------
// Is element index valid?
//-----------------------------------------------------------------------------
template< class T >
inline bool CUtlVector<T>::IsValidIndex( int i ) const
template <class T>
inline bool CUtlVector<T>::IsValidIndex(int i) const
{
return (i >= 0) && (i < m_Size);
}
//-----------------------------------------------------------------------------
// Returns in invalid index
//-----------------------------------------------------------------------------
template< class T >
inline int CUtlVector<T>::InvalidIndex( void )
template <class T>
inline int CUtlVector<T>::InvalidIndex(void)
{
return -1;
}
//-----------------------------------------------------------------------------
// Grows the vector
//-----------------------------------------------------------------------------
template< class T >
void CUtlVector<T>::GrowVector( int num )
template <class T>
void CUtlVector<T>::GrowVector(int num)
{
if (m_Size + num - 1 >= m_Memory.NumAllocated())
{
m_Memory.Grow( m_Size + num - m_Memory.NumAllocated() );
m_Memory.Grow(m_Size + num - m_Memory.NumAllocated());
}
m_Size += num;
ResetDbgInfo();
}
//-----------------------------------------------------------------------------
// Makes sure we have enough memory allocated to store a requested # of elements
//-----------------------------------------------------------------------------
template< class T >
void CUtlVector<T>::EnsureCapacity( int num )
template <class T>
void CUtlVector<T>::EnsureCapacity(int num)
{
m_Memory.EnsureCapacity(num);
ResetDbgInfo();
}
//-----------------------------------------------------------------------------
// Makes sure we have at least this many elements
//-----------------------------------------------------------------------------
template< class T >
void CUtlVector<T>::EnsureCount( int num )
template <class T>
void CUtlVector<T>::EnsureCount(int num)
{
if (Count() < num)
AddMultipleToTail( num - Count() );
AddMultipleToTail(num - Count());
}
//-----------------------------------------------------------------------------
// Shifts elements
//-----------------------------------------------------------------------------
template< class T >
void CUtlVector<T>::ShiftElementsRight( int elem, int num )
template <class T>
void CUtlVector<T>::ShiftElementsRight(int elem, int num)
{
assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 ));
Assert(IsValidIndex(elem) || (m_Size == 0) || (num == 0));
int numToMove = m_Size - elem - num;
if ((numToMove > 0) && (num > 0))
memmove( &Element(elem+num), &Element(elem), numToMove * sizeof(T) );
memmove(&Element(elem+num), &Element(elem), numToMove * sizeof(T));
}
template< class T >
void CUtlVector<T>::ShiftElementsLeft( int elem, int num )
template <class T>
void CUtlVector<T>::ShiftElementsLeft(int elem, int num)
{
assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 ));
Assert(IsValidIndex(elem) || (m_Size == 0) || (num == 0));
int numToMove = m_Size - elem - num;
if ((numToMove > 0) && (num > 0))
{
memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) );
memmove(&Element(elem), &Element(elem + num), numToMove * sizeof(T));
#ifdef _DEBUG
memset( &Element(m_Size-num), 0xDD, num * sizeof(T) );
memset(&Element(m_Size-num), 0xDD, num * sizeof(T));
#endif
}
}
//-----------------------------------------------------------------------------
// Adds an element, uses default constructor
//-----------------------------------------------------------------------------
template< class T >
template <class T>
inline int CUtlVector<T>::AddToHead()
{
return InsertBefore(0);
}
template< class T >
template <class T>
inline int CUtlVector<T>::AddToTail()
{
return InsertBefore( m_Size );
return InsertBefore(m_Size);
}
template< class T >
inline int CUtlVector<T>::InsertAfter( int elem )
template <class T>
inline int CUtlVector<T>::InsertAfter(int elem)
{
return InsertBefore( elem + 1 );
return InsertBefore(elem + 1);
}
template< class T >
int CUtlVector<T>::InsertBefore( int elem )
template <class T>
int CUtlVector<T>::InsertBefore(int elem)
{
// Can insert at the end
assert( (elem == Count()) || IsValidIndex(elem) );
Assert((elem == Count()) || IsValidIndex(elem));
GrowVector();
ShiftElementsRight(elem);
Construct( &Element(elem) );
Construct(&Element(elem));
return elem;
}
//-----------------------------------------------------------------------------
// Adds an element, uses copy constructor
//-----------------------------------------------------------------------------
template< class T >
inline int CUtlVector<T>::AddToHead( T const& src )
template <class T>
inline int CUtlVector<T>::AddToHead(T const &src)
{
return InsertBefore( 0, src );
return InsertBefore(0, src);
}
template< class T >
inline int CUtlVector<T>::AddToTail( T const& src )
inline int CUtlVector<T>::AddToTail(T const &src)
{
return InsertBefore( m_Size, src );
return InsertBefore(m_Size, src);
}
template< class T >
inline int CUtlVector<T>::InsertAfter( int elem, T const& src )
inline int CUtlVector<T>::InsertAfter(int elem, T const &src)
{
return InsertBefore( elem + 1, src );
return InsertBefore(elem + 1, src);
}
template< class T >
int CUtlVector<T>::InsertBefore( int elem, T const& src )
int CUtlVector<T>::InsertBefore(int elem, T const &src)
{
// Can insert at the end
assert( (elem == Count()) || IsValidIndex(elem) );
Assert((elem == Count()) || IsValidIndex(elem));
GrowVector();
ShiftElementsRight(elem);
CopyConstruct( &Element(elem), src );
CopyConstruct(&Element(elem), src);
return elem;
}
//-----------------------------------------------------------------------------
// Adds multiple elements, uses default constructor
//-----------------------------------------------------------------------------
template< class T >
inline int CUtlVector<T>::AddMultipleToHead( int num )
template <class T>
inline int CUtlVector<T>::AddMultipleToHead(int num)
{
return InsertMultipleBefore( 0, num );
return InsertMultipleBefore(0, num);
}
template< class T >
inline int CUtlVector<T>::AddMultipleToTail( int num, const T *pToCopy )
template <class T>
inline int CUtlVector<T>::AddMultipleToTail(int num, const T *pToCopy)
{
return InsertMultipleBefore( m_Size, num, pToCopy );
return InsertMultipleBefore(m_Size, num, pToCopy);
}
template< class T >
int CUtlVector<T>::InsertMultipleAfter( int elem, int num )
template <class T>
int CUtlVector<T>::InsertMultipleAfter(int elem, int num)
{
return InsertMultipleBefore( elem + 1, num );
return InsertMultipleBefore(elem + 1, num);
}
template< class T >
void CUtlVector<T>::SetCount( int count )
template <class T>
void CUtlVector<T>::SetCount(int count)
{
RemoveAll();
AddMultipleToTail( count );
AddMultipleToTail(count);
}
template< class T >
inline void CUtlVector<T>::SetSize( int size )
template <class T>
inline void CUtlVector<T>::SetSize(int size)
{
SetCount( size );
SetCount(size);
}
template< class T >
void CUtlVector<T>::CopyArray( T const *pArray, int size )
template <class T>
void CUtlVector<T>::CopyArray(T const *pArray, int size)
{
SetSize( size );
for( int i=0; i < size; i++ )
SetSize(size);
for(int i = 0; i < size; i++)
{
(*this)[i] = pArray[i];
}
}
template< class T >
int CUtlVector<T>::AddVectorToTail( CUtlVector const &src )
template <class T>
int CUtlVector<T>::AddVectorToTail(CUtlVector const &src)
{
int base = Count();
// Make space.
AddMultipleToTail( src.Count() );
AddMultipleToTail(src.Count());
// Copy the elements.
for ( int i=0; i < src.Count(); i++ )
for (int i = 0; i < src.Count(); i++)
{
(*this)[base + i] = src[i];
}
return base;
}
template< class T >
inline int CUtlVector<T>::InsertMultipleBefore( int elem, int num, const T *pToInsert )
template <class T>
inline int CUtlVector<T>::InsertMultipleBefore(int elem, int num, const T *pToInsert)
{
if( num == 0 )
if(num == 0)
return elem;
// Can insert at the end
assert( (elem == Count()) || IsValidIndex(elem) );
Assert((elem == Count()) || IsValidIndex(elem));
GrowVector(num);
ShiftElementsRight(elem, num);
// Invoke default constructors
for (int i = 0; i < num; ++i)
Construct( &Element(elem+i) );
for (int i = 0; i < num; i++)
{
Construct(&Element(elem+i));
}
// Copy stuff in?
if ( pToInsert )
if (pToInsert)
{
for ( int i=0; i < num; i++ )
for (int i = 0; i < num; i++)
{
Element( elem+i ) = pToInsert[i];
Element(elem+i) = pToInsert[i];
}
}
return elem;
}
//-----------------------------------------------------------------------------
// Finds an element (element needs operator== defined)
//-----------------------------------------------------------------------------
template< class T >
int CUtlVector<T>::Find( T const& src ) const
template <class T>
int CUtlVector<T>::Find(T const &src) const
{
for ( int i = 0; i < Count(); ++i )
for (int i = 0; i < Count(); i++)
{
if (Element(i) == src)
return i;
}
return -1;
return InvalidIndex();
}
template< class T >
bool CUtlVector<T>::HasElement( T const& src )
template <class T>
bool CUtlVector<T>::HasElement(T const &src)
{
return ( Find(src) >= 0 );
return (Find(src) >= 0);
}
//-----------------------------------------------------------------------------
// Element removal
//-----------------------------------------------------------------------------
template< class T >
void CUtlVector<T>::FastRemove( int elem )
template <class T>
void CUtlVector<T>::FastRemove(int elem)
{
assert( IsValidIndex(elem) );
Assert(IsValidIndex(elem));
Destruct( &Element(elem) );
Destruct(&Element(elem));
if (m_Size > 0)
{
memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) );
--m_Size;
memcpy(&Element(elem), &Element(m_Size - 1), sizeof(T));
m_Size--;
}
}
template< class T >
void CUtlVector<T>::Remove( int elem )
template <class T>
void CUtlVector<T>::Remove(int elem)
{
Destruct( &Element(elem) );
Destruct(&Element(elem));
ShiftElementsLeft(elem);
--m_Size;
m_Size--;
}
template< class T >
void CUtlVector<T>::FindAndRemove( T const& src )
template <class T>
void CUtlVector<T>::FindAndRemove(T const &src)
{
int elem = Find( src );
if ( elem != -1 )
int elem = Find(src);
if (elem != InvalidIndex())
{
Remove( elem );
Remove(elem);
}
}
template< class T >
void CUtlVector<T>::RemoveMultiple( int elem, int num )
template <class T>
void CUtlVector<T>::RemoveMultiple(int elem, int num)
{
assert( IsValidIndex(elem) );
assert( elem + num <= Count() );
Assert(IsValidIndex(elem));
Assert(elem + num <= Count());
for (int i = elem + num; --i >= elem; )
for (int i = elem + num; --i >= elem;)
Destruct(&Element(i));
ShiftElementsLeft(elem, num);
m_Size -= num;
}
template< class T >
template <class T>
void CUtlVector<T>::RemoveAll()
{
for (int i = m_Size; --i >= 0; )
for (int i = m_Size; --i >= 0;)
Destruct(&Element(i));
m_Size = 0;
}
//-----------------------------------------------------------------------------
// Memory deallocation
//-----------------------------------------------------------------------------
template< class T >
template <class T>
void CUtlVector<T>::Purge()
{
RemoveAll();
m_Memory.Purge( );
m_Memory.Purge();
ResetDbgInfo();
}
template<class T>
template <class T>
inline void CUtlVector<T>::PurgeAndDeleteElements()
{
for( int i=0; i < m_Size; i++ )
for (int i = 0; i < m_Size; i++)
delete Element(i);
Purge();
}
template< class T >
void CUtlVector<T>::SetGrowSize( int size )
template <class T>
void CUtlVector<T>::SetGrowSize(int size)
{
m_Memory.SetGrowSize( size );
m_Memory.SetGrowSize(size);
}
#endif // CCVECTOR_H

View File

@ -3,5 +3,6 @@ include 'dep/cppunitlite'
include 'dep/bzip2'
include 'rehlds'
include 'rehlds/dedicated'
include 'rehlds/filesystem/FileSystem_Stdio'
include 'rehlds/HLTV', 'rehlds/HLTV/Core', 'rehlds/HLTV/Proxy', 'rehlds/HLTV/Console', 'rehlds/HLTV/Director', 'rehlds/HLTV/DemoPlayer'
include 'flightrec/decoder_api', 'flightrec/decoder'

View File

@ -66,6 +66,6 @@ rootProject.ext.createGccConfig = { boolean release, BinaryKind binKind ->
)
}
cfg.singleDefines('LINUX')
cfg.singleDefines('LINUX', '_LINUX')
return cfg
}

View File

@ -66,6 +66,6 @@ rootProject.ext.createIccConfig = { boolean release, BinaryKind binKind ->
)
}
cfg.singleDefines('LINUX')
cfg.singleDefines('LINUX', '_LINUX')
return cfg
}