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: Table.h
6//
7
8//
9// Class code:MetaData::Table represents a MetaData table.
10//
11// ======================================================================================
12
13#pragma once
14
15#include "external.h"
16
17namespace MetaData
18{
19
20// --------------------------------------------------------------------------------------
21//
22// This class represents a read-only MetaData table (a continuous chunk of data).
23//
24class TableRO
25{
26 friend class TableRW;
27
28private:
29 //
30 // Private data
31 //
32
33 BYTE *m_pData;
34
35public:
36 //
37 // Initialization
38 //
39
40 __checkReturn
41 inline HRESULT Initialize(
42 __range(2, UINT32_MAX) UINT32 cbRecordSize,
43 DataBlob sourceData,
44 BOOL fCopyData)
45 {
46 _ASSERTE(!fCopyData);
47 _ASSERTE((cbRecordSize == 0) || (sourceData.GetSize() % cbRecordSize == 0));
48 m_pData = sourceData.GetDataPointer();
49 return S_OK;
50 }
51
52 // Destroys the table and all its allocated data. Can run on uninitialized table.
53 inline void Delete()
54 {
55 m_pData = NULL;
56 }
57
58public:
59 //
60 // Getters
61 //
62
63 __checkReturn
64 inline HRESULT GetRecord(
65 UINT32 nRowIndex,
66 __deref_out_opt BYTE **ppRecord,
67 UINT32 cbRecordSize,
68 UINT32 cRecordCount,
69#ifdef FEATURE_PREJIT
70 struct HotTablesDirectory *pHotTablesDirectory,
71#endif //FEATURE_PREJIT
72 UINT32 nTableIndex)
73 {
74 if ((nRowIndex == 0) || (nRowIndex > cRecordCount))
75 {
76 Debug_ReportError("Invalid record index.");
77 *ppRecord = NULL;
78 return CLDB_E_INDEX_NOTFOUND;
79 }
80#ifdef FEATURE_PREJIT
81 if ((pHotTablesDirectory != NULL) && (pHotTablesDirectory->m_rgTableHeader_SignedOffset[nTableIndex] != 0))
82 {
83 HRESULT hr = HotTable::GetData(
84 nRowIndex,
85 ppRecord,
86 cbRecordSize,
87 HotTable::GetTableHeader(pHotTablesDirectory, nTableIndex));
88
89 if (hr == S_OK)
90 {
91 _ASSERTE(memcmp(
92 *ppRecord,
93 m_pData + (nRowIndex - 1) * cbRecordSize,
94 cbRecordSize) == 0);
95 return S_OK;
96 }
97 if (FAILED(hr))
98 {
99 *ppRecord = NULL;
100 return hr;
101 }
102 _ASSERTE(hr == S_FALSE);
103 }
104#endif //FEATURE_PREJIT
105 *ppRecord = m_pData + (nRowIndex - 1) * cbRecordSize;
106 return S_OK;
107 } // TableRO::GetRecord
108
109}; // class TableRO
110
111// --------------------------------------------------------------------------------------
112//
113// This class represents a read-write MetaData table.
114//
115class TableRW
116{
117private:
118 //
119 // Private data
120 //
121
122 // The storage of table records.
123 RecordPool m_RecordStorage;
124
125public:
126 //
127 // Initialization
128 //
129
130 // Initializes (empty) table of record size (cbRecordSize) with new allocated data for cRecordCount
131 // records.
132 __checkReturn
133 inline HRESULT InitializeEmpty_WithRecordCount(
134 __range(2, UINT32_MAX) UINT32 cbRecordSize,
135 __range(0, UINT32_MAX) UINT32 cRecordCount
136 COMMA_INDEBUG_MD( BOOL debug_fIsReadWrite))
137 {
138 return m_RecordStorage.InitNew(cbRecordSize, cRecordCount);
139 }
140
141 __checkReturn
142 inline HRESULT Initialize(
143 __range(2, UINT32_MAX) UINT32 cbRecordSize,
144 DataBlob sourceData,
145 BOOL fCopyData)
146 {
147 return m_RecordStorage.InitOnMem(cbRecordSize, sourceData.GetDataPointer(), sourceData.GetSize(), !fCopyData);
148 }
149
150 __checkReturn
151 inline HRESULT InitializeFromTable(
152 const TableRO *pSourceTable,
153 UINT32 cbRecordSize,
154 UINT32 cRecordCount,
155 BOOL fCopyData)
156 {
157 return m_RecordStorage.InitOnMem(cbRecordSize, pSourceTable->m_pData, cbRecordSize * cRecordCount, !fCopyData);
158 }
159 __checkReturn
160 inline HRESULT InitializeFromTable(
161 const TableRW *pSourceTable,
162 BOOL fCopyData)
163 {
164 _ASSERTE(fCopyData);
165 return m_RecordStorage.ReplaceContents(const_cast<RecordPool *>(&pSourceTable->m_RecordStorage));
166 }
167
168 // Destroys the table and all its allocated data. Can run on uninitialized table.
169 inline void Delete()
170 {
171 return m_RecordStorage.Uninit();
172 }
173
174public:
175 //
176 // Getters
177 //
178
179 inline UINT32 GetRecordCount() const
180 {
181 return const_cast<RecordPool &>(m_RecordStorage).Count();
182 }
183 inline HRESULT GetRecordsDataSize(UINT32 *pcbSize) const
184 {
185 return m_RecordStorage.GetSaveSize(pcbSize);
186 }
187
188 __checkReturn
189 inline HRESULT GetRecord(
190 UINT32 nIndex,
191 __deref_out_opt BYTE **ppRecord)
192 {
193 return m_RecordStorage.GetRecord(nIndex, ppRecord);
194 }
195
196 __checkReturn
197 inline HRESULT SaveToStream(
198 IStream *pStream) const
199 {
200 return const_cast<RecordPool &>(m_RecordStorage).PersistToStream(pStream);
201 }
202
203public:
204 //
205 // Setters
206 //
207
208 __checkReturn
209 inline HRESULT AddRecord(
210 __out BYTE **ppbRecord,
211 __out UINT32 *pnIndex)
212 {
213 return m_RecordStorage.AddRecord(ppbRecord, pnIndex);
214 }
215 __checkReturn
216 inline HRESULT InsertRecord(
217 UINT32 nIndex,
218 BYTE **ppbRecord)
219 {
220 return m_RecordStorage.InsertRecord(nIndex, ppbRecord);
221 }
222
223 // Makes table data writable, i.e. copies them into newly allocated chunk of memory. The caller
224 // guarantees that the table is not writable yet (otherwise this method asserts).
225 //
226 // Returns S_OK (even if the table is empty).
227 // Returns METADATA_E_INTERNAL_ERROR error code if the table has more segments.
228 __checkReturn
229 inline HRESULT MakeWritable()
230 {
231 return m_RecordStorage.ConvertToRW();
232 }
233
234#ifdef _DEBUG_METADATA
235 // Sets table information for debugging.
236 void Debug_SetTableInfo(const char *szTableName, UINT32 nTableIndex)
237 {
238 }
239#endif //_DEBUG_METADATA
240
241}; // class TableRW
242
243}; // namespace MetaData
244