diff options
Diffstat (limited to 'src/md/heaps')
-rw-r--r-- | src/md/heaps/.gitmirror | 1 | ||||
-rw-r--r-- | src/md/heaps/blobheap.h | 324 | ||||
-rw-r--r-- | src/md/heaps/export.h | 18 | ||||
-rw-r--r-- | src/md/heaps/external.h | 22 | ||||
-rw-r--r-- | src/md/heaps/guidheap.h | 259 | ||||
-rw-r--r-- | src/md/heaps/stringheap.h | 307 |
6 files changed, 931 insertions, 0 deletions
diff --git a/src/md/heaps/.gitmirror b/src/md/heaps/.gitmirror new file mode 100644 index 0000000000..f507630f94 --- /dev/null +++ b/src/md/heaps/.gitmirror @@ -0,0 +1 @@ +Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror.
\ No newline at end of file diff --git a/src/md/heaps/blobheap.h b/src/md/heaps/blobheap.h new file mode 100644 index 0000000000..8765537bd8 --- /dev/null +++ b/src/md/heaps/blobheap.h @@ -0,0 +1,324 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// File: BlobHeap.h +// + +// +// Classes code:MetaData::BlobHeapRO and code:MetaData::BlobHeapRW represent #Blob heap. +// The #Blob heap stores size-prefixed data chunks (as defined in CLI ECMA specification). Elements are +// indexed by code:#BlobHeapIndex. +// +//#BlobHeapIndex +// Blob heap indexes are 0-based. They are stored the same way in the table columns (i.e. there is no +// 0-based vs. 1-based index difference as in table record indexes code:TableRecordStorage). +// +// ====================================================================================== + +#pragma once + +#include "external.h" + +namespace MetaData +{ + +// -------------------------------------------------------------------------------------- +// +// This class represents read-only #Blob heap with all utility methods. +// +class BlobHeapRO +{ + friend class BlobHeapRW; + +private: + // + // Private data + // + + // The storage of blobs. + StgBlobPoolReadOnly m_BlobPool; + +public: + // + // Initialization + // + + __checkReturn + HRESULT Initialize( + DataBlob sourceData, + BOOL fCopyData) + { + _ASSERTE(!fCopyData); + return m_BlobPool.InitOnMemReadOnly((void *)sourceData.GetDataPointer(), sourceData.GetSize()); + } + +#ifdef FEATURE_PREJIT + // Can be called multiple times. + inline void InitializeHotData( + HotHeap hotHeap) + { + m_BlobPool.InitHotData(hotHeap); + } +#endif //FEATURE_PREJIT + + inline void Delete() + { + return m_BlobPool.Uninit(); + } + +public: + // + // Getters + // + + __checkReturn + inline HRESULT GetBlob( + UINT32 nIndex, + __out DataBlob *pData) + { + return m_BlobPool.GetBlob(nIndex, pData); + } + + __checkReturn + inline HRESULT GetAllData( + __inout DataBlob *pData) + { + return m_BlobPool.GetDataReadOnly(0, pData); + } + + // Gets raw size (in bytes) of the represented blob data. + inline UINT32 GetUnalignedSize() const + { + return m_BlobPool.GetPoolSize(); + } + + // Returns TRUE if the blob index (nIndex, see code:#BlobHeapIndex) is valid (i.e. in the blob + // heap). + inline BOOL IsValidIndex(UINT32 nIndex) const + { + return const_cast<StgBlobPoolReadOnly &>(m_BlobPool).IsValidCookie(nIndex); + } + +}; // class BlobHeapRO + +// -------------------------------------------------------------------------------------- +// +// This class represents read-write #Blob heap with all utility methods. +// +class BlobHeapRW +{ +private: + // + // Private data + // + + // The storage of blobs. + StgBlobPool m_BlobPool; + +public: + // + // Initialization + // + + __checkReturn + HRESULT InitializeEmpty( + UINT32 cbAllocationSize + COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite)) + { + return m_BlobPool.InitNew(cbAllocationSize, 0, TRUE); + } + __checkReturn + HRESULT InitializeEmpty_WithItemsCount( + UINT32 cbAllocationSize, + UINT32 cItemsCount + COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite)) + { + return m_BlobPool.InitNew(cbAllocationSize, cItemsCount, TRUE); + } + __checkReturn + HRESULT InitializeEmpty_WithoutDefaultEmptyBlob( + UINT32 cbAllocationSize + COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite)) + { + return m_BlobPool.InitNew(cbAllocationSize, 0, FALSE); + } + + __checkReturn + HRESULT Initialize( + DataBlob sourceData, + BOOL fCopyData) + { + return m_BlobPool.InitOnMem((void *)sourceData.GetDataPointer(), sourceData.GetSize(), !fCopyData); + } + __checkReturn + HRESULT InitializeFromBlobHeap( + const BlobHeapRO *pSourceBlobHeap, + BOOL fCopyData) + { + return m_BlobPool.InitOnMem( + (void *)pSourceBlobHeap->m_BlobPool.GetSegData(), + pSourceBlobHeap->m_BlobPool.GetDataSize(), + !fCopyData); + } + __checkReturn + HRESULT InitializeFromBlobHeap( + const BlobHeapRW *pSourceBlobHeap, + BOOL fCopyData) + { + return m_BlobPool.InitOnMem( + (void *)pSourceBlobHeap->m_BlobPool.GetSegData(), + pSourceBlobHeap->m_BlobPool.GetDataSize(), + !fCopyData); + } + + // Destroys the blob heap and all its allocated data. Can run on uninitialized blob heap. + inline void Delete() + { + return m_BlobPool.Uninit(); + } + +public: + // + // Getters + // + + __checkReturn + inline HRESULT GetBlob( + UINT32 nIndex, + __out DataBlob *pData) + { + return m_BlobPool.GetBlob(nIndex, pData); + } + + // Gets the blob with its size-prefix at index (nIndex, see code:#BlobHeapIndex), or returns error. + // + // Returns S_OK and the data (*pData) at index (nIndex). The end of the data marks the end of the blob. + // Returns error code otherwise (and clears *pData). + // + // User of this API shouldn't access memory behind the data buffer (*pData). + __checkReturn + inline HRESULT GetBlobWithSizePrefix( + UINT32 nIndex, + __out DataBlob *pData) + { + return m_BlobPool.GetBlobWithSizePrefix(nIndex, pData); + } + + // Gets raw size (in bytes) of the represented blob data. Doesn't align the size as code:GetAlignedSize. + inline UINT32 GetUnalignedSize() const + { + return m_BlobPool.GetRawSize(); + } + // Gets size (in bytes) aligned up to 4-bytes of the represented blob data. + // Fills *pcbSize with 0 on error. + __checkReturn + inline HRESULT GetAlignedSize( + __out UINT32 *pcbSize) const + { + return m_BlobPool.GetSaveSize(pcbSize); + } + // Returns TRUE if the blob heap is empty (even if it contains only default empty blob). + inline BOOL IsEmpty() const + { + return const_cast<StgBlobPool &>(m_BlobPool).IsEmpty(); + } + + // Returns TRUE if the blob index (nIndex, see code:#BlobHeapIndex) is valid (i.e. in the blob + // heap). + inline BOOL IsValidIndex(UINT32 nIndex) const + { + return const_cast<StgBlobPool &>(m_BlobPool).IsValidCookie(nIndex); + } + + __checkReturn + HRESULT SaveToStream_Aligned( + UINT32 nStartIndex, + __in IStream *pStream) const + { + if (nStartIndex == 0) + { + return const_cast<StgBlobPool &>(m_BlobPool).PersistToStream(pStream); + } + + if (nStartIndex == m_BlobPool.GetRawSize()) + { + _ASSERTE(!m_BlobPool.HaveEdits()); + return S_OK; + } + _ASSERTE(m_BlobPool.HaveEdits()); + _ASSERTE(nStartIndex == m_BlobPool.GetOffsetOfEdit()); + return const_cast<StgBlobPool &>(m_BlobPool).PersistPartialToStream(pStream, nStartIndex); + } + +public: + // + // Heap modifications + // + + __checkReturn + inline HRESULT AddBlob( + DataBlob data, + __out UINT32 *pnIndex) + { + return m_BlobPool.AddBlob(&data, pnIndex); + } + + __checkReturn + HRESULT AddBlobHeap( + const BlobHeapRW *pSourceBlobHeap, + UINT32 nStartSourceIndex) + { + return m_BlobPool.CopyPool( + nStartSourceIndex, + &pSourceBlobHeap->m_BlobPool); + } // BlobHeapRW::AddBlobHeap + + __checkReturn + inline HRESULT MakeWritable() + { + return m_BlobPool.ConvertToRW(); + } + +public: + // + // Tracking of heap modifications for EnC + // + + //#EnCSessionTracking + // EnC session starts automatically with initialization (code:Initialize or code:InitializeEmpty) or by + // user's explicit call to code:StartNewEnCSession. The heap stores its actual data size, so we can find + // out if some data were added later. + + // Gets heap size (in bytes) from the beginning of the last EnC session (code:#EnCSessionTracking). + inline UINT32 GetEnCSessionStartHeapSize() const + { + if (m_BlobPool.HaveEdits()) + { + return m_BlobPool.GetOffsetOfEdit(); + } + + return m_BlobPool.GetRawSize(); + } + // Starts new EnC session (code:#EnCSessionTracking). + inline void StartNewEnCSession() + { + m_BlobPool.ResetOffsetOfEdit(); + } + // Gets size (in bytes) aligned to 4-bytes of adds made from the beginning of the last EnC session. + __checkReturn + inline HRESULT GetEnCSessionAddedHeapSize_Aligned( + __out UINT32 *pcbSize) const + { + if (m_BlobPool.HaveEdits()) + { + return m_BlobPool.GetEditSaveSize(pcbSize); + } + + *pcbSize = 0; + return S_OK; + } + +}; // class BlobHeapRW + +}; // namespace MetaData diff --git a/src/md/heaps/export.h b/src/md/heaps/export.h new file mode 100644 index 0000000000..b14023706d --- /dev/null +++ b/src/md/heaps/export.h @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// File: export.h +// + +// +// Popular types defined in MetaData\Heaps directory. +// It's supposed to be included from other (MetaData) subcomponents, not from this directory. +// +// ====================================================================================== + +#pragma once + +#include "stringheap.h" +#include "blobheap.h" +#include "guidheap.h" diff --git a/src/md/heaps/external.h b/src/md/heaps/external.h new file mode 100644 index 0000000000..9b5362c761 --- /dev/null +++ b/src/md/heaps/external.h @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// File: external.h +// + +// +// External types used in MetaData\Heaps subcomponent classes. +// This file is used for precompiled headers, so it has to be included at the beginning of every .cpp in +// this directory. +// +// ====================================================================================== + +#pragma once + +#include "../external.h" +#include "../export.h" + +#include <stgpool.h> +#include <metamodelpub.h> +#include <utilcode.h> diff --git a/src/md/heaps/guidheap.h b/src/md/heaps/guidheap.h new file mode 100644 index 0000000000..57f0147871 --- /dev/null +++ b/src/md/heaps/guidheap.h @@ -0,0 +1,259 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// File: GuidHeap.h +// + +// +// Classes code:MetaData::GuidHeapRO and code:MetaData::GuidHeapRW represent #GUID heap. +// The #GUID heap stores size-prefixed data chunks (as defined in CLI ECMA specification). Elements are +// indexed by code:#GuidHeapIndex. +// +//#GuidHeapIndex +// Guid heap indexes are 1-based and they are really indexes, not offsets (as in string heap). +// The indexes correspond to: +// * 0 ... invalid index, +// * 1 ... data offset 0, +// * 2 ... data offset sizeof(GUID), +// * n ... data offset (n-1)*sizeof(GUID). +// Note that this class provides only translation from 1-based index to 0-based index. The translation of +// 0-based index to data offset is done in code:GuidHeapStorage::GetGuid. +// +// ====================================================================================== + +#pragma once + +#include "external.h" + +namespace MetaData +{ + +// -------------------------------------------------------------------------------------- +// +// This class represents read-only #GUID heap with all utility methods. +// +class GuidHeapRO +{ + friend class GuidHeapRW; + +private: + // + // Private data + // + + // The storage of guids. + StgPoolReadOnly m_GuidPool; + +public: + // + // Initialization + // + + __checkReturn + inline HRESULT Initialize( + DataBlob sourceData, + BOOL fCopyData) + { + _ASSERTE(!fCopyData); + return m_GuidPool.InitOnMemReadOnly((void *)sourceData.GetDataPointer(), sourceData.GetSize()); + } + +#ifdef FEATURE_PREJIT + // Can be called multiple times. + inline void InitializeHotData( + HotHeap hotHeap) + { + m_GuidPool.InitHotData(hotHeap); + } +#endif //FEATURE_PREJIT + + // Destroys the guid heap and all its allocated data. Can run on uninitialized guid heap. + inline void Delete() + { + return m_GuidPool.Uninit(); + } + +public: + // + // Getters + // + + // Gets pointer to guid (*ppGuid) at index (nIndex, see code:#GuidHeapIndex). + // Returns error code for invalid index (0, or too large index) and sets *ppGuid to NULL. + __checkReturn + inline HRESULT GetGuid( + UINT32 nIndex, + __deref_out GUID UNALIGNED **ppGuid) + { + return m_GuidPool.GetGuid(nIndex, ppGuid); + } + __checkReturn + inline HRESULT GetGuid( + UINT32 nIndex, + __deref_out const GUID UNALIGNED **ppGuid) const + { + return const_cast<StgPoolReadOnly &>(m_GuidPool).GetGuid(nIndex, const_cast<GUID UNALIGNED **>(ppGuid)); + } + + inline UINT32 GetSize() const + { + return const_cast<StgPoolReadOnly &>(m_GuidPool).GetPoolSize(); + } + +}; // class GuidHeapRO + +// -------------------------------------------------------------------------------------- +// +// This class represents read-write #GUID heap with all utility methods. +// +class GuidHeapRW +{ +private: + // + // Private data + // + + // The storage of guids. + StgGuidPool m_GuidPool; + +public: + // + // Initialization + // + + __checkReturn + inline HRESULT InitializeEmpty( + UINT32 cbAllocationSize + COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite)) + { + return m_GuidPool.InitNew(cbAllocationSize, 0); + } + __checkReturn + inline HRESULT InitializeEmpty_WithItemsCount( + UINT32 cbAllocationSize, + UINT32 cItemsCount + COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite)) + { + return m_GuidPool.InitNew(cbAllocationSize, cItemsCount); + } + __checkReturn + inline HRESULT Initialize( + DataBlob sourceData, + BOOL fCopyData) + { + return m_GuidPool.InitOnMem((void *)sourceData.GetDataPointer(), sourceData.GetSize(), !fCopyData); + } + + __checkReturn + inline HRESULT InitializeFromGuidHeap( + const GuidHeapRO *pSourceGuidHeap, + BOOL fCopyData) + { + return m_GuidPool.InitOnMem( + (void *)pSourceGuidHeap->m_GuidPool.GetSegData(), + pSourceGuidHeap->m_GuidPool.GetDataSize(), + !fCopyData); + } + __checkReturn + inline HRESULT InitializeFromGuidHeap( + const GuidHeapRW *pSourceGuidHeap, + BOOL fCopyData) + { + return m_GuidPool.InitOnMem( + (void *)pSourceGuidHeap->m_GuidPool.GetSegData(), + pSourceGuidHeap->m_GuidPool.GetDataSize(), + !fCopyData); + } + + // Destroys the guid heap and all its allocated data. Can run on uninitialized guid heap. + inline void Delete() + { + return m_GuidPool.Uninit(); + } + +public: + // + // Getters + // + + __checkReturn + inline HRESULT GetGuid( + UINT32 nIndex, + __deref_out GUID UNALIGNED **ppGuid) + { + return m_GuidPool.GetGuid(nIndex, ppGuid); + } + __checkReturn + inline HRESULT GetGuid( + UINT32 nIndex, + __deref_out const GUID UNALIGNED **ppGuid) const + { + return const_cast<StgGuidPool &>(m_GuidPool).GetGuid(nIndex, const_cast<GUID UNALIGNED **>(ppGuid)); + } + + // Gets size (in bytes) of the represented guid data. Note: the size is everytime aligned. + inline UINT32 GetSize() const + { + _ASSERTE(m_GuidPool.GetRawSize() % sizeof(GUID) == 0); + return m_GuidPool.GetRawSize(); + } + + // Returns TRUE if the guid heap is empty. + inline BOOL IsEmpty() const + { + return const_cast<StgGuidPool &>(m_GuidPool).IsEmpty(); + } + + // Returns TRUE if the guid index (nIndex, see code:#GuidHeapIndex) is valid (i.e. is in the guid + // heap). + // Note: index 0 is considered invalid. + inline BOOL IsValidIndex(UINT32 nIndex) const + { + return const_cast<StgGuidPool &>(m_GuidPool).IsValidCookie(nIndex); + } + + __checkReturn + inline HRESULT SaveToStream( + __in IStream *pStream) const + { + return const_cast<StgGuidPool &>(m_GuidPool).PersistToStream(pStream); + } + +public: + // + // Heap modifications + // + + // Adds guid (*pGuid) to the end of the heap. + // Returns S_OK and index (*pnIndex, see code:#GuidHeapIndex) of added GUID. + // Returns error code otherwise (and fills *pnIndex with 0 - an invalid GUID index). + __checkReturn + inline HRESULT AddGuid( + __in const GUID *pGuid, + __out UINT32 *pnIndex) + { + return m_GuidPool.AddGuid(pGuid, pnIndex); + } + + // Adds data from *pSourceGuidHeap starting at index (nStartSourceIndex) to the guid heap. + // Returns S_OK (even if the source is empty) or error code. + __checkReturn + HRESULT AddGuidHeap( + const GuidHeapRW *pSourceGuidHeap, + UINT32 nStartSourceIndex) + { + return m_GuidPool.CopyPool( + nStartSourceIndex, + &pSourceGuidHeap->m_GuidPool); + } // GuidHeapRW::AddGuidHeap + + __checkReturn + inline HRESULT MakeWritable() + { + return m_GuidPool.ConvertToRW(); + } + +}; // class GuidHeapRW + +}; // namespace MetaData diff --git a/src/md/heaps/stringheap.h b/src/md/heaps/stringheap.h new file mode 100644 index 0000000000..b5353a12fd --- /dev/null +++ b/src/md/heaps/stringheap.h @@ -0,0 +1,307 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// File: StringHeap.h +// + +// +// Classes code:MetaData::StringHeapRO and code:MetaData::StringHeapRW represent #String heap. +// The #String heap stores null-terminated UTF-8 strings (as defined in CLI ECMA specification). Elements +// are indexed by code:#StringHeapIndex. +// +//#StringHeapIndex +// String heap indexes are 0-based. They are stored the same way in the table columns (i.e. there is no +// 0-based vs. 1-based index difference as in table record indexes code:TableRecordStorage). +// +// ====================================================================================== + +#pragma once + +#include "external.h" + +namespace MetaData +{ + +// -------------------------------------------------------------------------------------- +// +// This class represents read-only #String heap with all utility methods. +// +class StringHeapRO +{ + friend class StringHeapRW; + +private: + // + // Private data + // + + // The storage of strings. + StgPoolReadOnly m_StringPool; + +public: + // + // Initialization + // + + __checkReturn + inline HRESULT Initialize( + DataBlob sourceData, + BOOL fCopyData) + { + _ASSERTE(!fCopyData); + return m_StringPool.InitOnMemReadOnly((void *)sourceData.GetDataPointer(), sourceData.GetSize()); + } + +#ifdef FEATURE_PREJIT + // Can be called multiple times. + inline void InitializeHotData( + HotHeap hotHeap) + { + m_StringPool.InitHotData(hotHeap); + } +#endif //FEATURE_PREJIT + + inline void Delete() + { + return m_StringPool.Uninit(); + } + +public: + // + // Getters + // + + __checkReturn + inline HRESULT GetString( + UINT32 nIndex, + __deref_out_z LPCSTR *pszString) const + { + return const_cast<StgPoolReadOnly &>(m_StringPool).GetString( + nIndex, + pszString); + } + + // Gets raw size (in bytes) of the represented strings. + inline UINT32 GetUnalignedSize() const + { + return m_StringPool.GetPoolSize(); + } + +}; // class StringHeapRO + +// -------------------------------------------------------------------------------------- +// +// This class represents read-write #String heap with all utility methods. +// +class StringHeapRW +{ +private: + // + // Private data + // + + // The storage of strings. + StgStringPool m_StringPool; + +public: + // + // Initialization + // + + __checkReturn + inline HRESULT InitializeEmpty( + UINT32 cbAllocationSize + COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite)) + { + return m_StringPool.InitNew(cbAllocationSize, 0); + } + __checkReturn + inline HRESULT InitializeEmpty_WithItemsCount( + UINT32 cbAllocationSize, + UINT32 cItemsCount + COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite)) + { + return m_StringPool.InitNew(cbAllocationSize, cItemsCount); + } + __checkReturn + inline HRESULT Initialize( + DataBlob sourceData, + BOOL fCopyData) + { + return m_StringPool.InitOnMem((void *)sourceData.GetDataPointer(), sourceData.GetSize(), !fCopyData); + } + __checkReturn + inline HRESULT InitializeFromStringHeap( + const StringHeapRO *pSourceStringHeap, + BOOL fCopyData) + { + return m_StringPool.InitOnMem( + (void *)pSourceStringHeap->m_StringPool.GetSegData(), + pSourceStringHeap->m_StringPool.GetDataSize(), + !fCopyData); + } + __checkReturn + inline HRESULT InitializeFromStringHeap( + const StringHeapRW *pSourceStringHeap, + BOOL fCopyData) + { + return m_StringPool.InitOnMem( + (void *)pSourceStringHeap->m_StringPool.GetSegData(), + pSourceStringHeap->m_StringPool.GetDataSize(), + !fCopyData); + } + + // Destroys the string heap and all its allocated data. Can run on uninitialized string heap. + inline void Delete() + { + return m_StringPool.Uninit(); + } + +public: + // + // Getters + // + + __checkReturn + inline HRESULT GetString( + UINT32 nIndex, + __deref_out_z LPCSTR *pszString) const + { + return const_cast<StgStringPool &>(m_StringPool).GetString( + nIndex, + pszString); + } + + // Gets raw size (in bytes) of the represented strings. Doesn't align the size as code:GetAlignedSize. + inline UINT32 GetUnalignedSize() const + { + return m_StringPool.GetRawSize(); + } + // Gets size (in bytes) aligned up to 4-bytes of the represented strings. + // Fills *pcbSize with 0 on error. + __checkReturn + inline HRESULT GetAlignedSize( + __out UINT32 *pcbSize) const + { + return m_StringPool.GetSaveSize(pcbSize); + } + // Returns TRUE if the string heap is empty (even if it contains only default empty string). + inline BOOL IsEmpty() const + { + return const_cast<StgStringPool &>(m_StringPool).IsEmpty(); + } + + // Returns TRUE if the string index (nIndex, see code:#StringHeapIndex) is valid (i.e. in the string + // heap). + inline BOOL IsValidIndex(UINT32 nIndex) const + { + return const_cast<StgStringPool &>(m_StringPool).IsValidCookie(nIndex); + } + + __checkReturn + inline HRESULT SaveToStream_Aligned( + UINT32 nStartIndex, + __in IStream *pStream) const + { + if (nStartIndex == 0) + { + return const_cast<StgStringPool &>(m_StringPool).PersistToStream(pStream); + } + + if (nStartIndex == m_StringPool.GetRawSize()) + { + _ASSERTE(!m_StringPool.HaveEdits()); + return S_OK; + } + _ASSERTE(m_StringPool.HaveEdits()); + _ASSERTE(nStartIndex == m_StringPool.GetOffsetOfEdit()); + return const_cast<StgStringPool &>(m_StringPool).PersistPartialToStream(pStream, nStartIndex); + } + +public: + // + // Heap modifications + // + + // Adds null-terminated UTF-8 string (szString) to the end of the heap (incl. its null-terminator). + // Returns S_OK and index of added string (*pnIndex). + // Returns error code otherwise (and fills *pnIndex with 0). + __checkReturn + inline HRESULT AddString( + __in_z LPCSTR szString, + __out UINT32 *pnIndex) + { + return m_StringPool.AddString(szString, pnIndex); + } + // Adds null-terminated UTF-16 string (wszString) to the end of the heap (incl. its null-terminator). + // Returns S_OK and index of added string (*pnIndex). + // Returns error code otherwise (and fills *pnIndex with 0). + __checkReturn + inline HRESULT AddStringW( + __in_z LPCWSTR wszString, + __out UINT32 *pnIndex) + { + return m_StringPool.AddStringW(wszString, pnIndex); + } + + // Adds data from *pSourceStringHeap starting at index (nStartSourceIndex) to the string heap. + // Returns S_OK (even if the source is empty) or error code. + __checkReturn + inline HRESULT AddStringHeap( + const StringHeapRW *pSourceStringHeap, + UINT32 nStartSourceIndex) + { + return m_StringPool.CopyPool( + nStartSourceIndex, + &pSourceStringHeap->m_StringPool); + } // StringHeapRW::AddStringHeap + + __checkReturn + inline HRESULT MakeWritable() + { + return m_StringPool.ConvertToRW(); + } + +public: + // + // Tracking of heap modifications for EnC + // + + //#EnCSessionTracking + // EnC session starts automatically with initialization (code:Initialize or code:InitializeEmpty) or by + // user's explicit call to code:StartNewEnCSession. The heap stores its actual data size, so we can find + // out if some data were added later. + + // Gets heap size (in bytes) from the beginning of the last EnC session (code:#EnCSessionTracking). + inline UINT32 GetEnCSessionStartHeapSize() const + { + if (m_StringPool.HaveEdits()) + { + return m_StringPool.GetOffsetOfEdit(); + } + + return m_StringPool.GetRawSize(); + } + // Starts new EnC session (code:#EnCSessionTracking). + inline void StartNewEnCSession() + { + m_StringPool.ResetOffsetOfEdit(); + } + // Gets size (in bytes) aligned to 4-bytes of adds made from the beginning of the last EnC session. + __checkReturn + inline HRESULT GetEnCSessionAddedHeapSize_Aligned( + __out UINT32 *pcbSize) const + { + if (m_StringPool.HaveEdits()) + { + return m_StringPool.GetEditSaveSize(pcbSize); + } + + *pcbSize = 0; + return S_OK; + } + +}; // class StringHeapRW + +}; // namespace MetaData |