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 | |
17 | namespace MetaData |
18 | { |
19 | |
20 | // -------------------------------------------------------------------------------------- |
21 | // |
22 | // This class represents a read-only MetaData table (a continuous chunk of data). |
23 | // |
24 | class TableRO |
25 | { |
26 | friend class TableRW; |
27 | |
28 | private: |
29 | // |
30 | // Private data |
31 | // |
32 | |
33 | BYTE *m_pData; |
34 | |
35 | public: |
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 | |
58 | public: |
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 | // |
115 | class TableRW |
116 | { |
117 | private: |
118 | // |
119 | // Private data |
120 | // |
121 | |
122 | // The storage of table records. |
123 | RecordPool m_RecordStorage; |
124 | |
125 | public: |
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 | |
174 | public: |
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 | |
203 | public: |
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 | |