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: StringHeap.h
6//
7
8//
9// Classes code:MetaData::StringHeapRO and code:MetaData::StringHeapRW represent #String heap.
10// The #String heap stores null-terminated UTF-8 strings (as defined in CLI ECMA specification). Elements
11// are indexed by code:#StringHeapIndex.
12//
13//#StringHeapIndex
14// String 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 #String heap with all utility methods.
29//
30class StringHeapRO
31{
32 friend class StringHeapRW;
33
34private:
35 //
36 // Private data
37 //
38
39 // The storage of strings.
40 StgPoolReadOnly m_StringPool;
41
42public:
43 //
44 // Initialization
45 //
46
47 __checkReturn
48 inline HRESULT Initialize(
49 DataBlob sourceData,
50 BOOL fCopyData)
51 {
52 _ASSERTE(!fCopyData);
53 return m_StringPool.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_StringPool.InitHotData(hotHeap);
62 }
63#endif //FEATURE_PREJIT
64
65 inline void Delete()
66 {
67 return m_StringPool.Uninit();
68 }
69
70public:
71 //
72 // Getters
73 //
74
75 __checkReturn
76 inline HRESULT GetString(
77 UINT32 nIndex,
78 __deref_out_z LPCSTR *pszString) const
79 {
80 return const_cast<StgPoolReadOnly &>(m_StringPool).GetString(
81 nIndex,
82 pszString);
83 }
84
85 // Gets raw size (in bytes) of the represented strings.
86 inline UINT32 GetUnalignedSize() const
87 {
88 return m_StringPool.GetPoolSize();
89 }
90
91}; // class StringHeapRO
92
93// --------------------------------------------------------------------------------------
94//
95// This class represents read-write #String heap with all utility methods.
96//
97class StringHeapRW
98{
99private:
100 //
101 // Private data
102 //
103
104 // The storage of strings.
105 StgStringPool m_StringPool;
106
107public:
108 //
109 // Initialization
110 //
111
112 __checkReturn
113 inline HRESULT InitializeEmpty(
114 UINT32 cbAllocationSize
115 COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite))
116 {
117 return m_StringPool.InitNew(cbAllocationSize, 0);
118 }
119 __checkReturn
120 inline HRESULT InitializeEmpty_WithItemsCount(
121 UINT32 cbAllocationSize,
122 UINT32 cItemsCount
123 COMMA_INDEBUG_MD(BOOL debug_fIsReadWrite))
124 {
125 return m_StringPool.InitNew(cbAllocationSize, cItemsCount);
126 }
127 __checkReturn
128 inline HRESULT Initialize(
129 DataBlob sourceData,
130 BOOL fCopyData)
131 {
132 return m_StringPool.InitOnMem((void *)sourceData.GetDataPointer(), sourceData.GetSize(), !fCopyData);
133 }
134 __checkReturn
135 inline HRESULT InitializeFromStringHeap(
136 const StringHeapRO *pSourceStringHeap,
137 BOOL fCopyData)
138 {
139 return m_StringPool.InitOnMem(
140 (void *)pSourceStringHeap->m_StringPool.GetSegData(),
141 pSourceStringHeap->m_StringPool.GetDataSize(),
142 !fCopyData);
143 }
144 __checkReturn
145 inline HRESULT InitializeFromStringHeap(
146 const StringHeapRW *pSourceStringHeap,
147 BOOL fCopyData)
148 {
149 return m_StringPool.InitOnMem(
150 (void *)pSourceStringHeap->m_StringPool.GetSegData(),
151 pSourceStringHeap->m_StringPool.GetDataSize(),
152 !fCopyData);
153 }
154
155 // Destroys the string heap and all its allocated data. Can run on uninitialized string heap.
156 inline void Delete()
157 {
158 return m_StringPool.Uninit();
159 }
160
161public:
162 //
163 // Getters
164 //
165
166 __checkReturn
167 inline HRESULT GetString(
168 UINT32 nIndex,
169 __deref_out_z LPCSTR *pszString) const
170 {
171 return const_cast<StgStringPool &>(m_StringPool).GetString(
172 nIndex,
173 pszString);
174 }
175
176 // Gets raw size (in bytes) of the represented strings. Doesn't align the size as code:GetAlignedSize.
177 inline UINT32 GetUnalignedSize() const
178 {
179 return m_StringPool.GetRawSize();
180 }
181 // Gets size (in bytes) aligned up to 4-bytes of the represented strings.
182 // Fills *pcbSize with 0 on error.
183 __checkReturn
184 inline HRESULT GetAlignedSize(
185 __out UINT32 *pcbSize) const
186 {
187 return m_StringPool.GetSaveSize(pcbSize);
188 }
189 // Returns TRUE if the string heap is empty (even if it contains only default empty string).
190 inline BOOL IsEmpty() const
191 {
192 return const_cast<StgStringPool &>(m_StringPool).IsEmpty();
193 }
194
195 // Returns TRUE if the string index (nIndex, see code:#StringHeapIndex) is valid (i.e. in the string
196 // heap).
197 inline BOOL IsValidIndex(UINT32 nIndex) const
198 {
199 return const_cast<StgStringPool &>(m_StringPool).IsValidCookie(nIndex);
200 }
201
202 __checkReturn
203 inline HRESULT SaveToStream_Aligned(
204 UINT32 nStartIndex,
205 __in IStream *pStream) const
206 {
207 if (nStartIndex == 0)
208 {
209 return const_cast<StgStringPool &>(m_StringPool).PersistToStream(pStream);
210 }
211
212 if (nStartIndex == m_StringPool.GetRawSize())
213 {
214 _ASSERTE(!m_StringPool.HaveEdits());
215 return S_OK;
216 }
217 _ASSERTE(m_StringPool.HaveEdits());
218 _ASSERTE(nStartIndex == m_StringPool.GetOffsetOfEdit());
219 return const_cast<StgStringPool &>(m_StringPool).PersistPartialToStream(pStream, nStartIndex);
220 }
221
222public:
223 //
224 // Heap modifications
225 //
226
227 // Adds null-terminated UTF-8 string (szString) to the end of the heap (incl. its null-terminator).
228 // Returns S_OK and index of added string (*pnIndex).
229 // Returns error code otherwise (and fills *pnIndex with 0).
230 __checkReturn
231 inline HRESULT AddString(
232 __in_z LPCSTR szString,
233 __out UINT32 *pnIndex)
234 {
235 return m_StringPool.AddString(szString, pnIndex);
236 }
237 // Adds null-terminated UTF-16 string (wszString) to the end of the heap (incl. its null-terminator).
238 // Returns S_OK and index of added string (*pnIndex).
239 // Returns error code otherwise (and fills *pnIndex with 0).
240 __checkReturn
241 inline HRESULT AddStringW(
242 __in_z LPCWSTR wszString,
243 __out UINT32 *pnIndex)
244 {
245 return m_StringPool.AddStringW(wszString, pnIndex);
246 }
247
248 // Adds data from *pSourceStringHeap starting at index (nStartSourceIndex) to the string heap.
249 // Returns S_OK (even if the source is empty) or error code.
250 __checkReturn
251 inline HRESULT AddStringHeap(
252 const StringHeapRW *pSourceStringHeap,
253 UINT32 nStartSourceIndex)
254 {
255 return m_StringPool.CopyPool(
256 nStartSourceIndex,
257 &pSourceStringHeap->m_StringPool);
258 } // StringHeapRW::AddStringHeap
259
260 __checkReturn
261 inline HRESULT MakeWritable()
262 {
263 return m_StringPool.ConvertToRW();
264 }
265
266public:
267 //
268 // Tracking of heap modifications for EnC
269 //
270
271 //#EnCSessionTracking
272 // EnC session starts automatically with initialization (code:Initialize or code:InitializeEmpty) or by
273 // user's explicit call to code:StartNewEnCSession. The heap stores its actual data size, so we can find
274 // out if some data were added later.
275
276 // Gets heap size (in bytes) from the beginning of the last EnC session (code:#EnCSessionTracking).
277 inline UINT32 GetEnCSessionStartHeapSize() const
278 {
279 if (m_StringPool.HaveEdits())
280 {
281 return m_StringPool.GetOffsetOfEdit();
282 }
283
284 return m_StringPool.GetRawSize();
285 }
286 // Starts new EnC session (code:#EnCSessionTracking).
287 inline void StartNewEnCSession()
288 {
289 m_StringPool.ResetOffsetOfEdit();
290 }
291 // Gets size (in bytes) aligned to 4-bytes of adds made from the beginning of the last EnC session.
292 __checkReturn
293 inline HRESULT GetEnCSessionAddedHeapSize_Aligned(
294 __out UINT32 *pcbSize) const
295 {
296 if (m_StringPool.HaveEdits())
297 {
298 return m_StringPool.GetEditSaveSize(pcbSize);
299 }
300
301 *pcbSize = 0;
302 return S_OK;
303 }
304
305}; // class StringHeapRW
306
307}; // namespace MetaData
308