[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / utilcode / stgpoolreadonly.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 // StgPoolReadOnly.cpp
6 // 
7
8 // 
9 // Read only pools are used to reduce the amount of data actually required in the database.
10 // 
11 //*****************************************************************************
12 #include "stdafx.h"                     // Standard include.
13 #include <stgpool.h>                    // Our interface definitions.
14 #include "metadatatracker.h"
15 //
16 //
17 // StgPoolReadOnly
18 //
19 //
20
21 #if METADATATRACKER_ENABLED
22 MetaDataTracker  *MetaDataTracker::m_MDTrackers = NULL;
23 BOOL MetaDataTracker::s_bEnabled = FALSE;
24
25 void        (*MetaDataTracker::s_IBCLogMetaDataAccess)(const void *addr) = NULL;
26 void        (*MetaDataTracker::s_IBCLogMetaDataSearch)(const void *result) = NULL;
27
28 #endif // METADATATRACKER_ENABLED
29
30 const BYTE StgPoolSeg::m_zeros[64] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
31                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
32                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
33                                       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
34
35
36 //*****************************************************************************
37 // Free any memory we allocated.
38 //*****************************************************************************
39 StgPoolReadOnly::~StgPoolReadOnly()
40 {
41     LIMITED_METHOD_CONTRACT;
42 }
43
44
45 //*****************************************************************************
46 // Init the pool from existing data.
47 //*****************************************************************************
48 HRESULT StgPoolReadOnly::InitOnMemReadOnly(// Return code.
49         void        *pData,             // Predefined data.
50         ULONG       iSize)              // Size of data.
51 {
52     CONTRACTL
53     {
54         NOTHROW;
55         INJECT_FAULT(return E_OUTOFMEMORY);
56     }
57     CONTRACTL_END
58     
59     // Make sure we aren't stomping anything and are properly initialized.
60     _ASSERTE(m_pSegData == m_zeros);
61     
62     // Create case requires no further action.
63     if (pData == NULL)
64         return E_INVALIDARG;
65     
66     // Keep m_zeros data pointer if there's no content of the pool
67     if (iSize != 0)
68     {
69         m_pSegData = reinterpret_cast<BYTE*>(pData);
70     }
71     m_cbSegSize = iSize;
72     m_cbSegNext = iSize;
73     return S_OK;
74 }
75
76 //*****************************************************************************
77 // Prepare to shut down or reinitialize.
78 //*****************************************************************************
79 void StgPoolReadOnly::Uninit()
80 {
81     LIMITED_METHOD_CONTRACT;
82
83     m_pSegData = (BYTE*)m_zeros;
84     m_pNextSeg = 0;
85 }
86
87
88 //*****************************************************************************
89 // Convert a string to UNICODE into the caller's buffer.
90 //*****************************************************************************
91 HRESULT StgPoolReadOnly::GetStringW(        // Return code.
92     ULONG       iOffset,                    // Offset of string in pool.
93     __out_ecount(cchBuffer) LPWSTR szOut,   // Output buffer for string.
94     int         cchBuffer)                  // Size of output buffer.
95 {
96     STATIC_CONTRACT_NOTHROW;
97     STATIC_CONTRACT_FAULT;
98     
99     HRESULT hr;
100     LPCSTR  pString;                // The string in UTF8.
101     int     iChars;
102     
103     IfFailRet(GetString(iOffset, &pString));
104     iChars = ::WszMultiByteToWideChar(CP_UTF8, 0, pString, -1, szOut, cchBuffer);
105     if (iChars == 0)
106         return (BadError(HRESULT_FROM_NT(GetLastError())));
107     return S_OK;
108 }
109
110 //*****************************************************************************
111 // Return a pointer to a null terminated blob given an offset previously
112 // handed out by Addblob or Findblob.
113 //*****************************************************************************
114 HRESULT 
115 StgPoolReadOnly::GetBlob(
116     UINT32              nOffset,    // Offset of blob in pool.
117     MetaData::DataBlob *pData)
118 {
119     STATIC_CONTRACT_NOTHROW;
120     STATIC_CONTRACT_FORBID_FAULT;
121     
122     HRESULT hr;
123     UINT32  cbBlobContentSize;
124     
125     // This should not be a necessary special case.  The zero byte at the 
126     //  start of the pool will code for a length of zero.  We will return
127     //  a pointer to the next length byte, but the caller should notice that
128     //  the size is zero, and should not look at any bytes.
129     // [SL] Yes, but we don't need all further computations and checks if iOffset==0
130     
131     if (nOffset == 0)
132     {
133         pData->Clear();
134         return S_OK;
135     }
136     
137     // Is the offset within this heap?
138     if (!IsValidOffset(nOffset))
139     {
140         Debug_ReportError("Invalid blob offset.");
141         IfFailGo(CLDB_E_INDEX_NOTFOUND);
142     }
143     
144     IfFailGo(GetDataReadOnly(nOffset, pData));
145     if (!pData->GetCompressedU(&cbBlobContentSize))
146     {
147         Debug_ReportError("Invalid blob - size compression.");
148         IfFailGo(COR_E_BADIMAGEFORMAT);
149     }
150     if (!pData->TruncateToExactSize(cbBlobContentSize))
151     {
152         Debug_ReportError("Invalid blob - reaches behind the end of data block.");
153         IfFailGo(COR_E_BADIMAGEFORMAT);
154     }
155     
156     return S_OK;
157 ErrExit:
158     pData->Clear();
159     return hr;
160 } // StgPoolReadOnly::GetBlob
161
162 //*****************************************************************************
163 // code:StgPoolReadOnly::GetBlob specialization with inlined check for valid offsets to avoid redundant code:StgPoolReadOnly::GetDataReadOnly calls.
164 // code:StgPoolReadOnly::GetDataReadOnly is not cheap because of it performs binary lookup in hot metadata.
165 //*****************************************************************************
166 HRESULT 
167 StgBlobPoolReadOnly::GetBlob(
168     UINT32              nOffset,    // Offset of blob in pool.
169     MetaData::DataBlob *pData)
170 {
171     STATIC_CONTRACT_NOTHROW;
172     STATIC_CONTRACT_FORBID_FAULT;
173     
174     HRESULT hr;
175     UINT32  cbBlobContentSize;
176     
177     // This should not be a necessary special case.  The zero byte at the 
178     //  start of the pool will code for a length of zero.  We will return
179     //  a pointer to the next length byte, but the caller should notice that
180     //  the size is zero, and should not look at any bytes.
181     // [SL] Yes, but we don't need all further computations and checks if iOffset==0
182     
183     if (nOffset == 0)
184     {
185         pData->Clear();
186         return S_OK;
187     }
188
189     if (m_pSegData == m_zeros)
190     {
191         Debug_ReportError("Invalid blob offset.");
192         IfFailGo(CLDB_E_INDEX_NOTFOUND);
193     }
194
195     IfFailGo(GetDataReadOnly(nOffset, pData));
196     if (!pData->GetCompressedU(&cbBlobContentSize))
197     {
198         Debug_ReportError("Invalid blob - size compression.");
199         IfFailGo(CLDB_E_INDEX_NOTFOUND);
200     }
201     if (!pData->TruncateToExactSize(cbBlobContentSize))
202     {
203         Debug_ReportError("Invalid blob - reaches behind the end of data block.");
204         IfFailGo(CLDB_E_INDEX_NOTFOUND);
205     }
206     
207     return S_OK;
208 ErrExit:
209     pData->Clear();
210     return hr;
211 } // StgBlobPoolReadOnly::GetBlob