[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / utilcode / stgpooli.cpp
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 // StgPool.cpp
6 // 
7
8 // 
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.
14 //
15 //*****************************************************************************
16 #include "stdafx.h"                                             // Standard include.
17 #include <stgpool.h>                                    // Our interface definitions.
18
19 int CStringPoolHash::Cmp(
20         const void      *pData,                                 // A string.
21         void            *pItem)                                 // A hash item which refers to a string.
22 {
23     STATIC_CONTRACT_NOTHROW;
24     STATIC_CONTRACT_FORBID_FAULT;
25     
26     LPCSTR p1 = reinterpret_cast<LPCSTR>(pData);
27     LPCSTR p2;
28     if (FAILED(m_Pool->GetString(reinterpret_cast<STRINGHASH*>(pItem)->iOffset, &p2)))
29     {
30         return -1;
31     }
32     return (strcmp(p1, p2));
33 } // int CStringPoolHash::Cmp()
34
35
36 int CBlobPoolHash::Cmp(
37     const void *pData,                                  // A blob.
38     void        *pItem)                                 // A hash item which refers to a blob.
39 {
40     STATIC_CONTRACT_NOTHROW;
41     STATIC_CONTRACT_FORBID_FAULT;
42     
43     ULONG ul1;
44     ULONG ul2;
45     MetaData::DataBlob data2;
46     
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);
51     
52     // Get the second item.
53     if (FAILED(m_Pool->GetData(reinterpret_cast<BLOBHASH*>(pItem)->iOffset, &data2)))
54     {
55         return -1;
56     }
57     
58     // Get and adjust size of second item.
59     ul2 = CPackedLen::GetLength(data2.GetDataPointer());
60     ul2 += CPackedLen::Size(ul2);
61     
62     if (ul1 < ul2)
63         return (-1);
64     else if (ul1 > ul2)
65         return (1);
66     return (memcmp(pData, data2.GetDataPointer(), ul1));
67 } // int CBlobPoolHash::Cmp()
68
69 int CGuidPoolHash::Cmp(const void *pData, void *pItem)
70 {
71     STATIC_CONTRACT_NOTHROW;
72     STATIC_CONTRACT_FORBID_FAULT;
73     
74     GUID *p2;
75     if (FAILED(m_Pool->GetGuid(reinterpret_cast<GUIDHASH*>(pItem)->iIndex, &p2)))
76     {
77         return -1;
78     }
79     return (memcmp(pData, p2, sizeof(GUID)));
80 } // int CGuidPoolHash::Cmp()
81
82 //
83 //
84 // CPackedLen
85 //
86 //
87
88
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.
95 {
96     STATIC_CONTRACT_NOTHROW;
97     STATIC_CONTRACT_FORBID_FAULT;
98
99         BYTE const      *pBytes = reinterpret_cast<BYTE const*>(pData);
100
101         if ((*pBytes & 0x80) == 0x00)           // 0??? ????
102         {
103                 *pLength = (*pBytes & 0x7f);
104                 return pBytes + 1;
105         }
106
107         if ((*pBytes & 0xC0) == 0x80)           // 10?? ????
108         {
109                 *pLength = ((*pBytes & 0x3f) << 8 | *(pBytes+1));
110                 return pBytes + 2;
111         }
112
113         if ((*pBytes & 0xE0) == 0xC0)           // 110? ????
114         {
115                 *pLength = ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3));
116                 return pBytes + 4;
117         }
118
119         *pLength = (ULONG) -1;
120         return 0;
121 } // void const *CPackedLen::GetData()
122
123 #ifndef MAX_PTR
124 #define MAX_PTR ((BYTE*)(~(SSIZE_T)0))
125 #endif
126
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
135 {
136     STATIC_CONTRACT_NOTHROW;
137     STATIC_CONTRACT_FORBID_FAULT;
138
139     if (pDataSource == NULL ||
140         pDataSourceEnd == NULL ||
141         pDataSourceEnd < pDataSource ||
142         ppDataNext == NULL ||
143         pLength == NULL ||
144         pDataSource > (MAX_PTR - 4))
145     {
146         return E_INVALIDARG;
147     }
148
149     BYTE const  *pBytes = reinterpret_cast<BYTE const*>(pDataSource);
150     BYTE const  *pBytesEnd = reinterpret_cast<BYTE const*>(pDataSourceEnd);
151
152     size_t cbAvail = pBytesEnd - pBytes;
153
154     if (cbAvail < 1)
155     {   // Fail if no source data available
156         return COR_E_OVERFLOW;
157     }
158
159     if ((*pBytes & 0x80) == 0x00)       // 0??? ????
160     {
161         *pLength = (*pBytes & 0x7f);
162         *ppDataNext = pBytes + 1;
163         return S_OK;
164     }
165
166     if (cbAvail < 2)
167     {   // Fail if not enough source data available
168         return COR_E_OVERFLOW;
169     }
170
171     if ((*pBytes & 0xC0) == 0x80)       // 10?? ????
172     {
173         *pLength = ((*pBytes & 0x3f) << 8 | *(pBytes+1));
174         *ppDataNext = pBytes + 2;
175         return S_OK;
176     }
177
178     if (cbAvail < 4)
179     {   // Fail if not enough source data available
180         return COR_E_OVERFLOW;
181     }
182
183     if ((*pBytes & 0xE0) == 0xC0)       // 110? ????
184     {
185         *pLength = ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3));
186         *ppDataNext = pBytes + 4;
187         return S_OK;;
188     }
189
190     return COR_E_OVERFLOW;
191 } // CPackedLen::GetLength
192
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
201 {
202     STATIC_CONTRACT_NOTHROW;
203     STATIC_CONTRACT_FORBID_FAULT;
204
205     HRESULT hr = S_OK;
206
207     IfFailRet(SafeGetLength(pDataSource, pDataSourceEnd, pcbData, ppData));
208
209     if (*pcbData == 0)
210     {   // Zero length value means zero data, so no range checking required.
211         return S_OK;
212     }
213
214     BYTE const *pbData = reinterpret_cast<BYTE const*>(*ppData);
215
216     if (pbData + *pcbData < pbData)
217     {   // First check for integer overflow
218         return COR_E_OVERFLOW;
219     }
220
221     if (pDataSourceEnd < pbData + *pcbData)
222     {   // Now check for data buffer overflow
223         return COR_E_OVERFLOW;
224     }
225
226     return S_OK;
227 } // CPackedLen::GetLength
228
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
237 {
238     STATIC_CONTRACT_NOTHROW;
239     STATIC_CONTRACT_FORBID_FAULT;
240
241     return SafeGetData(pDataSource, (void const *)((BYTE const *)pDataSource + cbDataSource), pcbData, ppData);
242 } // CPackedLen::GetLength
243
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.
250 {
251     STATIC_CONTRACT_NOTHROW;
252     STATIC_CONTRACT_FORBID_FAULT;
253
254         BYTE const      *pBytes = reinterpret_cast<BYTE const*>(pData);
255
256         if ((*pBytes & 0x80) == 0x00)           // 0??? ????
257         {
258                 if (ppCode) *ppCode = pBytes + 1;
259                 return (*pBytes & 0x7f);
260         }
261
262         if ((*pBytes & 0xC0) == 0x80)           // 10?? ????
263         {
264                 if (ppCode) *ppCode = pBytes + 2;
265                 return ((*pBytes & 0x3f) << 8 | *(pBytes+1));
266         }
267
268         if ((*pBytes & 0xE0) == 0xC0)           // 110? ????
269         {
270                 if (ppCode) *ppCode = pBytes + 4;
271                 return ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3));
272         }
273
274         return (ULONG) -1;
275 } // ULONG CPackedLen::GetLength()
276
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.
283 {
284     STATIC_CONTRACT_NOTHROW;
285     STATIC_CONTRACT_FORBID_FAULT;
286
287         BYTE const      *pBytes = reinterpret_cast<BYTE const*>(pData);
288
289         if ((*pBytes & 0x80) == 0x00)           // 0??? ????
290         {
291                 if (pSizeLen) *pSizeLen = 1;
292                 return (*pBytes & 0x7f);
293         }
294
295         if ((*pBytes & 0xC0) == 0x80)           // 10?? ????
296         {
297                 if (pSizeLen) *pSizeLen = 2;
298                 return ((*pBytes & 0x3f) << 8 | *(pBytes+1));
299         }
300
301         if ((*pBytes & 0xE0) == 0xC0)           // 110? ????
302         {
303                 if (pSizeLen) *pSizeLen = 4;
304                 return ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3));
305         }
306
307         return (ULONG) -1;
308 } // ULONG CPackedLen::GetLength()
309
310 //*****************************************************************************
311 // Encode a length.
312 //*****************************************************************************
313 #ifdef _MSC_VER
314 #pragma warning(disable:4244) // conversion from unsigned long to unsigned char
315 #endif
316 void* CPackedLen::PutLength(                    // First byte past length.
317         void            *pData,                                 // Pack the length here.
318         ULONG           iLen)                                   // The length.
319 {
320     STATIC_CONTRACT_NOTHROW;
321     STATIC_CONTRACT_FORBID_FAULT;
322
323         BYTE            *pBytes = reinterpret_cast<BYTE*>(pData);
324
325         if (iLen <= 0x7F)
326         {
327                 *pBytes = iLen;
328                 return pBytes + 1;
329         }
330
331         if (iLen <= 0x3FFF)
332         {
333                 *pBytes = (iLen >> 8) | 0x80;
334                 *(pBytes+1) = iLen & 0xFF;
335                 return pBytes + 2;
336         }
337
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;
343         return pBytes + 4;
344 } // void* CPackedLen::PutLength()
345 #ifdef _MSC_VER
346 #pragma warning(default:4244) // conversion from unsigned long to unsigned char
347 #endif
348