diff options
Diffstat (limited to 'src/md/ceefilegen/ceegentokenmapper.cpp')
-rw-r--r-- | src/md/ceefilegen/ceegentokenmapper.cpp | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/md/ceefilegen/ceegentokenmapper.cpp b/src/md/ceefilegen/ceegentokenmapper.cpp new file mode 100644 index 0000000000..95ccbcd3f2 --- /dev/null +++ b/src/md/ceefilegen/ceegentokenmapper.cpp @@ -0,0 +1,160 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// CeeGenTokenMapper.cpp +// + +// +// This helper class tracks mapped tokens from their old value to the new value +// which can happen when the data is optimized on save. +// +//***************************************************************************** +#include "stdafx.h" +#include "ceegentokenmapper.h" + + +//***************************************************************************** +// At this point, only a select set of token values are stored for remap. +// If others should become required, this needs to get updated. +//***************************************************************************** +int CeeGenTokenMapper::IndexForType(mdToken tk) +{ +#ifdef CEEGEN_TRACKED_TOKEN +#undef CEEGEN_TRACKED_TOKEN +#endif +#define CEEGEN_TRACKED_TOKEN(type) case INDEX_OF_TYPE(mdt ## type): return (tkix ## type); + + int iType = INDEX_OF_TYPE(TypeFromToken(tk)); + switch(iType) + { + CEEGEN_TRACKED_TOKENS() + } + + return (-1); +} + + +//***************************************************************************** +// Called by the meta data engine when a token is remapped to a new location. +// This value is recorded in the m_rgMap array based on type and rid of the +// from token value. +//***************************************************************************** +HRESULT __stdcall CeeGenTokenMapper::Map( + mdToken tkFrom, + mdToken tkTo) +{ + HRESULT hr = S_OK; + mdToken *pToken = NULL; + ULONG ridFrom = 0; + TOKENMAP *pMap = NULL; + + BEGIN_ENTRYPOINT_NOTHROW; + + if ( IndexForType(tkFrom) == -1 ) + { + // It is a type that we are not tracking, such as mdtProperty or mdtEvent, + // just return S_OK. + goto ErrExit; + } + + _ASSERTE(IndexForType(tkFrom) < GetMaxMapSize()); + _ASSERTE(IndexForType(tkTo) != -1 && IndexForType(tkTo) < GetMaxMapSize()); + + // If there is another token mapper that the user wants called, go + // ahead and call it now. + if (m_pIMapToken) + m_pIMapToken->Map(tkFrom, tkTo); + + ridFrom = RidFromToken(tkFrom); + pMap = &m_rgMap[IndexForType(tkFrom)]; + + // If there isn't enough entries, fill out array up to the count + // and mark the token to nil so we know there is no valid data yet. + if ((ULONG) pMap->Count() <= ridFrom) + { + for (int i=ridFrom - pMap->Count() + 1; i; i--) + { + pToken = pMap->Append(); + if (!pToken) + break; + *pToken = mdTokenNil; + } + _ASSERTE(!pToken || pMap->Get(ridFrom) == pToken); + } + else + pToken = pMap->Get(ridFrom); + + IfNullGo(pToken); + + *pToken = tkTo; + +ErrExit: + END_ENTRYPOINT_NOTHROW; + + return hr; +} + + +//***************************************************************************** +// Check the given token to see if it has moved to a new location. If so, +// return true and give back the new token. +//***************************************************************************** +int CeeGenTokenMapper::HasTokenMoved( + mdToken tkFrom, + mdToken &tkTo) +{ + mdToken tk; + + int i = IndexForType(tkFrom); + if(i == -1) return false; + + _ASSERTE(i < GetMaxMapSize()); + TOKENMAP *pMap = &m_rgMap[i]; + + // Assume nothing moves. + tkTo = tkFrom; + + // If the array is smaller than the index, can't have moved. + if ((ULONG) pMap->Count() <= RidFromToken(tkFrom)) + return (false); + + // If the entry is set to 0, then nothing there. + tk = *pMap->Get(RidFromToken(tkFrom)); + if (tk == mdTokenNil) + return (false); + + // Had to move to a new location, return that new location. + tkTo = tk; + return (true); +} + + +//***************************************************************************** +// Hand out a copy of the meta data information. +//***************************************************************************** + +HRESULT CeeGenTokenMapper::GetMetaData( + IMetaDataImport **ppIImport) +{ + if (m_pIImport) + return (m_pIImport->QueryInterface(IID_IMetaDataImport, (PVOID *) ppIImport)); + *ppIImport = 0; + return E_FAIL; +} + + +HRESULT __stdcall CeeGenTokenMapper::QueryInterface(REFIID iid, PVOID *ppIUnk) +{ + if (iid == IID_IUnknown || iid == IID_IMapToken) + *ppIUnk = static_cast<IMapToken*>(this); + else + { + *ppIUnk = 0; + return (E_NOINTERFACE); + } + AddRef(); + return (S_OK); +} + + |