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
6#include "stdafx.h"
7#include "sigbuilder.h"
8#include "ex.h"
9
10void SigBuilder::AppendByte(BYTE b)
11{
12 STANDARD_VM_CONTRACT;
13
14 Ensure(1);
15 m_pBuffer[m_dwLength++] = b;
16}
17
18void SigBuilder::AppendData(ULONG data)
19{
20 STANDARD_VM_CONTRACT;
21
22 //
23 // Inlined logic from CorSigCompressData
24 //
25
26 if (data <= 0x7F)
27 {
28 Ensure(1);
29 m_pBuffer[m_dwLength++] = BYTE(data);
30 return;
31 }
32
33 if (data <= 0x3FFF)
34 {
35 Ensure(2);
36
37 DWORD dwLength = m_dwLength;
38 BYTE * pBuffer = m_pBuffer;
39
40 pBuffer[dwLength] = BYTE((data >> 8) | 0x80);
41 pBuffer[dwLength+1] = BYTE(data);
42
43 m_dwLength = dwLength + 2;
44 return;
45 }
46
47 if (data <= 0x1FFFFFFF)
48 {
49 Ensure(4);
50
51 DWORD dwLength = m_dwLength;
52 BYTE * pBuffer = m_pBuffer;
53
54 pBuffer[dwLength] = BYTE((data >> 24) | 0xC0);
55 pBuffer[dwLength+1] = BYTE(data >> 16);
56 pBuffer[dwLength+2] = BYTE(data >> 8);
57 pBuffer[dwLength+3] = BYTE(data);
58
59 m_dwLength = dwLength + 4;
60 return;
61 }
62
63 // We currently can only represent to 0x1FFFFFFF.
64 ThrowHR(COR_E_OVERFLOW);
65}
66
67void SigBuilder::AppendToken(mdToken tk)
68{
69 STANDARD_VM_CONTRACT;
70
71 //
72 // Inlined logic from CorSigCompressToken
73 //
74
75 RID rid = RidFromToken(tk);
76 ULONG32 ulTyp = TypeFromToken(tk);
77
78 _ASSERTE(rid <= 0x3FFFFFF);
79 rid = (rid << 2);
80
81 // TypeDef is encoded with low bits 00
82 // TypeRef is encoded with low bits 01
83 // TypeSpec is encoded with low bits 10
84 // BaseType is encoded with low bit 11
85 //
86 if (ulTyp == g_tkCorEncodeToken[0])
87 {
88 // make the last two bits 00
89 // nothing to do
90 }
91 else if (ulTyp == g_tkCorEncodeToken[1])
92 {
93 // make the last two bits 01
94 rid |= 0x1;
95 }
96 else if (ulTyp == g_tkCorEncodeToken[2])
97 {
98 // make last two bits 0
99 rid |= 0x2;
100 }
101 else if (ulTyp == g_tkCorEncodeToken[3])
102 {
103 rid |= 0x3;
104 }
105 else
106 {
107 ThrowHR(COR_E_BADIMAGEFORMAT);
108 }
109
110 AppendData(rid);
111}
112
113void SigBuilder::AppendBlob(const PVOID pBlob, SIZE_T cbBlob)
114{
115 STANDARD_VM_CONTRACT;
116
117 Ensure(cbBlob);
118 memcpy(m_pBuffer + m_dwLength, pBlob, cbBlob);
119 m_dwLength += (DWORD)cbBlob;
120}
121
122void SigBuilder::Grow(SIZE_T cbMin)
123{
124 STANDARD_VM_CONTRACT;
125
126 DWORD dwNewAllocation = max(m_dwLength + (DWORD)cbMin, 2 * m_dwAllocation);
127
128 // Overflow checks
129 if (dwNewAllocation < m_dwLength || (dwNewAllocation - m_dwLength) < cbMin)
130 ThrowOutOfMemory();
131
132 BYTE * pNewAllocation = new BYTE[dwNewAllocation];
133 memcpy(pNewAllocation, m_pBuffer, m_dwLength);
134
135 BYTE * pOldAllocation = m_pBuffer;
136
137 m_pBuffer = pNewAllocation;
138 m_dwAllocation = dwNewAllocation;
139
140 if (pOldAllocation != m_prealloc)
141 delete [] pOldAllocation;
142}
143
144SigBuilder::~SigBuilder()
145{
146 if (m_pBuffer != m_prealloc)
147 delete [] m_pBuffer;
148}
149
150SigBuilder::SigBuilder(DWORD cbPreallocationSize)
151{
152 STANDARD_VM_CONTRACT;
153
154 m_dwLength = 0;
155 if (cbPreallocationSize <= sizeof(m_prealloc))
156 {
157 m_pBuffer = m_prealloc;
158 m_dwAllocation = sizeof(m_prealloc);
159 }
160 else
161 {
162 m_pBuffer = new BYTE[cbPreallocationSize];
163 m_dwAllocation = cbPreallocationSize;
164 }
165}
166