1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5// File: BlobHeap.h
6//
7
8//
9// Classes code:MetaData::BlobHeapRO and code:MetaData::BlobHeapRW represent #Blob heap.
10// The #Blob heap stores size-prefixed data chunks (as defined in CLI ECMA specification). Elements are
11// indexed by code:#BlobHeapIndex.
12//
13//#BlobHeapIndex
14// Blob heap indexes are 0-based. They are stored the same way in the table columns (i.e. there is no
15// 0-based vs. 1-based index difference as in table record indexes code:TableRecordStorage).
16//
17// ======================================================================================
18
19#pragma once
20
21#include "external.h"
22
23namespace MetaData
24{
25
26// --------------------------------------------------------------------------------------
27//
28// This class represents read-only #Blob heap with all utility methods.
29//
30class BlobHeapRO
31{
32 friend class BlobHeapRW;
33
34private:
35 //
36 // Private data
37 //
38
39 // The storage of blobs.
40 StgBlobPoolReadOnly m_BlobPool;
41
42public:
43 //
44 // Initialization
45 //
46
47 __checkReturn
48 HRESULT Initialize(
49 DataBlob sourceData,
50 BOOL fCopyData)
51 {
52 _ASSERTE(!fCopyData);
53 return m_BlobPool.InitOnMemReadOnly((void *)sourceData.GetDataPointer(), sourceData.GetSize());
54 }
55
56#ifdef FEATURE_PREJIT
57 // Can be called multiple times.
58 inline void InitializeHotData(
59 HotHeap hotHeap)
60 {
61 m_BlobPool.InitHotData(hotHeap);
62 }
63#endif //FEATURE_PREJIT
64
65 inline void Delete()
66 {
67 return m_BlobPool.Uninit();
68 }
69
70public:
71 //
72 // Getters
73 //
74
75 __checkReturn
76 inline HRESULT GetBlob(
77 UINT32 nIndex,
78 __out DataBlob *pData)
79 {
80 return m_BlobPool.GetBlob(nIndex, pData);
81 }
82
83 __checkReturn
84 inline HRESULT GetAllData(
85 __inout DataBlob *pData)
86 {
87 return m_BlobPool.GetDataReadOnly(0, pData);
88 }
89
90 // Gets raw size (in bytes) of the represented blob data.
91 inline UINT32 GetUnalignedSize() const
92 {
93 return m_BlobPool.GetPoolSize();
94 }
95
96 // Returns TRUE if the blob index (nIndex, see code:#BlobHeapIndex) is valid (i.e. in the blob
97 // heap).
98 inline BOOL IsValidIndex(UINT32 nIndex) const
99 {
100 return const_cast<StgBlobPoolReadOnly &>(m_BlobPool).IsValidCookie(nIndex);
101 }
102
103}; // class BlobHeapRO
104
105// --------------------------------------------------------------------------------------
106//
107// This class represents read-write #Blob heap with all utility methods.
108//
109class BlobHeapRW
110{
111private:
112 //
113 // Private data
114 //
115
116 // The storage of blobs.
117 StgBlobPool m_BlobPool;
118
119public:
120 //
121 // Initialization
122 //
123
124 __checkReturn
125 HRESULT InitializeEmpty(
126 UINT32 cbAllocationSize
127 COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite))
128 {
129 return m_BlobPool.InitNew(cbAllocationSize, 0, TRUE);
130 }
131 __checkReturn
132 HRESULT InitializeEmpty_WithItemsCount(
133 UINT32 cbAllocationSize,
134 UINT32 cItemsCount
135 COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite))
136 {
137 return m_BlobPool.InitNew(cbAllocationSize, cItemsCount, TRUE);
138 }
139 __checkReturn
140 HRESULT InitializeEmpty_WithoutDefaultEmptyBlob(
141 UINT32 cbAllocationSize
142 COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite))
143 {
144 return m_BlobPool.InitNew(cbAllocationSize, 0, FALSE);
145 }
146
147 __checkReturn
148 HRESULT Initialize(
149 DataBlob sourceData,
150 BOOL fCopyData)
151 {
152 return m_BlobPool.InitOnMem((void *)sourceData.GetDataPointer(), sourceData.GetSize(), !fCopyData);
153 }
154 __checkReturn
155 HRESULT InitializeFromBlobHeap(
156 const BlobHeapRO *pSourceBlobHeap,
157 BOOL fCopyData)
158 {
159 return m_BlobPool.InitOnMem(
160 (void *)pSourceBlobHeap->m_BlobPool.GetSegData(),
161 pSourceBlobHeap->m_BlobPool.GetDataSize(),
162 !fCopyData);
163 }
164 __checkReturn
165 HRESULT InitializeFromBlobHeap(
166 const BlobHeapRW *pSourceBlobHeap,
167 BOOL fCopyData)
168 {
169 return m_BlobPool.InitOnMem(
170 (void *)pSourceBlobHeap->m_BlobPool.GetSegData(),
171 pSourceBlobHeap->m_BlobPool.GetDataSize(),
172 !fCopyData);
173 }
174
175 // Destroys the blob heap and all its allocated data. Can run on uninitialized blob heap.
176 inline void Delete()
177 {
178 return m_BlobPool.Uninit();
179 }
180
181public:
182 //
183 // Getters
184 //
185
186 __checkReturn
187 inline HRESULT GetBlob(
188 UINT32 nIndex,
189 __out DataBlob *pData)
190 {
191 return m_BlobPool.GetBlob(nIndex, pData);
192 }
193
194 // Gets the blob with its size-prefix at index (nIndex, see code:#BlobHeapIndex), or returns error.
195 //
196 // Returns S_OK and the data (*pData) at index (nIndex). The end of the data marks the end of the blob.
197 // Returns error code otherwise (and clears *pData).
198 //
199 // User of this API shouldn't access memory behind the data buffer (*pData).
200 __checkReturn
201 inline HRESULT GetBlobWithSizePrefix(
202 UINT32 nIndex,
203 __out DataBlob *pData)
204 {
205 return m_BlobPool.GetBlobWithSizePrefix(nIndex, pData);
206 }
207
208 // Gets raw size (in bytes) of the represented blob data. Doesn't align the size as code:GetAlignedSize.
209 inline UINT32 GetUnalignedSize() const
210 {
211 return m_BlobPool.GetRawSize();
212 }
213 // Gets size (in bytes) aligned up to 4-bytes of the represented blob data.
214 // Fills *pcbSize with 0 on error.
215 __checkReturn
216 inline HRESULT GetAlignedSize(
217 __out UINT32 *pcbSize) const
218 {
219 return m_BlobPool.GetSaveSize(pcbSize);
220 }
221 // Returns TRUE if the blob heap is empty (even if it contains only default empty blob).
222 inline BOOL IsEmpty() const
223 {
224 return const_cast<StgBlobPool &>(m_BlobPool).IsEmpty();
225 }
226
227 // Returns TRUE if the blob index (nIndex, see code:#BlobHeapIndex) is valid (i.e. in the blob
228 // heap).
229 inline BOOL IsValidIndex(UINT32 nIndex) const
230 {
231 return const_cast<StgBlobPool &>(m_BlobPool).IsValidCookie(nIndex);
232 }
233
234 __checkReturn
235 HRESULT SaveToStream_Aligned(
236 UINT32 nStartIndex,
237 __in IStream *pStream) const
238 {
239 if (nStartIndex == 0)
240 {
241 return const_cast<StgBlobPool &>(m_BlobPool).PersistToStream(pStream);
242 }
243
244 if (nStartIndex == m_BlobPool.GetRawSize())
245 {
246 _ASSERTE(!m_BlobPool.HaveEdits());
247 return S_OK;
248 }
249 _ASSERTE(m_BlobPool.HaveEdits());
250 _ASSERTE(nStartIndex == m_BlobPool.GetOffsetOfEdit());
251 return const_cast<StgBlobPool &>(m_BlobPool).PersistPartialToStream(pStream, nStartIndex);
252 }
253
254public:
255 //
256 // Heap modifications
257 //
258
259 __checkReturn
260 inline HRESULT AddBlob(
261 DataBlob data,
262 __out UINT32 *pnIndex)
263 {
264 return m_BlobPool.AddBlob(&data, pnIndex);
265 }
266
267 __checkReturn
268 HRESULT AddBlobHeap(
269 const BlobHeapRW *pSourceBlobHeap,
270 UINT32 nStartSourceIndex)
271 {
272 return m_BlobPool.CopyPool(
273 nStartSourceIndex,
274 &pSourceBlobHeap->m_BlobPool);
275 } // BlobHeapRW::AddBlobHeap
276
277 __checkReturn
278 inline HRESULT MakeWritable()
279 {
280 return m_BlobPool.ConvertToRW();
281 }
282
283public:
284 //
285 // Tracking of heap modifications for EnC
286 //
287
288 //#EnCSessionTracking
289 // EnC session starts automatically with initialization (code:Initialize or code:InitializeEmpty) or by
290 // user's explicit call to code:StartNewEnCSession. The heap stores its actual data size, so we can find
291 // out if some data were added later.
292
293 // Gets heap size (in bytes) from the beginning of the last EnC session (code:#EnCSessionTracking).
294 inline UINT32 GetEnCSessionStartHeapSize() const
295 {
296 if (m_BlobPool.HaveEdits())
297 {
298 return m_BlobPool.GetOffsetOfEdit();
299 }
300
301 return m_BlobPool.GetRawSize();
302 }
303 // Starts new EnC session (code:#EnCSessionTracking).
304 inline void StartNewEnCSession()
305 {
306 m_BlobPool.ResetOffsetOfEdit();
307 }
308 // Gets size (in bytes) aligned to 4-bytes of adds made from the beginning of the last EnC session.
309 __checkReturn
310 inline HRESULT GetEnCSessionAddedHeapSize_Aligned(
311 __out UINT32 *pcbSize) const
312 {
313 if (m_BlobPool.HaveEdits())
314 {
315 return m_BlobPool.GetEditSaveSize(pcbSize);
316 }
317
318 *pcbSize = 0;
319 return S_OK;
320 }
321
322}; // class BlobHeapRW
323
324}; // namespace MetaData
325