From 20208f41c5ded988cf68b1c4acef13c206313171 Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Mon, 4 Aug 2025 20:22:40 +0300 Subject: [PATCH] Update CKeyValues3Table & CKV3MemberName --- public/tier1/keyvalues3.h | 27 +++++-- tier1/keyvalues3.cpp | 154 +++++++++++++++++++++++++++----------- 2 files changed, 132 insertions(+), 49 deletions(-) diff --git a/public/tier1/keyvalues3.h b/public/tier1/keyvalues3.h index aaed0e33..e8b507e7 100644 --- a/public/tier1/keyvalues3.h +++ b/public/tier1/keyvalues3.h @@ -347,7 +347,7 @@ struct KV3BinaryBlob_t class CKV3MemberName { public: - inline CKV3MemberName(const char* pszString): m_nHashCode(), m_pszString("") + inline CKV3MemberName(const char* pszString, UtlSymLargeId_t symid = UTL_INVAL_SYMBOL_LARGE ): m_nHashCode(), m_SymId( symid ), m_pszString("") { if (!pszString || !pszString[0]) return; @@ -356,14 +356,16 @@ public: m_pszString = pszString; } - inline CKV3MemberName(): m_nHashCode(), m_pszString("") {} - inline CKV3MemberName( CUtlStringToken nHashCode, const char* pszString = ""): m_nHashCode(nHashCode), m_pszString(pszString) {} + inline CKV3MemberName(): m_nHashCode(), m_SymId( UTL_INVAL_SYMBOL_LARGE ), m_pszString("") {} + inline CKV3MemberName( CUtlStringToken nHashCode, const char* pszString = "", UtlSymLargeId_t symid = UTL_INVAL_SYMBOL_LARGE ): m_nHashCode(nHashCode), m_SymId( symid ), m_pszString(pszString) {} inline unsigned int GetHashCode() const { return m_nHashCode.GetHashCode(); } inline const char* GetString() const { return m_pszString; } + inline UtlSymLargeId_t GetSymId() const { return m_SymId; } private: CUtlStringToken m_nHashCode; + UtlSymLargeId_t m_SymId; const char* m_pszString; }; @@ -777,12 +779,17 @@ class CKeyValues3Table public: enum { - MEMBER_FLAG_EXTERNAL_NAME = (1 << 0) + MEMBER_FLAG_EXTERNAL_NAME = (1 << 0), + MEMBER_FLAG_LARGE_SYMBOL = (1 << 1) }; typedef CUtlStringToken Hash_t; typedef KeyValues3* Member_t; - typedef const char* Name_t; + union Name_t + { + const char *m_String; + UtlSymLargeId_t m_SymId; + }; typedef uint8 Flags_t; static const size_t DATA_SIZE = KV3_TABLE_MAX_FIXED_MEMBERS; @@ -800,8 +807,9 @@ public: int GetMemberCount() const { return m_nCount; } Member_t GetMember( KV3MemberId_t id ); const Member_t GetMember( KV3MemberId_t id ) const { return const_cast(this)->GetMember( id ); } - const Name_t GetMemberName( KV3MemberId_t id ) const; + const const char *GetMemberName( const KeyValues3 *parent, KV3MemberId_t id ) const; const Hash_t GetMemberHash( KV3MemberId_t id ) const; + CKV3MemberName GetKV3MemberName( const KeyValues3 *parent, KV3MemberId_t id ) const; void PurgeFastSearch(); void EnableFastSearch(); @@ -824,6 +832,10 @@ public: static constexpr size_t TotalSizeWithoutStaticData() { return sizeof(CKeyValues3Table) - sizeof(m_StaticBuffer); } private: + void PurgeNameBuffer( KeyValues3 *parent, KV3MemberId_t id ); + + void StoreKeyName( KeyValues3 *parent, Name_t &out_string, Flags_t &out_flags, const char *input_string, UtlSymLargeId_t sym_id = UTL_INVAL_SYMBOL_LARGE, bool name_external = false ); + int GetAllocatedChunks() const { return m_nAllocatedChunks; } bool IsBaseStatic() { return !m_bIsDynamicallySized; } @@ -1114,7 +1126,8 @@ public: IParsingErrorListener* GetParsingErrorListener() const { return m_pParsingErrorListener; } void SetParsingErrorListener( IParsingErrorListener* listener ) { m_pParsingErrorListener = listener; } - const char* AllocString( const char* pString ); + const char* AllocString( const char* pString, UtlSymLargeId_t *symid = NULL ); + const char *LookupString( UtlSymLargeId_t symid ) const; void EnableMetaData( bool bEnable ); void CopyMetaData( KV3MetaData_t* pDest, const KV3MetaData_t* pSrc ); diff --git a/tier1/keyvalues3.cpp b/tier1/keyvalues3.cpp index 7fe4eb8a..b034dc0a 100644 --- a/tier1/keyvalues3.cpp +++ b/tier1/keyvalues3.cpp @@ -801,7 +801,7 @@ const char* KeyValues3::GetMemberName( KV3MemberId_t id ) const if ( GetType() != KV3_TYPE_TABLE || id < 0 || id >= m_Data.m_pTable->GetMemberCount() ) return nullptr; - return m_Data.m_pTable->GetMemberName( id ); + return m_Data.m_pTable->GetMemberName( this, id ); } CKV3MemberName KeyValues3::GetMemberNameEx( KV3MemberId_t id ) const @@ -809,7 +809,7 @@ CKV3MemberName KeyValues3::GetMemberNameEx( KV3MemberId_t id ) const if ( GetType() != KV3_TYPE_TABLE || id < 0 || id >= m_Data.m_pTable->GetMemberCount() ) return CKV3MemberName(); - return CKV3MemberName( m_Data.m_pTable->GetMemberHash( id ), m_Data.m_pTable->GetMemberName( id ) ); + return m_Data.m_pTable->GetKV3MemberName( this, id ); } CUtlStringToken KeyValues3::GetMemberHash( KV3MemberId_t id ) const @@ -1548,11 +1548,19 @@ KeyValues3* CKeyValues3Table::GetMember( KV3MemberId_t id ) return MembersBase()[id]; } -const CKeyValues3Table::Name_t CKeyValues3Table::GetMemberName( KV3MemberId_t id ) const +const const char* CKeyValues3Table::GetMemberName( const KeyValues3 *parent, KV3MemberId_t id ) const { Assert( 0 <= id && id < m_nCount ); - return NamesBase()[id]; + Flags_t flags = FlagsBase()[id]; + + if((flags & MEMBER_FLAG_LARGE_SYMBOL) != 0) + { + UtlSymLargeId_t symid = NamesBase()[id].m_SymId; + return parent->GetContext()->LookupString( symid ); + } + + return NamesBase()[id].m_String; } const CKeyValues3Table::Hash_t CKeyValues3Table::GetMemberHash( KV3MemberId_t id ) const @@ -1562,6 +1570,27 @@ const CKeyValues3Table::Hash_t CKeyValues3Table::GetMemberHash( KV3MemberId_t id return HashesBase()[id]; } +CKV3MemberName CKeyValues3Table::GetKV3MemberName( const KeyValues3 *parent, KV3MemberId_t id ) const +{ + Assert( 0 <= id && id < m_nCount ); + + Flags_t flags = FlagsBase()[id]; + + UtlSymLargeId_t symid = UTL_INVAL_SYMBOL_LARGE; + const char *key_name = nullptr; + if((flags & MEMBER_FLAG_LARGE_SYMBOL) != 0) + { + symid = NamesBase()[id].m_SymId; + key_name = parent->GetContext()->LookupString( symid ); + } + else + { + key_name = NamesBase()[id].m_String; + } + + return CKV3MemberName( GetMemberHash( id ), key_name, symid ); +} + void CKeyValues3Table::EnableFastSearch() { if ( m_pFastSearch ) @@ -1693,24 +1722,8 @@ KV3MemberId_t CKeyValues3Table::CreateMember( KeyValues3 *parent, const CKV3Memb members_base[curr] = parent->AllocMember(); hashes_base[curr] = name.GetHashCode(); - Flags_t flags = 0; - - if(name_external) - { - names_base[curr] = name.GetString(); - flags |= MEMBER_FLAG_EXTERNAL_NAME; - } - else - { - auto context = parent->GetContext(); - - if(context) - names_base[curr] = context->AllocString( name.GetString() ); - else - names_base[curr] = strdup( name.GetString() ); - } - - flags_base[curr] = flags; + + StoreKeyName( parent, names_base[curr], flags_base[curr], name.GetString(), name.GetSymId(), name_external ); if ( m_pFastSearch && !m_pFastSearch->m_ignore ) m_pFastSearch->m_member_ids.Insert( name.GetHashCode(), curr ); @@ -1720,6 +1733,52 @@ KV3MemberId_t CKeyValues3Table::CreateMember( KeyValues3 *parent, const CKV3Memb return curr; } +void CKeyValues3Table::StoreKeyName( KeyValues3 *parent, Name_t &out_buffer, Flags_t &out_flags, const char *input_string, UtlSymLargeId_t sym_id, bool name_external ) +{ + Flags_t flags = 0; + + if(name_external) + { + out_buffer.m_String = input_string; + flags |= MEMBER_FLAG_EXTERNAL_NAME; + } + else + { + auto context = parent->GetContext(); + + if(context) + { + const char *existing_str = context->LookupString( sym_id ); + + if(existing_str && (existing_str == input_string || strcmp(existing_str, input_string) == 0)) + { + out_buffer.m_SymId = sym_id; + flags |= MEMBER_FLAG_LARGE_SYMBOL; + } + else + { + const char *alloced_string = context->AllocString( input_string, &sym_id ); + + if(sym_id >= 0) + { + out_buffer.m_SymId = sym_id; + flags |= MEMBER_FLAG_LARGE_SYMBOL; + } + else + { + out_buffer.m_String = alloced_string; + } + } + } + else + { + out_buffer.m_String = strdup( input_string ); + } + } + + out_flags = flags; +} + void CKeyValues3Table::CopyFrom( KeyValues3 *parent, const CKeyValues3Table* src ) { int new_size = src->GetMemberCount(); @@ -1743,12 +1802,10 @@ void CKeyValues3Table::CopyFrom( KeyValues3 *parent, const CKeyValues3Table* src for(int i = 0; i < new_size; i++) { - flags_base[i] = src_flags_base[i] & ~MEMBER_FLAG_EXTERNAL_NAME; - - if(context) - names_base[i] = context->AllocString( src_names_base[i] ); + if(context && (src_flags_base[i] & MEMBER_FLAG_LARGE_SYMBOL) != 0) + StoreKeyName( parent, names_base[i], flags_base[i], context->LookupString( src_names_base[i].m_SymId ), src_names_base[i].m_SymId ); else - names_base[i] = strdup( src_names_base[i] ); + StoreKeyName( parent, names_base[i], flags_base[i], src_names_base[i].m_String ); members_base[i] = parent->AllocMember(); members_base[i]->CopyFrom( src_members_base[i] ); @@ -1758,6 +1815,19 @@ void CKeyValues3Table::CopyFrom( KeyValues3 *parent, const CKeyValues3Table* src EnableFastSearch(); } +void CKeyValues3Table::PurgeNameBuffer( KeyValues3 *parent, KV3MemberId_t id ) +{ + auto name = NamesBase()[id]; + auto flags = FlagsBase()[id]; + + if((flags & MEMBER_FLAG_EXTERNAL_NAME) == 0 && + (flags & MEMBER_FLAG_LARGE_SYMBOL) == 0 && + !parent->GetContext() && name.m_String) + { + free( (void *)name.m_String ); + } +} + void CKeyValues3Table::RemoveMember( KeyValues3 *parent, KV3MemberId_t id ) { m_nCount--; @@ -1769,10 +1839,7 @@ void CKeyValues3Table::RemoveMember( KeyValues3 *parent, KV3MemberId_t id ) parent->FreeMember( members_base[id] ); - if((flags_base[id] & MEMBER_FLAG_EXTERNAL_NAME) == 0 && !parent->GetContext() && names_base[id]) - { - free( (void *)names_base[id] ); - } + PurgeNameBuffer( parent, id ); if ( id < m_nCount ) { @@ -1801,11 +1868,7 @@ void CKeyValues3Table::RemoveAll( KeyValues3 *parent, int new_size ) for(int i = 0; i < m_nCount; i++) { parent->FreeMember( members_base[i] ); - - if((flags_base[i] & MEMBER_FLAG_EXTERNAL_NAME) == 0 && !parent->GetContext() && names_base[i]) - { - free( (void *)names_base[i] ); - } + PurgeNameBuffer( parent, i ); } m_nCount = 0; @@ -1846,10 +1909,7 @@ void CKeyValues3Table::PurgeContent( KeyValues3 *parent, bool bClearingContext ) parent->FreeMember( members_base[i] ); } - if((flags_base[i] & MEMBER_FLAG_EXTERNAL_NAME) == 0 && parent && !parent->GetContext() && names_base[i]) - { - free( (void *)names_base[i] ); - } + PurgeNameBuffer( parent, i ); } m_nCount = 0; @@ -1967,9 +2027,19 @@ KeyValues3* CKeyValues3Context::Root() return &m_KV3BaseCluster.Head()->m_Value; } -const char* CKeyValues3Context::AllocString( const char* pString ) +const char* CKeyValues3Context::AllocString( const char* pString, UtlSymLargeId_t *out_symid ) { - return m_Symbols.AddString( pString ).String(); + UtlSymLargeId_t sym = m_Symbols.AddStringRaw( pString ); + + if(out_symid) + *out_symid = sym; + + return m_Symbols.String( sym ); +} + +const char* CKeyValues3Context::LookupString( UtlSymLargeId_t symid ) const +{ + return m_Symbols.String( symid ); } void CKeyValues3Context::EnableMetaData( bool bEnable )