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// CeeGenTokenMapper.cpp
6//
7
8//
9// This helper class tracks mapped tokens from their old value to the new value
10// which can happen when the data is optimized on save.
11//
12//*****************************************************************************
13#include "stdafx.h"
14#include "ceegentokenmapper.h"
15
16
17//*****************************************************************************
18// At this point, only a select set of token values are stored for remap.
19// If others should become required, this needs to get updated.
20//*****************************************************************************
21int CeeGenTokenMapper::IndexForType(mdToken tk)
22{
23#ifdef CEEGEN_TRACKED_TOKEN
24#undef CEEGEN_TRACKED_TOKEN
25#endif
26#define CEEGEN_TRACKED_TOKEN(type) case INDEX_OF_TYPE(mdt ## type): return (tkix ## type);
27
28 int iType = INDEX_OF_TYPE(TypeFromToken(tk));
29 switch(iType)
30 {
31 CEEGEN_TRACKED_TOKENS()
32 }
33
34 return (-1);
35}
36
37
38//*****************************************************************************
39// Called by the meta data engine when a token is remapped to a new location.
40// This value is recorded in the m_rgMap array based on type and rid of the
41// from token value.
42//*****************************************************************************
43HRESULT STDMETHODCALLTYPE CeeGenTokenMapper::Map(
44 mdToken tkFrom,
45 mdToken tkTo)
46{
47 HRESULT hr = S_OK;
48 mdToken *pToken = NULL;
49 ULONG ridFrom = 0;
50 TOKENMAP *pMap = NULL;
51
52 BEGIN_ENTRYPOINT_NOTHROW;
53
54 if ( IndexForType(tkFrom) == -1 )
55 {
56 // It is a type that we are not tracking, such as mdtProperty or mdtEvent,
57 // just return S_OK.
58 goto ErrExit;
59 }
60
61 _ASSERTE(IndexForType(tkFrom) < GetMaxMapSize());
62 _ASSERTE(IndexForType(tkTo) != -1 && IndexForType(tkTo) < GetMaxMapSize());
63
64 // If there is another token mapper that the user wants called, go
65 // ahead and call it now.
66 if (m_pIMapToken)
67 m_pIMapToken->Map(tkFrom, tkTo);
68
69 ridFrom = RidFromToken(tkFrom);
70 pMap = &m_rgMap[IndexForType(tkFrom)];
71
72 // If there isn't enough entries, fill out array up to the count
73 // and mark the token to nil so we know there is no valid data yet.
74 if ((ULONG) pMap->Count() <= ridFrom)
75 {
76 for (int i=ridFrom - pMap->Count() + 1; i; i--)
77 {
78 pToken = pMap->Append();
79 if (!pToken)
80 break;
81 *pToken = mdTokenNil;
82 }
83 _ASSERTE(!pToken || pMap->Get(ridFrom) == pToken);
84 }
85 else
86 pToken = pMap->Get(ridFrom);
87
88 IfNullGo(pToken);
89
90 *pToken = tkTo;
91
92ErrExit:
93 END_ENTRYPOINT_NOTHROW;
94
95 return hr;
96}
97
98
99//*****************************************************************************
100// Check the given token to see if it has moved to a new location. If so,
101// return true and give back the new token.
102//*****************************************************************************
103int CeeGenTokenMapper::HasTokenMoved(
104 mdToken tkFrom,
105 mdToken &tkTo)
106{
107 mdToken tk;
108
109 int i = IndexForType(tkFrom);
110 if(i == -1) return false;
111
112 _ASSERTE(i < GetMaxMapSize());
113 TOKENMAP *pMap = &m_rgMap[i];
114
115 // Assume nothing moves.
116 tkTo = tkFrom;
117
118 // If the array is smaller than the index, can't have moved.
119 if ((ULONG) pMap->Count() <= RidFromToken(tkFrom))
120 return (false);
121
122 // If the entry is set to 0, then nothing there.
123 tk = *pMap->Get(RidFromToken(tkFrom));
124 if (tk == mdTokenNil)
125 return (false);
126
127 // Had to move to a new location, return that new location.
128 tkTo = tk;
129 return (true);
130}
131
132
133//*****************************************************************************
134// Hand out a copy of the meta data information.
135//*****************************************************************************
136
137HRESULT CeeGenTokenMapper::GetMetaData(
138 IMetaDataImport **ppIImport)
139{
140 if (m_pIImport)
141 return (m_pIImport->QueryInterface(IID_IMetaDataImport, (PVOID *) ppIImport));
142 *ppIImport = 0;
143 return E_FAIL;
144}
145
146
147HRESULT STDMETHODCALLTYPE CeeGenTokenMapper::QueryInterface(REFIID iid, PVOID *ppIUnk)
148{
149 if (iid == IID_IUnknown || iid == IID_IMapToken)
150 *ppIUnk = static_cast<IMapToken*>(this);
151 else
152 {
153 *ppIUnk = 0;
154 return (E_NOINTERFACE);
155 }
156 AddRef();
157 return (S_OK);
158}
159
160
161