| 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 |  |