mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-01-03 16:13:22 +08:00
Port KeyValues class from Source SDK 2013.
This commit is contained in:
parent
921bfd15d3
commit
a6722dd010
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: This header should never be used directly from leaf code!!!
|
||||
// Instead, just add the file memoverride.cpp into your project and all this
|
||||
@ -14,25 +14,31 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if !defined(NO_MALLOC_OVERRIDE) && defined(POSIX)
|
||||
#define NO_MALLOC_OVERRIDE
|
||||
#endif
|
||||
|
||||
// These memory debugging switches aren't relevant under Linux builds since memoverride.cpp
|
||||
// isn't built into Linux projects
|
||||
#ifndef POSIX
|
||||
// Define this in release to get memory tracking even in release builds
|
||||
//#define USE_MEM_DEBUG 1
|
||||
#endif
|
||||
|
||||
#if defined( _MEMTEST )
|
||||
#ifdef _WIN32
|
||||
#define USE_MEM_DEBUG 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Undefine this if using a compiler lacking threadsafe RTTI (like vc6)
|
||||
#define MEM_DEBUG_CLASSNAME 1
|
||||
|
||||
#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
|
||||
|
||||
#include <stddef.h>
|
||||
#if defined( OSX )
|
||||
#include <malloc/malloc.h>
|
||||
#endif
|
||||
|
||||
#include "tier0/mem.h"
|
||||
|
||||
#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
|
||||
|
||||
struct _CrtMemState;
|
||||
|
||||
#define MEMALLOC_VERSION 1
|
||||
@ -107,7 +113,17 @@ public:
|
||||
#endif
|
||||
|
||||
// Returns 0 if no failure, otherwise the size_t of the last requested chunk
|
||||
// "I'm sure this is completely thread safe!" Brian Deen 7/19/2012.
|
||||
virtual size_t MemoryAllocFailed() = 0;
|
||||
|
||||
// handles storing allocation info for coroutines
|
||||
virtual uint32 GetDebugInfoSize() = 0;
|
||||
virtual void SaveDebugInfo( void *pvDebugInfo ) = 0;
|
||||
virtual void RestoreDebugInfo( const void *pvDebugInfo ) = 0;
|
||||
virtual void InitDebugInfo( void *pvDebugInfo, const char *pchRootFileName, int nLine ) = 0;
|
||||
|
||||
// Replacement for ::GlobalMemoryStatus which accounts for unused memory in our system
|
||||
virtual void GlobalMemoryStatus( size_t *pUsedMemory, size_t *pFreeMemory ) = 0;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -117,11 +133,52 @@ MEM_INTERFACE IMemAlloc *g_pMemAlloc;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MEMALLOC_REGIONS
|
||||
#ifndef MEMALLOC_REGION
|
||||
#define MEMALLOC_REGION 0
|
||||
#endif
|
||||
inline void *MemAlloc_Alloc( size_t nSize )
|
||||
{
|
||||
return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize );
|
||||
}
|
||||
|
||||
inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
|
||||
{
|
||||
return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize, pFileName, nLine );
|
||||
}
|
||||
#else
|
||||
#undef MEMALLOC_REGION
|
||||
inline void *MemAlloc_Alloc( size_t nSize )
|
||||
{
|
||||
return g_pMemAlloc->Alloc( nSize );
|
||||
}
|
||||
|
||||
inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
|
||||
{
|
||||
return g_pMemAlloc->Alloc( nSize, pFileName, nLine );
|
||||
}
|
||||
#endif
|
||||
inline void MemAlloc_Free( void *ptr )
|
||||
{
|
||||
g_pMemAlloc->Free( ptr );
|
||||
}
|
||||
inline void MemAlloc_Free( void *ptr, const char *pFileName, int nLine )
|
||||
{
|
||||
g_pMemAlloc->Free( ptr, pFileName, nLine );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool ValueIsPowerOfTwo( size_t value ) // don't clash with mathlib definition
|
||||
{
|
||||
return (value & ( value - 1 )) == 0;
|
||||
}
|
||||
|
||||
inline void *MemAlloc_AllocAligned( size_t size, size_t align )
|
||||
{
|
||||
unsigned char *pAlloc, *pResult;
|
||||
|
||||
if (!IsPowerOfTwo(uint(align)))
|
||||
if (!IsPowerOfTwo(align))
|
||||
return NULL;
|
||||
|
||||
align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
|
||||
@ -139,7 +196,7 @@ inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFi
|
||||
{
|
||||
unsigned char *pAlloc, *pResult;
|
||||
|
||||
if (!IsPowerOfTwo(uint(align)))
|
||||
if (!IsPowerOfTwo(align))
|
||||
return NULL;
|
||||
|
||||
align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
|
||||
@ -153,9 +210,45 @@ inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFi
|
||||
return (void *)pResult;
|
||||
}
|
||||
|
||||
inline void *MemAlloc_AllocAlignedUnattributed( size_t size, size_t align )
|
||||
{
|
||||
unsigned char *pAlloc, *pResult;
|
||||
|
||||
if (!ValueIsPowerOfTwo(align))
|
||||
return NULL;
|
||||
|
||||
align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
|
||||
|
||||
if ( (pAlloc = (unsigned char*)MemAlloc_Alloc( sizeof(void *) + align + size ) ) == (unsigned char*)NULL)
|
||||
return NULL;
|
||||
|
||||
pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
|
||||
((unsigned char**)(pResult))[-1] = pAlloc;
|
||||
|
||||
return (void *)pResult;
|
||||
}
|
||||
|
||||
inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const char *pszFile, int nLine )
|
||||
{
|
||||
unsigned char *pAlloc, *pResult;
|
||||
|
||||
if (!ValueIsPowerOfTwo(align))
|
||||
return NULL;
|
||||
|
||||
align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
|
||||
|
||||
if ( (pAlloc = (unsigned char*)MemAlloc_Alloc( sizeof(void *) + align + size, pszFile, nLine ) ) == (unsigned char*)NULL)
|
||||
return NULL;
|
||||
|
||||
pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
|
||||
((unsigned char**)(pResult))[-1] = pAlloc;
|
||||
|
||||
return (void *)pResult;
|
||||
}
|
||||
|
||||
inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align )
|
||||
{
|
||||
if ( !IsPowerOfTwo( uint(align) ) )
|
||||
if ( !IsPowerOfTwo( align ) )
|
||||
return NULL;
|
||||
|
||||
// Don't change alignment between allocation + reallocation.
|
||||
@ -201,6 +294,23 @@ inline void MemAlloc_FreeAligned( void *pMemBlock )
|
||||
g_pMemAlloc->Free( pAlloc );
|
||||
}
|
||||
|
||||
inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pFileName, int nLine )
|
||||
{
|
||||
void *pAlloc;
|
||||
|
||||
if ( pMemBlock == NULL )
|
||||
return;
|
||||
|
||||
pAlloc = pMemBlock;
|
||||
|
||||
// pAlloc points to the pointer to starting of the memory block
|
||||
pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
|
||||
|
||||
// pAlloc is the pointer to the start of memory block
|
||||
pAlloc = *( (void **)pAlloc );
|
||||
g_pMemAlloc->Free( pAlloc, pFileName, nLine );
|
||||
}
|
||||
|
||||
inline size_t MemAlloc_GetSizeAligned( void *pMemBlock )
|
||||
{
|
||||
void *pAlloc;
|
||||
@ -234,6 +344,20 @@ inline size_t MemAlloc_GetSizeAligned( void *pMemBlock )
|
||||
#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
|
||||
#endif
|
||||
|
||||
#define MemAlloc_DumpStats() g_pMemAlloc->DumpStats()
|
||||
#define MemAlloc_CompactHeap() g_pMemAlloc->CompactHeap()
|
||||
#define MemAlloc_OutOfMemory() g_pMemAlloc->OutOfMemory()
|
||||
#define MemAlloc_CompactIncremental() g_pMemAlloc->CompactIncremental()
|
||||
#define MemAlloc_DumpStatsFileBase( _filename ) g_pMemAlloc->DumpStatsFileBase( _filename )
|
||||
#define MemAlloc_CrtCheckMemory() g_pMemAlloc->CrtCheckMemory()
|
||||
#define MemAlloc_GlobalMemoryStatus( _usedMemory, _freeMemory ) g_pMemAlloc->GlobalMemoryStatus( _usedMemory, _freeMemory )
|
||||
#define MemAlloc_MemoryAllocFailed() g_pMemAlloc->MemoryAllocFailed()
|
||||
|
||||
#define MemAlloc_GetDebugInfoSize() g_pMemAlloc->GetDebugInfoSize()
|
||||
#define MemAlloc_SaveDebugInfo( pvDebugInfo ) g_pMemAlloc->SaveDebugInfo( pvDebugInfo )
|
||||
#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) g_pMemAlloc->RestoreDebugInfo( pvDebugInfo )
|
||||
#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) g_pMemAlloc->InitDebugInfo( pvDebugInfo, pchRootFileName, nLine )
|
||||
#define MemAlloc_GetSize( x ) g_pMemAlloc->GetSize( x );
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CMemAllocAttributeAlloction
|
||||
@ -339,6 +463,51 @@ struct MemAllocFileLine_t
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#elif defined( POSIX )
|
||||
|
||||
#if defined( OSX )
|
||||
// Mac always aligns allocs, don't need to call posix_memalign which doesn't exist in 10.5.8 which TF2 still needs to run on
|
||||
//inline void *memalign(size_t alignment, size_t size) {void *pTmp=NULL; posix_memalign(&pTmp, alignment, size); return pTmp;}
|
||||
inline void *memalign(size_t alignment, size_t size) {void *pTmp=NULL; pTmp = malloc(size); return pTmp;}
|
||||
#endif
|
||||
|
||||
inline void *_aligned_malloc( size_t nSize, size_t align ) { return memalign( align, nSize ); }
|
||||
inline void _aligned_free( void *ptr ) { free( ptr ); }
|
||||
|
||||
inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName = NULL, int nLine = 0 ) { return malloc( nSize ); }
|
||||
inline void MemAlloc_Free( void *ptr, const char *pFileName = NULL, int nLine = 0 ) { free( ptr ); }
|
||||
|
||||
inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile = NULL, int nLine = 0 ) { return memalign( align, size ); }
|
||||
inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const char *pszFile = NULL, int nLine = 0 ) { return memalign( align, size ); }
|
||||
inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile = NULL, int nLine = 0 ) { free( pMemBlock ); }
|
||||
|
||||
#if defined( OSX )
|
||||
inline size_t _msize( void *ptr ) { return malloc_size( ptr ); }
|
||||
#else
|
||||
inline size_t _msize( void *ptr ) { return malloc_usable_size( ptr ); }
|
||||
#endif
|
||||
|
||||
inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align )
|
||||
{
|
||||
void *ptr_new_aligned = memalign( align, size );
|
||||
|
||||
if( ptr_new_aligned )
|
||||
{
|
||||
size_t old_size = _msize( ptr );
|
||||
size_t copy_size = ( size < old_size ) ? size : old_size;
|
||||
|
||||
memcpy( ptr_new_aligned, ptr, copy_size );
|
||||
free( ptr );
|
||||
}
|
||||
|
||||
return ptr_new_aligned;
|
||||
}
|
||||
#else
|
||||
#define MemAlloc_GetDebugInfoSize() g_pMemAlloc->GetDebugInfoSize()
|
||||
#define MemAlloc_SaveDebugInfo( pvDebugInfo ) g_pMemAlloc->SaveDebugInfo( pvDebugInfo )
|
||||
#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) g_pMemAlloc->RestoreDebugInfo( pvDebugInfo )
|
||||
#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) g_pMemAlloc->InitDebugInfo( pvDebugInfo, pchRootFileName, nLine )
|
||||
|
||||
#endif // !STEAM && !NO_MALLOC_OVERRIDE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -347,12 +516,139 @@ struct MemAllocFileLine_t
|
||||
|
||||
#define MEM_ALLOC_CREDIT_(tag) ((void)0)
|
||||
#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
|
||||
#define MEM_ALLOC_CREDIT_FUNCTION()
|
||||
#define MEM_ALLOC_CREDIT_CLASS()
|
||||
#define MEM_ALLOC_CLASSNAME(type) NULL
|
||||
#define MEM_ALLOC_CREDIT_FUNCTION()
|
||||
|
||||
#define MemAlloc_PushAllocDbgInfo( pszFile, line )
|
||||
#define MemAlloc_PopAllocDbgInfo()
|
||||
#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
|
||||
#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
|
||||
#define MemAlloc_DumpStats() ((void)0)
|
||||
#define MemAlloc_CompactHeap() ((void)0)
|
||||
#define MemAlloc_OutOfMemory() ((void)0)
|
||||
#define MemAlloc_CompactIncremental() ((void)0)
|
||||
#define MemAlloc_DumpStatsFileBase( _filename ) ((void)0)
|
||||
inline bool MemAlloc_CrtCheckMemory() { return true; }
|
||||
inline void MemAlloc_GlobalMemoryStatus( size_t *pusedMemory, size_t *pfreeMemory )
|
||||
{
|
||||
*pusedMemory = 0;
|
||||
*pfreeMemory = 0;
|
||||
}
|
||||
#define MemAlloc_MemoryAllocFailed() 0
|
||||
|
||||
#define MemAlloc_GetDebugInfoSize() 0
|
||||
#define MemAlloc_SaveDebugInfo( pvDebugInfo ) ((void)0)
|
||||
#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) ((void)0)
|
||||
#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) ((void)0)
|
||||
|
||||
|
||||
#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
|
||||
#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
|
||||
#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
|
||||
|
||||
#endif // !STEAM && NO_MALLOC_OVERRIDE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// linux memory tracking via hooks.
|
||||
#if defined( POSIX ) && !defined( NO_HOOK_MALLOC )
|
||||
PLATFORM_INTERFACE void MemoryLogMessage( char const *s ); // throw a message into the memory log
|
||||
PLATFORM_INTERFACE void EnableMemoryLogging( bool bOnOff );
|
||||
PLATFORM_INTERFACE void DumpMemoryLog( int nThresh );
|
||||
PLATFORM_INTERFACE void DumpMemorySummary( void );
|
||||
PLATFORM_INTERFACE void SetMemoryMark( void );
|
||||
PLATFORM_INTERFACE void DumpChangedMemory( int nThresh );
|
||||
|
||||
#else
|
||||
FORCEINLINE void MemoryLogMessage( char const *s )
|
||||
{
|
||||
}
|
||||
|
||||
FORCEINLINE void EnableMemoryLogging( bool bOnOff )
|
||||
{
|
||||
}
|
||||
FORCEINLINE void DumpMemoryLog( int nThresh )
|
||||
{
|
||||
}
|
||||
FORCEINLINE void DumpMemorySummary( void )
|
||||
{
|
||||
}
|
||||
FORCEINLINE void SetMemoryMark( void )
|
||||
{
|
||||
}
|
||||
FORCEINLINE void DumpChangedMemory( int nThresh )
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef POSIX
|
||||
// ApproximateProcessMemoryUsage returns the approximate memory footprint of this process.
|
||||
PLATFORM_INTERFACE size_t ApproximateProcessMemoryUsage( void );
|
||||
#else
|
||||
FORCEINLINE size_t ApproximateProcessMemoryUsage( void )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct aligned_tmp_t
|
||||
{
|
||||
// empty base class
|
||||
};
|
||||
|
||||
/*
|
||||
This class used to be required if you wanted an object to be allocated with a specific
|
||||
alignment. ALIGN16 and ALIGN16_POST are not actually sufficient for this because they
|
||||
guarantee that the globals, statics, locals, and function parameters are appropriately
|
||||
aligned they do not affect memory allocation alignment.
|
||||
However this class is usually not needed because as of 2012 our policy is that our
|
||||
allocator should take care of this automatically. Any object whose size is a multiple
|
||||
of 16 will be 16-byte aligned. Existing uses of this class were not changed because
|
||||
the cost/benefit did not justify it.
|
||||
*/
|
||||
// template here to allow adding alignment at levels of hierarchy that aren't the base
|
||||
template< int bytesAlignment = 16, class T = aligned_tmp_t >
|
||||
class CAlignedNewDelete : public T
|
||||
{
|
||||
|
||||
public:
|
||||
/*
|
||||
Note that this class does not overload operator new[] and delete[] which means that
|
||||
classes that depend on this for alignment may end up misaligned if an array is
|
||||
allocated. This problem is now mostly theoretical because this class is mostly
|
||||
obsolete.
|
||||
*/
|
||||
void *operator new( size_t nSize )
|
||||
{
|
||||
return MemAlloc_AllocAligned( nSize, bytesAlignment );
|
||||
}
|
||||
|
||||
void* operator new( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
|
||||
{
|
||||
return MemAlloc_AllocAlignedFileLine( nSize, bytesAlignment, pFileName, nLine );
|
||||
}
|
||||
|
||||
void operator delete(void *pData)
|
||||
{
|
||||
if ( pData )
|
||||
{
|
||||
MemAlloc_FreeAligned( pData );
|
||||
}
|
||||
}
|
||||
|
||||
void operator delete( void* pData, int nBlockUse, const char *pFileName, int nLine )
|
||||
{
|
||||
if ( pData )
|
||||
{
|
||||
MemAlloc_FreeAligned( pData, pFileName, nLine );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* TIER0_MEMALLOC_H */
|
||||
|
@ -75,27 +75,58 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IsLinux() false
|
||||
#define IsOSX() false
|
||||
#define IsPosix() false
|
||||
#ifndef PLATFORM_WINDOWS
|
||||
#define PLATFORM_WINDOWS 1 // Windows PC or Xbox 360
|
||||
#endif
|
||||
#ifndef _X360
|
||||
#define IsWindows() true
|
||||
#define IsPC() true
|
||||
#define IsConsole() false
|
||||
#define IsX360() false
|
||||
#define IsPS3() false
|
||||
#define IS_WINDOWS_PC
|
||||
#else
|
||||
#ifndef _CONSOLE
|
||||
#define _CONSOLE
|
||||
#define PLATFORM_WINDOWS_PC 1 // Windows PC
|
||||
#ifdef _WIN64
|
||||
#define IsPlatformWindowsPC64() true
|
||||
#define IsPlatformWindowsPC32() false
|
||||
#define PLATFORM_WINDOWS_PC64 1
|
||||
#else
|
||||
#define IsPlatformWindowsPC64() false
|
||||
#define IsPlatformWindowsPC32() true
|
||||
#define PLATFORM_WINDOWS_PC32 1
|
||||
#endif
|
||||
#else
|
||||
#define PLATFORM_X360 1
|
||||
#ifndef _CONSOLE
|
||||
#define _CONSOLE
|
||||
#endif
|
||||
#define IsWindows() false
|
||||
#define IsPC() false
|
||||
#define IsConsole() true
|
||||
#define IsX360() true
|
||||
#define IsPS3() false
|
||||
#endif
|
||||
#elif defined(_LINUX) || defined(__APPLE__)
|
||||
#elif defined(POSIX)
|
||||
#define IsPC() true
|
||||
#define IsWindows() false
|
||||
#define IsConsole() false
|
||||
#define IsX360() false
|
||||
#define IsPS3() false
|
||||
#define IsLinux() true
|
||||
#if defined( LINUX )
|
||||
#define IsLinux() true
|
||||
#else
|
||||
#define IsLinux() false
|
||||
#endif
|
||||
|
||||
#if defined( OSX )
|
||||
#define IsOSX() true
|
||||
#else
|
||||
#define IsOSX() false
|
||||
#endif
|
||||
|
||||
#define IsPosix() true
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
@ -25,10 +25,20 @@
|
||||
#include "utlvector.h"
|
||||
#include "Color.h"
|
||||
|
||||
#define FOR_EACH_SUBKEY( kvRoot, kvSubKey ) \
|
||||
for ( KeyValues * kvSubKey = kvRoot->GetFirstSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextKey() )
|
||||
|
||||
#define FOR_EACH_TRUE_SUBKEY( kvRoot, kvSubKey ) \
|
||||
for ( KeyValues * kvSubKey = kvRoot->GetFirstTrueSubKey(); kvSubKey != NULL; kvSubKey = kvSubKey->GetNextTrueSubKey() )
|
||||
|
||||
#define FOR_EACH_VALUE( kvRoot, kvValue ) \
|
||||
for ( KeyValues * kvValue = kvRoot->GetFirstValue(); kvValue != NULL; kvValue = kvValue->GetNextValue() )
|
||||
|
||||
class IBaseFileSystem;
|
||||
class CUtlBuffer;
|
||||
class Color;
|
||||
typedef void * FileHandle_t;
|
||||
class CKeyValuesGrowableStringTable;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Simple recursive data access class
|
||||
@ -39,7 +49,7 @@ typedef void * FileHandle_t;
|
||||
// About KeyValues Text File Format:
|
||||
|
||||
// It has 3 control characters '{', '}' and '"'. Names and values may be quoted or
|
||||
// not. The quote '"' charater must not be used within name or values, only for
|
||||
// not. The quote '"' character must not be used within name or values, only for
|
||||
// quoting whole tokens. You may use escape sequences wile parsing and add within a
|
||||
// quoted token a \" to add quotes within your name or token. When using Escape
|
||||
// Sequence the parser must now that by setting KeyValues::UsesEscapeSequences( true ),
|
||||
@ -49,11 +59,25 @@ typedef void * FileHandle_t;
|
||||
// with a closing bracket '}'. Subkeys use the same definitions recursively.
|
||||
// Whitespaces are space, return, newline and tabulator. Allowed Escape sequences
|
||||
// are \n, \t, \\, \n and \". The number character '#' is used for macro purposes
|
||||
// (eg #include), don't use it as first charater in key names.
|
||||
// (eg #include), don't use it as first character in key names.
|
||||
//-----------------------------------------------------------------------------
|
||||
class KeyValues
|
||||
{
|
||||
public:
|
||||
// By default, the KeyValues class uses a string table for the key names that is
|
||||
// limited to 4MB. The game will exit in error if this space is exhausted. In
|
||||
// general this is preferable for game code for performance and memory fragmentation
|
||||
// reasons.
|
||||
//
|
||||
// If this is not acceptable, you can use this call to switch to a table that can grow
|
||||
// arbitrarily. This call must be made before any KeyValues objects are allocated or it
|
||||
// will result in undefined behavior. If you use the growable string table, you cannot
|
||||
// share KeyValues pointers directly with any other module. You can serialize them across
|
||||
// module boundaries. These limitations are acceptable in the Steam backend code
|
||||
// this option was written for, but may not be in other situations. Make sure to
|
||||
// understand the implications before using this.
|
||||
static void SetUseGrowableStringTable( bool bUseGrowableTable );
|
||||
|
||||
KeyValues( const char *setName );
|
||||
|
||||
//
|
||||
@ -68,8 +92,11 @@ public:
|
||||
{
|
||||
public:
|
||||
explicit inline AutoDelete( KeyValues *pKeyValues ) : m_pKeyValues( pKeyValues ) {}
|
||||
explicit inline AutoDelete( const char *pchKVName ) : m_pKeyValues( new KeyValues( pchKVName ) ) {}
|
||||
inline ~AutoDelete( void ) { if( m_pKeyValues ) m_pKeyValues->deleteThis(); }
|
||||
inline void Assign( KeyValues *pKeyValues ) { m_pKeyValues = pKeyValues; }
|
||||
KeyValues *operator->() { return m_pKeyValues; }
|
||||
operator KeyValues *() { return m_pKeyValues; }
|
||||
private:
|
||||
AutoDelete( AutoDelete const &x ); // forbid
|
||||
AutoDelete & operator= ( AutoDelete const &x ); // forbid
|
||||
@ -88,12 +115,13 @@ public:
|
||||
void SetName( const char *setName);
|
||||
|
||||
// gets the name as a unique int
|
||||
int GetNameSymbol() const;
|
||||
int GetNameSymbol() const { return m_iKeyName; }
|
||||
|
||||
// File access. Set UsesEscapeSequences true, if resource file/buffer uses Escape Sequences (eg \n, \t)
|
||||
void UsesEscapeSequences(bool state); // default false
|
||||
void UsesConditionals(bool state); // default true
|
||||
bool LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL );
|
||||
bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
|
||||
bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL, bool sortKeys = false, bool bAllowEmptyString = false );
|
||||
|
||||
// Read from a buffer... Note that the buffer must be null terminated
|
||||
bool LoadFromBuffer( char const *resourceName, const char *pBuffer, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL );
|
||||
@ -114,9 +142,10 @@ public:
|
||||
// NOTE: GetFirstSubKey/GetNextKey will iterate keys AND values. Use the functions
|
||||
// below if you want to iterate over just the keys or just the values.
|
||||
//
|
||||
KeyValues *GetFirstSubKey(); // returns the first subkey in the list
|
||||
KeyValues *GetNextKey(); // returns the next subkey
|
||||
KeyValues *GetFirstSubKey() { return m_pSub; } // returns the first subkey in the list
|
||||
KeyValues *GetNextKey() { return m_pPeer; } // returns the next subkey
|
||||
void SetNextKey( KeyValues * pDat);
|
||||
KeyValues *FindLastSubKey(); // returns the LAST subkey in the list. This requires a linked list iteration to find the key. Returns NULL if we don't have any children
|
||||
|
||||
//
|
||||
// These functions can be used to treat it like a true key/values tree instead of
|
||||
@ -145,6 +174,7 @@ public:
|
||||
const char *GetString( const char *keyName = NULL, const char *defaultValue = "" );
|
||||
const wchar_t *GetWString( const char *keyName = NULL, const wchar_t *defaultValue = L"" );
|
||||
void *GetPtr( const char *keyName = NULL, void *defaultValue = (void*)0 );
|
||||
bool GetBool( const char *keyName = NULL, bool defaultValue = false, bool* optGotDefault = NULL );
|
||||
Color GetColor( const char *keyName = NULL /* default value is all black */);
|
||||
bool IsEmpty(const char *keyName = NULL);
|
||||
|
||||
@ -165,6 +195,7 @@ public:
|
||||
void SetFloat( const char *keyName, float value );
|
||||
void SetPtr( const char *keyName, void *value );
|
||||
void SetColor( const char *keyName, Color value);
|
||||
void SetBool( const char *keyName, bool value ) { SetInt( keyName, value ? 1 : 0 ); }
|
||||
|
||||
// Memory allocation (optimized)
|
||||
void *operator new( size_t iAllocSize );
|
||||
@ -178,10 +209,10 @@ public:
|
||||
// in the one we're chained to.
|
||||
void ChainKeyValue( KeyValues* pChain );
|
||||
|
||||
void RecursiveSaveToFile( CUtlBuffer& buf, int indentLevel );
|
||||
void RecursiveSaveToFile( CUtlBuffer& buf, int indentLevel, bool sortKeys = false, bool bAllowEmptyString = false );
|
||||
|
||||
bool WriteAsBinary( CUtlBuffer &buffer );
|
||||
bool ReadAsBinary( CUtlBuffer &buffer );
|
||||
bool ReadAsBinary( CUtlBuffer &buffer, int nStackDepth = 0 );
|
||||
|
||||
// Allocate & create a new copy of the keys
|
||||
KeyValues *MakeCopy( void ) const;
|
||||
@ -213,11 +244,17 @@ public:
|
||||
void SetStringValue( char const *strValue );
|
||||
|
||||
// unpack a key values list into a structure
|
||||
void UnpackIntoStructure( struct KeyValuesUnpackStructure const *pUnpackTable, void *pDest );
|
||||
void UnpackIntoStructure( struct KeyValuesUnpackStructure const *pUnpackTable, void *pDest, size_t DestSizeInBytes );
|
||||
|
||||
// Process conditional keys for widescreen support.
|
||||
bool ProcessResolutionKeys( const char *pResString );
|
||||
|
||||
// Dump keyvalues recursively into a dump context
|
||||
bool Dump( class IKeyValuesDumpContext *pDump, int nIndentLevel = 0 );
|
||||
|
||||
// Merge in another KeyValues, keeping "our" settings
|
||||
void RecursiveMergeKeyValues( KeyValues *baseKV );
|
||||
|
||||
private:
|
||||
KeyValues( KeyValues& ); // prevent copy constructor being used
|
||||
|
||||
@ -225,7 +262,14 @@ private:
|
||||
~KeyValues();
|
||||
|
||||
KeyValues* CreateKey( const char *keyName );
|
||||
|
||||
|
||||
/// Create a child key, given that we know which child is currently the last child.
|
||||
/// This avoids the O(N^2) behaviour when adding children in sequence to KV,
|
||||
/// when CreateKey() wil have to re-locate the end of the list each time. This happens,
|
||||
/// for example, every time we load any KV file whatsoever.
|
||||
KeyValues* CreateKeyUsingKnownLastChild( const char *keyName, KeyValues *pLastChild );
|
||||
void AddSubkeyUsingKnownLastChild( KeyValues *pSubKey, KeyValues *pLastChild );
|
||||
|
||||
void RecursiveCopyKeyValues( KeyValues& src );
|
||||
void RemoveEverything();
|
||||
// void RecursiveSaveToFile( IBaseFileSystem *filesystem, CUtlBuffer &buffer, int indentLevel );
|
||||
@ -233,7 +277,8 @@ private:
|
||||
|
||||
// NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
|
||||
// If filesystem is null, it'll ignore f.
|
||||
void RecursiveSaveToFile( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel );
|
||||
void RecursiveSaveToFile( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel, bool sortKeys, bool bAllowEmptyString );
|
||||
void SaveKeyToFile( KeyValues *dat, IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel, bool sortKeys, bool bAllowEmptyString );
|
||||
void WriteConvertedString( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const char *pszString );
|
||||
|
||||
void RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &buf );
|
||||
@ -245,7 +290,6 @@ private:
|
||||
|
||||
// For handling #base "filename"
|
||||
void MergeBaseKeys( CUtlVector< KeyValues * >& baseKeys );
|
||||
void RecursiveMergeKeyValues( KeyValues *baseKV );
|
||||
|
||||
// NOTE: If both filesystem and pBuf are non-null, it'll save to both of them.
|
||||
// If filesystem is null, it'll ignore f.
|
||||
@ -275,13 +319,36 @@ private:
|
||||
|
||||
char m_iDataType;
|
||||
char m_bHasEscapeSequences; // true, if while parsing this KeyValue, Escape Sequences are used (default false)
|
||||
char unused[2];
|
||||
char m_bEvaluateConditionals; // true, if while parsing this KeyValue, conditionals blocks are evaluated (default true)
|
||||
char unused[1];
|
||||
|
||||
KeyValues *m_pPeer; // pointer to next key in list
|
||||
KeyValues *m_pSub; // pointer to Start of a new sub key list
|
||||
KeyValues *m_pChain;// Search here if it's not in our list
|
||||
|
||||
private:
|
||||
// Statics to implement the optional growable string table
|
||||
// Function pointers that will determine which mode we are in
|
||||
static int (*s_pfGetSymbolForString)( const char *name, bool bCreate );
|
||||
static const char *(*s_pfGetStringForSymbol)( int symbol );
|
||||
static CKeyValuesGrowableStringTable *s_pGrowableStringTable;
|
||||
|
||||
public:
|
||||
// Functions that invoke the default behavior
|
||||
static int GetSymbolForStringClassic( const char *name, bool bCreate = true );
|
||||
static const char *GetStringForSymbolClassic( int symbol );
|
||||
|
||||
// Functions that use the growable string table
|
||||
static int GetSymbolForStringGrowable( const char *name, bool bCreate = true );
|
||||
static const char *GetStringForSymbolGrowable( int symbol );
|
||||
|
||||
// Functions to get external access to whichever of the above functions we're going to call.
|
||||
static int CallGetSymbolForString( const char *name, bool bCreate = true ) { return s_pfGetSymbolForString( name, bCreate ); }
|
||||
static const char *CallGetStringForSymbol( int symbol ) { return s_pfGetStringForSymbol( symbol ); }
|
||||
};
|
||||
|
||||
typedef KeyValues::AutoDelete KeyValuesAD;
|
||||
|
||||
enum KeyValuesUnpackDestinationTypes_t
|
||||
{
|
||||
UNPACK_TYPE_FLOAT, // dest is a float
|
||||
@ -354,4 +421,57 @@ inline bool KeyValues::IsEmpty( int keySymbol )
|
||||
|
||||
bool EvaluateConditional( const char *str );
|
||||
|
||||
class CUtlSortVectorKeyValuesByName
|
||||
{
|
||||
public:
|
||||
bool Less( const KeyValues* lhs, const KeyValues* rhs, void * )
|
||||
{
|
||||
return Q_stricmp( lhs->GetName(), rhs->GetName() ) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// KeyValuesDumpContext and generic implementations
|
||||
//
|
||||
|
||||
class IKeyValuesDumpContext
|
||||
{
|
||||
public:
|
||||
virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel ) = 0;
|
||||
virtual bool KvWriteValue( KeyValues *pValue, int nIndentLevel ) = 0;
|
||||
virtual bool KvEndKey( KeyValues *pKey, int nIndentLevel ) = 0;
|
||||
};
|
||||
|
||||
class IKeyValuesDumpContextAsText : public IKeyValuesDumpContext
|
||||
{
|
||||
public:
|
||||
virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel );
|
||||
virtual bool KvWriteValue( KeyValues *pValue, int nIndentLevel );
|
||||
virtual bool KvEndKey( KeyValues *pKey, int nIndentLevel );
|
||||
|
||||
public:
|
||||
virtual bool KvWriteIndent( int nIndentLevel );
|
||||
virtual bool KvWriteText( char const *szText ) = 0;
|
||||
};
|
||||
|
||||
class CKeyValuesDumpContextAsDevMsg : public IKeyValuesDumpContextAsText
|
||||
{
|
||||
public:
|
||||
// Overrides developer level to dump in DevMsg, zero to dump as Msg
|
||||
CKeyValuesDumpContextAsDevMsg( int nDeveloperLevel = 1 ) : m_nDeveloperLevel( nDeveloperLevel ) {}
|
||||
|
||||
public:
|
||||
virtual bool KvBeginKey( KeyValues *pKey, int nIndentLevel );
|
||||
virtual bool KvWriteText( char const *szText );
|
||||
|
||||
protected:
|
||||
int m_nDeveloperLevel;
|
||||
};
|
||||
|
||||
inline bool KeyValuesDumpAsDevMsg( KeyValues *pKeyValues, int nIndentLevel = 0, int nDeveloperLevel = 1 )
|
||||
{
|
||||
CKeyValuesDumpContextAsDevMsg ctx( nDeveloperLevel );
|
||||
return pKeyValues->Dump( &ctx, nIndentLevel );
|
||||
}
|
||||
|
||||
#endif // KEYVALUES_H
|
||||
|
@ -110,6 +110,8 @@ int V_strcasecmp (const char *s1, const char *s2);
|
||||
int V_strncasecmp (const char *s1, const char *s2, int n);
|
||||
int V_strnicmp (const char *s1, const char *s2, int n);
|
||||
int V_atoi (const char *str);
|
||||
int64 V_atoi64(const char *str);
|
||||
uint64 V_atoui64(const char *str);
|
||||
float V_atof (const char *str);
|
||||
char* V_stristr( char* pStr, const char* pSearch );
|
||||
const char* V_stristr( const char* pStr, const char* pSearch );
|
||||
@ -409,6 +411,8 @@ bool V_GenerateUniqueName( char *name, int memsize, const char *prefix, const Na
|
||||
#define Q_strncasecmp V_strncasecmp
|
||||
#define Q_strnicmp V_strnicmp
|
||||
#define Q_atoi V_atoi
|
||||
#define Q_atoi64 V_atoi64
|
||||
#define Q_atoui64 V_atoui64
|
||||
#define Q_atof V_atof
|
||||
#define Q_stristr V_stristr
|
||||
#define Q_strnistr V_strnistr
|
||||
|
@ -176,6 +176,7 @@ public:
|
||||
short GetShort( );
|
||||
unsigned short GetUnsignedShort( );
|
||||
int GetInt( );
|
||||
int64 GetInt64( );
|
||||
int GetIntHex( );
|
||||
unsigned int GetUnsignedInt( );
|
||||
float GetFloat( );
|
||||
@ -249,6 +250,7 @@ public:
|
||||
void PutShort( short s );
|
||||
void PutUnsignedShort( unsigned short us );
|
||||
void PutInt( int i );
|
||||
void PutInt64( int64 i );
|
||||
void PutUnsignedInt( unsigned int u );
|
||||
void PutFloat( float f );
|
||||
void PutDouble( double d );
|
||||
@ -700,6 +702,13 @@ inline int CUtlBuffer::GetInt( )
|
||||
return i;
|
||||
}
|
||||
|
||||
inline int64 CUtlBuffer::GetInt64( )
|
||||
{
|
||||
int64 i;
|
||||
GetType( i, "%lld" );
|
||||
return i;
|
||||
}
|
||||
|
||||
inline int CUtlBuffer::GetIntHex( )
|
||||
{
|
||||
int i;
|
||||
@ -920,6 +929,11 @@ inline void CUtlBuffer::PutInt( int i )
|
||||
PutType( i, "%d" );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutInt64( int64 i )
|
||||
{
|
||||
PutType( i, "%llu" );
|
||||
}
|
||||
|
||||
inline void CUtlBuffer::PutUnsignedInt( unsigned int u )
|
||||
{
|
||||
PutType( u, "%u" );
|
||||
|
1024
tier1/KeyValues.cpp
1024
tier1/KeyValues.cpp
File diff suppressed because it is too large
Load Diff
@ -316,13 +316,13 @@ const char *StringAfterPrefixCaseSensitive( const char *str, const char *prefix
|
||||
}
|
||||
|
||||
|
||||
int V_atoi (const char *str)
|
||||
int64 V_atoi64( const char *str )
|
||||
{
|
||||
AssertValidStringPtr( str );
|
||||
|
||||
int val;
|
||||
int sign;
|
||||
int c;
|
||||
int64 val;
|
||||
int64 sign;
|
||||
int64 c;
|
||||
|
||||
Assert( str );
|
||||
if (*str == '-')
|
||||
@ -377,6 +377,63 @@ int V_atoi (const char *str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64 V_atoui64( const char *str )
|
||||
{
|
||||
AssertValidStringPtr( str );
|
||||
|
||||
uint64 val;
|
||||
uint64 c;
|
||||
|
||||
Assert( str );
|
||||
|
||||
val = 0;
|
||||
|
||||
//
|
||||
// check for hex
|
||||
//
|
||||
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
|
||||
{
|
||||
str += 2;
|
||||
while (1)
|
||||
{
|
||||
c = *str++;
|
||||
if (c >= '0' && c <= '9')
|
||||
val = (val<<4) + c - '0';
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
val = (val<<4) + c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
val = (val<<4) + c - 'A' + 10;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// check for character
|
||||
//
|
||||
if (str[0] == '\'')
|
||||
{
|
||||
return str[1];
|
||||
}
|
||||
|
||||
//
|
||||
// assume decimal
|
||||
//
|
||||
while (1)
|
||||
{
|
||||
c = *str++;
|
||||
if (c <'0' || c > '9')
|
||||
return val;
|
||||
val = val*10 + c - '0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int V_atoi( const char *str )
|
||||
{
|
||||
return (int)V_atoi64( str );
|
||||
}
|
||||
|
||||
float V_atof (const char *str)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user