diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/kvc/kvc_paintkit.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/kvc/kvc_paintkit.cpp')
| -rw-r--r-- | utils/kvc/kvc_paintkit.cpp | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/utils/kvc/kvc_paintkit.cpp b/utils/kvc/kvc_paintkit.cpp new file mode 100644 index 0000000..967c82f --- /dev/null +++ b/utils/kvc/kvc_paintkit.cpp @@ -0,0 +1,421 @@ +//===================== Copyright (c) Valve Corporation. All Rights Reserved. ====================== +// +//================================================================================================== + + +#if defined( WIN32 ) && !defined( _X360 ) +#include <windows.h> // SRC only!! +#endif // + +#include "filesystem.h" +#include "tier0/icommandline.h" +#include "tier1/keyvalues.h" +#include "tier2/keyvaluesmacros.h" + + +#include "kvc_paintkit.h" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//-------------------------------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------------------------------- +static void WriteIndent( IBaseFileSystem *pFileSystem, FileHandle_t hFile, bool bOptTabs, int nOptTabWidth, int nIndentLevel ) +{ + if ( nIndentLevel <= 0 ) + return; + + if ( bOptTabs || nOptTabWidth <= 0 ) + { + char *szTabIndent = ( char * )stackalloc( nIndentLevel + 1 ); + V_memset( szTabIndent, '\t', nIndentLevel ); + szTabIndent[nIndentLevel] = '\0'; + pFileSystem->Write( szTabIndent, nIndentLevel, hFile ); + } + else + { + const int nSpaceCount = nIndentLevel * nOptTabWidth; + char *szSpaceIndent = ( char * )stackalloc( nSpaceCount + 1 ); + V_memset( szSpaceIndent, ' ', nSpaceCount ); + szSpaceIndent[nSpaceCount] = '\0'; + pFileSystem->Write( szSpaceIndent, nSpaceCount, hFile ); + } +} + + +//-------------------------------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------------------------------- +static void WritePadding( IBaseFileSystem *pFileSystem, FileHandle_t hFile, bool bOptTabs, int nOptTabWidth, int nCurrentColumn, int nTargetColumn ) +{ + if ( nCurrentColumn <= 0 || nTargetColumn <= 0 || nTargetColumn <= nCurrentColumn ) + { + WriteIndent( pFileSystem, hFile, bOptTabs, nOptTabWidth, 1 ); + return; + } + + if ( bOptTabs || nOptTabWidth <= 0 ) + { + if ( nOptTabWidth <= 0 ) + { + nOptTabWidth = 4; // Can't handle 0 tab width, use 4 + } + + nTargetColumn = ( nTargetColumn + nOptTabWidth - 1 ) / nOptTabWidth * nOptTabWidth; // Round to next tab stop + + Assert( nTargetColumn % nOptTabWidth == 0 ); + + const int nTabCount = ( nTargetColumn - nCurrentColumn ) / nOptTabWidth; + + char *szTabPadding = ( char * )stackalloc( nTabCount + 1 ); + V_memset( szTabPadding, '\t', nTabCount ); + szTabPadding[nTabCount] = '\0'; + pFileSystem->Write( szTabPadding, nTabCount, hFile ); + } + else + { + nTargetColumn = ( nTargetColumn + nOptTabWidth - 1 ) / nOptTabWidth * nOptTabWidth; // Round to next tab stop + + Assert( nTargetColumn % nOptTabWidth == 0 ); + + const int nSpaceCount = nTargetColumn - nCurrentColumn; + char *szSpacePadding = ( char * )stackalloc( nSpaceCount + 1 ); + V_memset( szSpacePadding, ' ', nSpaceCount ); + szSpacePadding[nSpaceCount] = '\0'; + pFileSystem->Write( szSpacePadding, nSpaceCount, hFile ); + } +} + + +//-------------------------------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------------------------------- +static void WriteConvertedString( IBaseFileSystem *pFileSystem, FileHandle_t hFile, const char *pszString ) +{ + // handle double quote chars within the string + // the worst possible case is that the whole string is quotes + int nSrcLen = Q_strlen( pszString ); + char *szConvertedString = ( char * )stackalloc( ( nSrcLen + 1 ) * sizeof( char ) * 2 ); + int j = 0; + for ( int i = 0; i <= nSrcLen; ++i ) + { + if ( pszString[i] == '\"' ) + { + szConvertedString[j] = '\\'; + ++j; + } + szConvertedString[j] = pszString[i]; + ++j; + } + + pFileSystem->Write( szConvertedString, V_strlen( szConvertedString ), hFile ); +} + + +//-------------------------------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------------------------------- +template <size_t maxLenInChars> static int CleanFloatString( OUT_Z_ARRAY char (&pszFloatBuf)[maxLenInChars] ) +{ + int nStrLen = V_strlen( pszFloatBuf ); + + const char *pDecimal = V_strnchr( pszFloatBuf, '.', maxLenInChars - 1 ); + if ( pDecimal ) + { + ++pDecimal; // Keep number after decimal always + + char *pToStrip = pszFloatBuf + nStrLen - 1; + while ( pToStrip > pDecimal && *pToStrip == '0' ) + { + *pToStrip = '\0'; + --pToStrip; + --nStrLen; + } + } + + return nStrLen; +} + + +//-------------------------------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------------------------------- +static void SaveToFile_R( KeyValues *pkv, IBaseFileSystem *pFileSystem, FileHandle_t hFile, bool bOptTabs, int nOptTabWidth, int nIndentLevel, int nValueColumn = -1 ) +{ + WriteIndent( pFileSystem, hFile, bOptTabs, nOptTabWidth, nIndentLevel ); + pFileSystem->Write( "\"", 1, hFile ); + WriteConvertedString( pFileSystem, hFile, pkv->GetName() ); + pFileSystem->Write( "\"", 1, hFile ); + + if ( pkv->GetFirstSubKey() ) + { + int nMaxSubKeyNameLength = 0; + + for ( KeyValues *pkvSubKey = pkv->GetFirstSubKey(); pkvSubKey; pkvSubKey = pkvSubKey->GetNextKey() ) + { + const int nNameLength = V_strlen( pkvSubKey->GetName() ); + nMaxSubKeyNameLength = Max( nNameLength, nMaxSubKeyNameLength ); + } + + int nSubKeyValueColumn = -1; + + if ( nMaxSubKeyNameLength > 0 ) + { + nSubKeyValueColumn = nMaxSubKeyNameLength + 1; + } + + pFileSystem->Write( "\n", 1, hFile ); + WriteIndent( pFileSystem, hFile, bOptTabs, nOptTabWidth, nIndentLevel ); + pFileSystem->Write( "{\n", 2, hFile ); + for ( KeyValues *pkvSubKey = pkv->GetFirstSubKey(); pkvSubKey; pkvSubKey = pkvSubKey->GetNextKey() ) + { + SaveToFile_R( pkvSubKey, pFileSystem, hFile, bOptTabs, nOptTabWidth, nIndentLevel + 1, nSubKeyValueColumn ); + } + WriteIndent( pFileSystem, hFile, bOptTabs, nOptTabWidth, nIndentLevel ); + pFileSystem->Write( "}\n", 2, hFile ); + } + else + { + if ( nValueColumn > 0 ) + { + const int nNameLength = V_strlen( pkv->GetName() ); + WritePadding( pFileSystem, hFile, bOptTabs, nOptTabWidth, nNameLength, nValueColumn ); + } + else + { + WriteIndent( pFileSystem, hFile, bOptTabs, nOptTabWidth, 1 ); // Don't know which column to align things on + } + + pFileSystem->Write( "\"", 1, hFile ); + + switch ( pkv->GetDataType() ) + { + case KeyValues::TYPE_STRING: + { + const char *pszStringValue = pkv->GetString(); + if ( pszStringValue ) + { + WriteConvertedString( pFileSystem, hFile, pszStringValue ); + } + break; + } + case KeyValues::TYPE_WSTRING: + { + const wchar_t *pszWString = pkv->GetWString(); + if ( pszWString ) + { + const size_t nTmpBufSize = 4096; + char *szTmpBuf = ( char * )stackalloc( nTmpBufSize * sizeof( char ) ); + V_memset( szTmpBuf, '\0', nTmpBufSize ); + const int nResult = Q_UnicodeToUTF8( pszWString, szTmpBuf, nTmpBufSize ); + if ( nResult != 0 ) + { + WriteConvertedString( pFileSystem, hFile, szTmpBuf ); + } + } + break; + } + case KeyValues::TYPE_INT: + { + char szTmpBuf[32] = {}; + V_snprintf( szTmpBuf, sizeof( szTmpBuf ), "%d", pkv->GetInt() ); + pFileSystem->Write( szTmpBuf, V_strlen( szTmpBuf ), hFile ); + break; + } + case KeyValues::TYPE_UINT64: + { + char szTmpBuf[32] = {}; + // write "0x" + 16 char 0-padded hex encoded 64 bit value +#ifdef WIN32 + Q_snprintf( szTmpBuf, sizeof( szTmpBuf ), "0x%016I64X", *( ( uint64 * )pkv->GetUint64() ) ); +#else + Q_snprintf( szTmpBuf, sizeof( szTmpBuf ), "0x%016llX", *( ( uint64 * )pkv->GetUint64() ) ); +#endif + pFileSystem->Write( szTmpBuf, V_strlen( szTmpBuf ), hFile ); + break; + } + case KeyValues::TYPE_FLOAT: + { + char szTmpBuf[32] = {}; + V_snprintf( szTmpBuf, sizeof( szTmpBuf ), "%f", pkv->GetFloat() ); + int nStrLen = V_strlen( szTmpBuf ); + nStrLen = CleanFloatString( szTmpBuf ); + pFileSystem->Write( szTmpBuf, nStrLen, hFile ); + break; + } + case KeyValues::TYPE_COLOR: + { + char szTmpBuf[32] = {}; + const Color c = pkv->GetColor(); + V_snprintf( szTmpBuf, sizeof( szTmpBuf ), "%d", c.r() ); + pFileSystem->Write( " ", 1, hFile ); + V_snprintf( szTmpBuf, sizeof( szTmpBuf ), "%d", c.g() ); + pFileSystem->Write( " ", 1, hFile ); + V_snprintf( szTmpBuf, sizeof( szTmpBuf ), "%d", c.b() ); + pFileSystem->Write( " ", 1, hFile ); + V_snprintf( szTmpBuf, sizeof( szTmpBuf ), "%d", c.a() ); + break; + } + default: + break; + } + pFileSystem->Write( "\"\n", 2, hFile ); + } +} + + +//-------------------------------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------------------------------- +static bool SaveCleanKeyValuesToFile( KeyValues *pkv, IBaseFileSystem *pFileSystem, const char *pszFileName, const char *pszPathID = nullptr, bool bOptTabs = true, int nOptSpaceIndent = 4 ) +{ + // Write out KeyValues to the specified file but cleaner than KeyValues::SaveToFile + // create a write file + FileHandle_t hFile = pFileSystem->Open( pszFileName, "wb", pszPathID ); + + if ( hFile == FILESYSTEM_INVALID_HANDLE ) + { + Msg( "CleanSaveKeyValuesToFile: Couldn't open file \"%s\" for writing in path \"%s\".\n", + pszFileName ? pszFileName : "NULL", pszPathID ? pszPathID : "NULL" ); + return false; + } + + for ( KeyValues *pkvTmp = pkv; pkvTmp; pkvTmp = pkvTmp->GetNextKey() ) + { + SaveToFile_R( pkvTmp, pFileSystem, hFile, bOptTabs, nOptSpaceIndent, 0 ); + } + + pFileSystem->Close( hFile ); + + return true; +} + + +//-------------------------------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------------------------------- +void ProcessPaintKitKeyValuesFile( const char *pszPaintKitKeyValuesFile, bool bOptFix, bool bOptVerbose ) +{ + if ( bOptVerbose ) + { + Msg( "Processing: %s\n", pszPaintKitKeyValuesFile ); + } + + char szFullPath[MAX_PATH] = {}; + + if ( !V_IsAbsolutePath( pszPaintKitKeyValuesFile ) ) + { + g_pFullFileSystem->RelativePathToFullPath_safe( pszPaintKitKeyValuesFile, nullptr, szFullPath ); + if ( !V_IsAbsolutePath( szFullPath ) ) + { + char szTmpA[MAX_PATH] = {}; + char szTmpB[MAX_PATH] = {}; + + if ( !g_pFullFileSystem->GetCurrentDirectoryA( szTmpA, ARRAYSIZE( szTmpB ) ) ) + { + Msg( "Error: non-resolvable, non-absolute path specified (%s) and couldn't determine current directory\n", pszPaintKitKeyValuesFile ); + return; + } + + V_ComposeFileName( szTmpA, pszPaintKitKeyValuesFile, szTmpB, ARRAYSIZE( szTmpB ) ); + V_FixupPathName( szTmpA, ARRAYSIZE( szTmpA ), szTmpB ); + g_pFullFileSystem->GetCaseCorrectFullPath( szTmpB, szFullPath ); + } + } + + if ( !V_IsAbsolutePath( szFullPath ) ) + { + Msg( "Error: Couldn't find absolute path to file: %s\n", pszPaintKitKeyValuesFile ); + return; + } + + if ( !g_pFullFileSystem->FileExists( szFullPath ) ) + { + Msg( "Error: Couldn't find file: %s\n", szFullPath ); + return; + } + + KeyValues *pkv = new KeyValues( "" ); + const bool bLoaded = pkv->LoadFromFile( g_pFullFileSystem, szFullPath ); + if ( bLoaded ) + { + for ( KeyValues *pkvTmp = pkv; pkvTmp; pkvTmp = pkvTmp->GetNextKey() ) + { + HandleKeyValuesMacros( pkvTmp ); + } + + char szFilename[MAX_PATH] = {}; + + if ( bOptFix ) + { + V_strcpy_safe( szFilename, szFullPath ); + V_strcat_safe( szFilename, "_fix" ); + + if ( bOptVerbose ) + { + Msg( " Saving: %s\n", szFilename ); + } + + if ( !SaveCleanKeyValuesToFile( pkv, g_pFullFileSystem, szFilename, nullptr, false ) ) + { + Msg( "Error: Couldn't write: %s\n", szFilename ); + } + } + else + { + V_strcpy_safe( szFilename, szFullPath ); + V_strcat_safe( szFilename, "_bak" ); + + if ( bOptVerbose ) + { + Msg( " Copying: %s -> %s\n", szFullPath, szFilename ); + } + + if ( CopyFile( szFullPath, szFilename, false ) ) + { + if ( bOptVerbose ) + { + Msg( " Saving: %s\n", szFullPath ); + } + + if ( !SaveCleanKeyValuesToFile( pkv, g_pFullFileSystem, szFullPath, nullptr, false ) ) + { + Msg( "Error: Couldn't write: %s\n", szFullPath ); + } + } + else + { + Msg( "Error: Couldn't copy %s to %s, aborting\n", szFullPath, szFilename ); + } + } + + pkv->SaveToFile( g_pFullFileSystem, "c:/tmp/bar.txt" ); + } + else + { + Msg( " + Couldn't Load: %s\n", szFullPath ); + } + + pkv->deleteThis(); +} + + +//-------------------------------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------------------------------- +void ProcessPaintKitKeyValuesFiles( const CUtlVector< CUtlSymbol > &workList ) +{ + // This bit of hackery allows us to access files on the harddrive + g_pFullFileSystem->AddSearchPath( "", "LOCAL", PATH_ADD_TO_HEAD ); + + const bool bOptFix = CommandLine()->CheckParm( "-f" ) != nullptr; + const bool bOptVerbose = CommandLine()->CheckParm( "-v" ) != nullptr; + + for ( int i = 0; i < workList.Count(); ++i ) + { + ProcessPaintKitKeyValuesFile( workList[i].String(), bOptFix, bOptVerbose ); + } +}
\ No newline at end of file |