| 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 |  | 
| 23 | namespace MetaData | 
| 24 | { | 
| 25 |  | 
| 26 | // -------------------------------------------------------------------------------------- | 
| 27 | //  | 
| 28 | // This class represents read-only #Blob heap with all utility methods. | 
| 29 | //  | 
| 30 | class BlobHeapRO | 
| 31 | { | 
| 32 |     friend class BlobHeapRW; | 
| 33 |      | 
| 34 | private: | 
| 35 |     //  | 
| 36 |     // Private data | 
| 37 |     //  | 
| 38 |      | 
| 39 |     // The storage of blobs. | 
| 40 |     StgBlobPoolReadOnly m_BlobPool; | 
| 41 |      | 
| 42 | public: | 
| 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 |      | 
| 70 | public: | 
| 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 | //  | 
| 109 | class BlobHeapRW | 
| 110 | { | 
| 111 | private: | 
| 112 |     //  | 
| 113 |     // Private data | 
| 114 |     //  | 
| 115 |      | 
| 116 |     // The storage of blobs. | 
| 117 |     StgBlobPool m_BlobPool; | 
| 118 |      | 
| 119 | public: | 
| 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 |      | 
| 181 | public: | 
| 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 |      | 
| 254 | public: | 
| 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 |      | 
| 283 | public: | 
| 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 |  |