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 //*****************************************************************************
9 // Pools are used to reduce the amount of data actually required in the database.
10 // This allows for duplicate string and binary values to be folded into one
11 // copy shared by the rest of the database. Strings are tracked in a hash
12 // table when insert/changing data to find duplicates quickly. The strings
13 // are then persisted consecutively in a stream in the database format.
15 //*****************************************************************************
16 #include "stdafx.h" // Standard include.
17 #include <stgpool.h> // Our interface definitions.
19 int CStringPoolHash::Cmp(
20 const void *pData, // A string.
21 void *pItem) // A hash item which refers to a string.
23 STATIC_CONTRACT_NOTHROW;
24 STATIC_CONTRACT_FORBID_FAULT;
26 LPCSTR p1 = reinterpret_cast<LPCSTR>(pData);
28 if (FAILED(m_Pool->GetString(reinterpret_cast<STRINGHASH*>(pItem)->iOffset, &p2)))
32 return (strcmp(p1, p2));
33 } // int CStringPoolHash::Cmp()
36 int CBlobPoolHash::Cmp(
37 const void *pData, // A blob.
38 void *pItem) // A hash item which refers to a blob.
40 STATIC_CONTRACT_NOTHROW;
41 STATIC_CONTRACT_FORBID_FAULT;
45 MetaData::DataBlob data2;
47 // Get size of first item.
48 ul1 = CPackedLen::GetLength(pData);
49 // Adjust size to include the length of size field.
50 ul1 += CPackedLen::Size(ul1);
52 // Get the second item.
53 if (FAILED(m_Pool->GetData(reinterpret_cast<BLOBHASH*>(pItem)->iOffset, &data2)))
58 // Get and adjust size of second item.
59 ul2 = CPackedLen::GetLength(data2.GetDataPointer());
60 ul2 += CPackedLen::Size(ul2);
66 return (memcmp(pData, data2.GetDataPointer(), ul1));
67 } // int CBlobPoolHash::Cmp()
69 int CGuidPoolHash::Cmp(const void *pData, void *pItem)
71 STATIC_CONTRACT_NOTHROW;
72 STATIC_CONTRACT_FORBID_FAULT;
75 if (FAILED(m_Pool->GetGuid(reinterpret_cast<GUIDHASH*>(pItem)->iIndex, &p2)))
79 return (memcmp(pData, p2, sizeof(GUID)));
80 } // int CGuidPoolHash::Cmp()
89 //*****************************************************************************
90 // Parse a length, return the data, store length.
91 //*****************************************************************************
92 void const *CPackedLen::GetData( // Pointer to data, or 0 on error.
93 void const *pData, // First byte of length.
94 ULONG *pLength) // Put length here, or -1 on error.
96 STATIC_CONTRACT_NOTHROW;
97 STATIC_CONTRACT_FORBID_FAULT;
99 BYTE const *pBytes = reinterpret_cast<BYTE const*>(pData);
101 if ((*pBytes & 0x80) == 0x00) // 0??? ????
103 *pLength = (*pBytes & 0x7f);
107 if ((*pBytes & 0xC0) == 0x80) // 10?? ????
109 *pLength = ((*pBytes & 0x3f) << 8 | *(pBytes+1));
113 if ((*pBytes & 0xE0) == 0xC0) // 110? ????
115 *pLength = ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3));
119 *pLength = (ULONG) -1;
121 } // void const *CPackedLen::GetData()
124 #define MAX_PTR ((BYTE*)(~(SSIZE_T)0))
127 //*****************************************************************************
128 // Parse a length, return the data, store length.
129 //*****************************************************************************
130 HRESULT CPackedLen::SafeGetLength( // S_OK, or error
131 void const *pDataSource, // First byte of length.
132 void const *pDataSourceEnd, // End of valid source data memory
133 ULONG *pLength, // Length of data, if return S_OK
134 void const **ppDataNext) // Pointer immediately following encoded length
136 STATIC_CONTRACT_NOTHROW;
137 STATIC_CONTRACT_FORBID_FAULT;
139 if (pDataSource == NULL ||
140 pDataSourceEnd == NULL ||
141 pDataSourceEnd < pDataSource ||
142 ppDataNext == NULL ||
144 pDataSource > (MAX_PTR - 4))
149 BYTE const *pBytes = reinterpret_cast<BYTE const*>(pDataSource);
150 BYTE const *pBytesEnd = reinterpret_cast<BYTE const*>(pDataSourceEnd);
152 size_t cbAvail = pBytesEnd - pBytes;
155 { // Fail if no source data available
156 return COR_E_OVERFLOW;
159 if ((*pBytes & 0x80) == 0x00) // 0??? ????
161 *pLength = (*pBytes & 0x7f);
162 *ppDataNext = pBytes + 1;
167 { // Fail if not enough source data available
168 return COR_E_OVERFLOW;
171 if ((*pBytes & 0xC0) == 0x80) // 10?? ????
173 *pLength = ((*pBytes & 0x3f) << 8 | *(pBytes+1));
174 *ppDataNext = pBytes + 2;
179 { // Fail if not enough source data available
180 return COR_E_OVERFLOW;
183 if ((*pBytes & 0xE0) == 0xC0) // 110? ????
185 *pLength = ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3));
186 *ppDataNext = pBytes + 4;
190 return COR_E_OVERFLOW;
191 } // CPackedLen::GetLength
193 //*****************************************************************************
194 // Parse a length, return the data, store length.
195 //*****************************************************************************
196 HRESULT CPackedLen::SafeGetData( // S_OK, or error
197 void const *pDataSource, // First byte of length.
198 void const *pDataSourceEnd, // End of valid source data memory
199 ULONG *pcbData, // Length of data
200 void const **ppData) // Start of data
202 STATIC_CONTRACT_NOTHROW;
203 STATIC_CONTRACT_FORBID_FAULT;
207 IfFailRet(SafeGetLength(pDataSource, pDataSourceEnd, pcbData, ppData));
210 { // Zero length value means zero data, so no range checking required.
214 BYTE const *pbData = reinterpret_cast<BYTE const*>(*ppData);
216 if (pbData + *pcbData < pbData)
217 { // First check for integer overflow
218 return COR_E_OVERFLOW;
221 if (pDataSourceEnd < pbData + *pcbData)
222 { // Now check for data buffer overflow
223 return COR_E_OVERFLOW;
227 } // CPackedLen::GetLength
229 //*****************************************************************************
230 // Parse a length, return the data, store length.
231 //*****************************************************************************
232 HRESULT CPackedLen::SafeGetData( // S_OK, or error
233 void const *pDataSource, // First byte of data
234 ULONG cbDataSource, // Count of valid bytes in data source
235 ULONG *pcbData, // Length of data
236 void const **ppData) // Start of data
238 STATIC_CONTRACT_NOTHROW;
239 STATIC_CONTRACT_FORBID_FAULT;
241 return SafeGetData(pDataSource, (void const *)((BYTE const *)pDataSource + cbDataSource), pcbData, ppData);
242 } // CPackedLen::GetLength
244 //*****************************************************************************
245 // Parse a length, return the length, pointer to actual bytes.
246 //*****************************************************************************
247 ULONG CPackedLen::GetLength( // Length or -1 on error.
248 void const *pData, // First byte of length.
249 void const **ppCode) // Put pointer to bytes here, if not 0.
251 STATIC_CONTRACT_NOTHROW;
252 STATIC_CONTRACT_FORBID_FAULT;
254 BYTE const *pBytes = reinterpret_cast<BYTE const*>(pData);
256 if ((*pBytes & 0x80) == 0x00) // 0??? ????
258 if (ppCode) *ppCode = pBytes + 1;
259 return (*pBytes & 0x7f);
262 if ((*pBytes & 0xC0) == 0x80) // 10?? ????
264 if (ppCode) *ppCode = pBytes + 2;
265 return ((*pBytes & 0x3f) << 8 | *(pBytes+1));
268 if ((*pBytes & 0xE0) == 0xC0) // 110? ????
270 if (ppCode) *ppCode = pBytes + 4;
271 return ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3));
275 } // ULONG CPackedLen::GetLength()
277 //*****************************************************************************
278 // Parse a length, return the length, size of the length.
279 //*****************************************************************************
280 ULONG CPackedLen::GetLength( // Length or -1 on error.
281 void const *pData, // First byte of length.
282 int *pSizeLen) // Put size of length here, if not 0.
284 STATIC_CONTRACT_NOTHROW;
285 STATIC_CONTRACT_FORBID_FAULT;
287 BYTE const *pBytes = reinterpret_cast<BYTE const*>(pData);
289 if ((*pBytes & 0x80) == 0x00) // 0??? ????
291 if (pSizeLen) *pSizeLen = 1;
292 return (*pBytes & 0x7f);
295 if ((*pBytes & 0xC0) == 0x80) // 10?? ????
297 if (pSizeLen) *pSizeLen = 2;
298 return ((*pBytes & 0x3f) << 8 | *(pBytes+1));
301 if ((*pBytes & 0xE0) == 0xC0) // 110? ????
303 if (pSizeLen) *pSizeLen = 4;
304 return ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3));
308 } // ULONG CPackedLen::GetLength()
310 //*****************************************************************************
312 //*****************************************************************************
314 #pragma warning(disable:4244) // conversion from unsigned long to unsigned char
316 void* CPackedLen::PutLength( // First byte past length.
317 void *pData, // Pack the length here.
318 ULONG iLen) // The length.
320 STATIC_CONTRACT_NOTHROW;
321 STATIC_CONTRACT_FORBID_FAULT;
323 BYTE *pBytes = reinterpret_cast<BYTE*>(pData);
333 *pBytes = (iLen >> 8) | 0x80;
334 *(pBytes+1) = iLen & 0xFF;
338 _ASSERTE(iLen <= 0x1FFFFFFF);
339 *pBytes = (iLen >> 24) | 0xC0;
340 *(pBytes+1) = (iLen >> 16) & 0xFF;
341 *(pBytes+2) = (iLen >> 8) & 0xFF;
342 *(pBytes+3) = iLen & 0xFF;
344 } // void* CPackedLen::PutLength()
346 #pragma warning(default:4244) // conversion from unsigned long to unsigned char