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 | |
23 | namespace MetaData |
24 | { |
25 | |
26 | // -------------------------------------------------------------------------------------- |
27 | // |
28 | // This class represents read-only #String heap with all utility methods. |
29 | // |
30 | class StringHeapRO |
31 | { |
32 | friend class StringHeapRW; |
33 | |
34 | private: |
35 | // |
36 | // Private data |
37 | // |
38 | |
39 | // The storage of strings. |
40 | StgPoolReadOnly m_StringPool; |
41 | |
42 | public: |
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 | |
70 | public: |
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 | // |
97 | class StringHeapRW |
98 | { |
99 | private: |
100 | // |
101 | // Private data |
102 | // |
103 | |
104 | // The storage of strings. |
105 | StgStringPool m_StringPool; |
106 | |
107 | public: |
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 | |
161 | public: |
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 | |
222 | public: |
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 | |
266 | public: |
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 | |