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:
parent
dab2663e6c
commit
0daf12924d
@ -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
|
||||
|
@ -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 {
|
||||
|
158
rehlds/filesystem/FileSystem_Stdio/build.gradle
Normal file
158
rehlds/filesystem/FileSystem_Stdio/build.gradle
Normal 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
|
||||
}
|
39
rehlds/filesystem/FileSystem_Stdio/msvc/PostBuild.bat
Normal file
39
rehlds/filesystem/FileSystem_Stdio/msvc/PostBuild.bat
Normal 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
|
22
rehlds/filesystem/FileSystem_Stdio/msvc/filesystem_stdio.sln
Normal file
22
rehlds/filesystem/FileSystem_Stdio/msvc/filesystem_stdio.sln
Normal 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
|
174
rehlds/filesystem/FileSystem_Stdio/msvc/filesystem_stdio.vcxproj
Normal file
174
rehlds/filesystem/FileSystem_Stdio/msvc/filesystem_stdio.vcxproj
Normal 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>
|
@ -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>
|
1676
rehlds/filesystem/FileSystem_Stdio/src/BaseFileSystem.cpp
Normal file
1676
rehlds/filesystem/FileSystem_Stdio/src/BaseFileSystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
378
rehlds/filesystem/FileSystem_Stdio/src/BaseFileSystem.h
Normal file
378
rehlds/filesystem/FileSystem_Stdio/src/BaseFileSystem.h
Normal 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;
|
||||
}
|
232
rehlds/filesystem/FileSystem_Stdio/src/FileSystem_Stdio.cpp
Normal file
232
rehlds/filesystem/FileSystem_Stdio/src/FileSystem_Stdio.cpp
Normal 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
|
91
rehlds/filesystem/FileSystem_Stdio/src/FileSystem_Stdio.h
Normal file
91
rehlds/filesystem/FileSystem_Stdio/src/FileSystem_Stdio.h
Normal 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;
|
||||
};
|
178
rehlds/filesystem/FileSystem_Stdio/src/filesystem_helpers.cpp
Normal file
178
rehlds/filesystem/FileSystem_Stdio/src/filesystem_helpers.cpp
Normal 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);
|
||||
}
|
36
rehlds/filesystem/FileSystem_Stdio/src/filesystem_helpers.h
Normal file
36
rehlds/filesystem/FileSystem_Stdio/src/filesystem_helpers.h
Normal 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, ...);
|
258
rehlds/filesystem/FileSystem_Stdio/src/linux_support.cpp
Normal file
258
rehlds/filesystem/FileSystem_Stdio/src/linux_support.cpp
Normal 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)
|
62
rehlds/filesystem/FileSystem_Stdio/src/linux_support.h
Normal file
62
rehlds/filesystem/FileSystem_Stdio/src/linux_support.h
Normal 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
|
898
rehlds/filesystem/FileSystem_Stdio/src/pathmatch.cpp
Normal file
898
rehlds/filesystem/FileSystem_Stdio/src/pathmatch.cpp
Normal 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
|
2031
rehlds/filesystem/FileSystem_Stdio/src/pathmatch_casefolding.h
Normal file
2031
rehlds/filesystem/FileSystem_Stdio/src/pathmatch_casefolding.h
Normal file
File diff suppressed because it is too large
Load Diff
29
rehlds/filesystem/FileSystem_Stdio/src/precompiled.cpp
Normal file
29
rehlds/filesystem/FileSystem_Stdio/src/precompiled.cpp
Normal 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"
|
40
rehlds/filesystem/FileSystem_Stdio/src/precompiled.h
Normal file
40
rehlds/filesystem/FileSystem_Stdio/src/precompiled.h
Normal 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"
|
@ -0,0 +1,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "interface.cpp"
|
||||
#include "utlsymbol.cpp"
|
||||
|
||||
#include "tier0/dbg.cpp"
|
||||
#include "tier0/characterset.cpp"
|
5
rehlds/filesystem/build.gradle
Normal file
5
rehlds/filesystem/build.gradle
Normal file
@ -0,0 +1,5 @@
|
||||
evaluationDependsOn(':rehlds/filesystem/FileSystem_Stdio');
|
||||
|
||||
task build {
|
||||
dependsOn project(':rehlds/filesystem/FileSystem_Stdio').tasks.build
|
||||
}
|
182
rehlds/hookers/filesystem/hooklist.cpp
Normal file
182
rehlds/hookers/filesystem/hooklist.cpp
Normal 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 },
|
||||
};
|
42
rehlds/hookers/filesystem/hooklist.h
Normal file
42
rehlds/hookers/filesystem/hooklist.h
Normal 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
|
86
rehlds/hookers/filesystem/main.cpp
Normal file
86
rehlds/hookers/filesystem/main.cpp
Normal 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)
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;}\
|
||||
|
50
rehlds/public/tier0/characterset.cpp
Normal file
50
rehlds/public/tier0/characterset.cpp
Normal 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++;
|
||||
}
|
||||
}
|
46
rehlds/public/tier0/characterset.h
Normal file
46
rehlds/public/tier0/characterset.h
Normal 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)])
|
@ -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 */
|
||||
|
||||
|
@ -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
152
rehlds/public/utlsymbol.cpp
Normal 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
113
rehlds/public/utlsymbol.h
Normal 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];
|
||||
}
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -66,6 +66,6 @@ rootProject.ext.createGccConfig = { boolean release, BinaryKind binKind ->
|
||||
)
|
||||
}
|
||||
|
||||
cfg.singleDefines('LINUX')
|
||||
cfg.singleDefines('LINUX', '_LINUX')
|
||||
return cfg
|
||||
}
|
||||
|
@ -66,6 +66,6 @@ rootProject.ext.createIccConfig = { boolean release, BinaryKind binKind ->
|
||||
)
|
||||
}
|
||||
|
||||
cfg.singleDefines('LINUX')
|
||||
cfg.singleDefines('LINUX', '_LINUX')
|
||||
return cfg
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user