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 | //***************************************************************************** |
21 | int 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 | //***************************************************************************** |
43 | HRESULT 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 | |
92 | ErrExit: |
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 | //***************************************************************************** |
103 | int 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 | |
137 | HRESULT 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 | |
147 | HRESULT 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 | |