Free cookie consent management tool by TermsFeed Policy Generator

source: tags/3.3.13/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory-5.5.0/TypeSystem/Implementation/BlobReader.cs @ 18242

Last change on this file since 18242 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 10.6 KB
Line 
1//
2// BlobReader.cs
3//
4// Author:
5//       Daniel Grunwald <daniel@danielgrunwald.de>
6//
7// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
8//
9// Permission is hereby granted, free of charge, to any person obtaining a copy
10// of this software and associated documentation files (the "Software"), to deal
11// in the Software without restriction, including without limitation the rights
12// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the Software is
14// furnished to do so, subject to the following conditions:
15//
16// The above copyright notice and this permission notice shall be included in
17// all copies or substantial portions of the Software.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25// THE SOFTWARE.
26
27using System;
28using System.Collections.Generic;
29using ICSharpCode.NRefactory.Semantics;
30
31namespace ICSharpCode.NRefactory.TypeSystem.Implementation
32{
33  sealed class BlobReader
34  {
35    internal static int GetBlobHashCode(byte[] blob)
36    {
37      unchecked {
38        int hash = 0;
39        foreach (byte b in blob) {
40          hash *= 257;
41          hash += b;
42        }
43        return hash;
44      }
45    }
46   
47    internal static bool BlobEquals(byte[] a, byte[] b)
48    {
49      if (a.Length != b.Length)
50        return false;
51      for (int i = 0; i < a.Length; i++) {
52        if (a[i] != b[i])
53          return false;
54      }
55      return true;
56    }
57   
58    byte[] buffer;
59    int position;
60    readonly IAssembly currentResolvedAssembly;
61
62    public BlobReader(byte[] buffer, IAssembly currentResolvedAssembly)
63    {
64      if (buffer == null)
65        throw new ArgumentNullException("buffer");
66      this.buffer = buffer;
67      this.currentResolvedAssembly = currentResolvedAssembly;
68    }
69   
70    public byte ReadByte()
71    {
72      return buffer[position++];
73    }
74
75    public sbyte ReadSByte()
76    {
77      unchecked {
78        return(sbyte) ReadByte();
79      }
80    }
81   
82    public byte[] ReadBytes(int length)
83    {
84      var bytes = new byte[length];
85      Buffer.BlockCopy(buffer, position, bytes, 0, length);
86      position += length;
87      return bytes;
88    }
89
90    public ushort ReadUInt16()
91    {
92      unchecked {
93        ushort value =(ushort)(buffer[position]
94                               |(buffer[position + 1] << 8));
95        position += 2;
96        return value;
97      }
98    }
99
100    public short ReadInt16()
101    {
102      unchecked {
103        return(short) ReadUInt16();
104      }
105    }
106
107    public uint ReadUInt32()
108    {
109      unchecked {
110        uint value =(uint)(buffer[position]
111                           |(buffer[position + 1] << 8)
112                           |(buffer[position + 2] << 16)
113                           |(buffer[position + 3] << 24));
114        position += 4;
115        return value;
116      }
117    }
118
119    public int ReadInt32()
120    {
121      unchecked {
122        return(int) ReadUInt32();
123      }
124    }
125
126    public ulong ReadUInt64()
127    {
128      unchecked {
129        uint low = ReadUInt32();
130        uint high = ReadUInt32();
131
132        return(((ulong) high) << 32) | low;
133      }
134    }
135
136    public long ReadInt64()
137    {
138      unchecked {
139        return(long) ReadUInt64();
140      }
141    }
142
143    public uint ReadCompressedUInt32()
144    {
145      unchecked {
146        byte first = ReadByte();
147        if((first & 0x80) == 0)
148          return first;
149
150        if((first & 0x40) == 0)
151          return((uint)(first & ~0x80) << 8)
152            | ReadByte();
153
154        return((uint)(first & ~0xc0) << 24)
155          |(uint) ReadByte() << 16
156          |(uint) ReadByte() << 8
157          | ReadByte();
158      }
159    }
160
161    public float ReadSingle()
162    {
163      unchecked {
164        if(!BitConverter.IsLittleEndian) {
165          var bytes = ReadBytes(4);
166          Array.Reverse(bytes);
167          return BitConverter.ToSingle(bytes, 0);
168        }
169
170        float value = BitConverter.ToSingle(buffer, position);
171        position += 4;
172        return value;
173      }
174    }
175
176    public double ReadDouble()
177    {
178      unchecked {
179        if(!BitConverter.IsLittleEndian) {
180          var bytes = ReadBytes(8);
181          Array.Reverse(bytes);
182          return BitConverter.ToDouble(bytes, 0);
183        }
184
185        double value = BitConverter.ToDouble(buffer, position);
186        position += 8;
187        return value;
188      }
189    }
190   
191    public ResolveResult ReadFixedArg(IType argType)
192    {
193      if (argType.Kind == TypeKind.Array) {
194        if (((ArrayType)argType).Dimensions != 1) {
195          // Only single-dimensional arrays are supported
196          return ErrorResolveResult.UnknownError;
197        }
198        IType elementType = ((ArrayType)argType).ElementType;
199        uint numElem = ReadUInt32();
200        if (numElem == 0xffffffff) {
201          // null reference
202          return new ConstantResolveResult(argType, null);
203        } else {
204          ResolveResult[] elements = new ResolveResult[numElem];
205          for (int i = 0; i < elements.Length; i++) {
206            elements[i] = ReadElem(elementType);
207            // Stop decoding when encountering an error:
208            if (elements[i].IsError)
209              return ErrorResolveResult.UnknownError;
210          }
211          IType int32 = currentResolvedAssembly.Compilation.FindType(KnownTypeCode.Int32);
212          ResolveResult[] sizeArgs = { new ConstantResolveResult(int32, elements.Length) };
213          return new ArrayCreateResolveResult(argType, sizeArgs, elements);
214        }
215      } else {
216        return ReadElem(argType);
217      }
218    }
219   
220    public ResolveResult ReadElem(IType elementType)
221    {
222      ITypeDefinition underlyingType;
223      if (elementType.Kind == TypeKind.Enum) {
224        underlyingType = elementType.GetDefinition().EnumUnderlyingType.GetDefinition();
225      } else {
226        underlyingType = elementType.GetDefinition();
227      }
228      if (underlyingType == null)
229        return ErrorResolveResult.UnknownError;
230      KnownTypeCode typeCode = underlyingType.KnownTypeCode;
231      if (typeCode == KnownTypeCode.Object) {
232        // boxed value type
233        IType boxedTyped = ReadCustomAttributeFieldOrPropType();
234        ResolveResult elem = ReadElem(boxedTyped);
235        if (elem.IsCompileTimeConstant && elem.ConstantValue == null)
236          return new ConstantResolveResult(elementType, null);
237        else
238          return new ConversionResolveResult(elementType, elem, Conversion.BoxingConversion);
239      } else if (typeCode == KnownTypeCode.Type) {
240        return new TypeOfResolveResult(underlyingType, ReadType());
241      } else {
242        return new ConstantResolveResult(elementType, ReadElemValue(typeCode));
243      }
244    }
245   
246    object ReadElemValue(KnownTypeCode typeCode)
247    {
248      switch (typeCode) {
249        case KnownTypeCode.Boolean:
250          return ReadByte() != 0;
251        case KnownTypeCode.Char:
252          return (char)ReadUInt16();
253        case KnownTypeCode.SByte:
254          return ReadSByte();
255        case KnownTypeCode.Byte:
256          return ReadByte();
257        case KnownTypeCode.Int16:
258          return ReadInt16();
259        case KnownTypeCode.UInt16:
260          return ReadUInt16();
261        case KnownTypeCode.Int32:
262          return ReadInt32();
263        case KnownTypeCode.UInt32:
264          return ReadUInt32();
265        case KnownTypeCode.Int64:
266          return ReadInt64();
267        case KnownTypeCode.UInt64:
268          return ReadUInt64();
269        case KnownTypeCode.Single:
270          return ReadSingle();
271        case KnownTypeCode.Double:
272          return ReadDouble();
273        case KnownTypeCode.String:
274          return ReadSerString();
275        default:
276          throw new NotSupportedException();
277      }
278    }
279   
280    public string ReadSerString ()
281    {
282      if (buffer [position] == 0xff) {
283        position++;
284        return null;
285      }
286
287      int length = (int) ReadCompressedUInt32();
288      if (length == 0)
289        return string.Empty;
290
291      string @string = System.Text.Encoding.UTF8.GetString(
292        buffer, position,
293        buffer [position + length - 1] == 0 ? length - 1 : length);
294
295      position += length;
296      return @string;
297    }
298   
299    public KeyValuePair<IMember, ResolveResult> ReadNamedArg(IType attributeType)
300    {
301      SymbolKind memberType;
302      var b = ReadByte();
303      switch (b) {
304        case 0x53:
305          memberType = SymbolKind.Field;
306          break;
307        case 0x54:
308          memberType = SymbolKind.Property;
309          break;
310        default:
311          throw new NotSupportedException(string.Format("Custom member type 0x{0:x} is not supported.", b));
312      }
313      IType type = ReadCustomAttributeFieldOrPropType();
314      string name = ReadSerString();
315      ResolveResult val = ReadFixedArg(type);
316      IMember member = null;
317      // Use last matching member, as GetMembers() returns members from base types first.
318      foreach (IMember m in attributeType.GetMembers(m => m.SymbolKind == memberType && m.Name == name)) {
319        if (m.ReturnType.Equals(type))
320          member = m;
321      }
322      return new KeyValuePair<IMember, ResolveResult>(member, val);
323    }
324
325    IType ReadCustomAttributeFieldOrPropType()
326    {
327      ICompilation compilation = currentResolvedAssembly.Compilation;
328      var b = ReadByte();
329      switch (b) {
330        case 0x02:
331          return compilation.FindType(KnownTypeCode.Boolean);
332        case 0x03:
333          return compilation.FindType(KnownTypeCode.Char);
334        case 0x04:
335          return compilation.FindType(KnownTypeCode.SByte);
336        case 0x05:
337          return compilation.FindType(KnownTypeCode.Byte);
338        case 0x06:
339          return compilation.FindType(KnownTypeCode.Int16);
340        case 0x07:
341          return compilation.FindType(KnownTypeCode.UInt16);
342        case 0x08:
343          return compilation.FindType(KnownTypeCode.Int32);
344        case 0x09:
345          return compilation.FindType(KnownTypeCode.UInt32);
346        case 0x0a:
347          return compilation.FindType(KnownTypeCode.Int64);
348        case 0x0b:
349          return compilation.FindType(KnownTypeCode.UInt64);
350        case 0x0c:
351          return compilation.FindType(KnownTypeCode.Single);
352        case 0x0d:
353          return compilation.FindType(KnownTypeCode.Double);
354        case 0x0e:
355          return compilation.FindType(KnownTypeCode.String);
356        case 0x1d:
357          return new ArrayType(compilation, ReadCustomAttributeFieldOrPropType());
358        case 0x50:
359          return compilation.FindType(KnownTypeCode.Type);
360        case 0x51: // boxed value type
361          return compilation.FindType(KnownTypeCode.Object);
362        case 0x55: // enum
363          return ReadType();
364        default:
365          throw new NotSupportedException(string.Format("Custom attribute type 0x{0:x} is not supported.", b));
366      }
367    }
368   
369    IType ReadType()
370    {
371      string typeName = ReadSerString();
372      ITypeReference typeReference = ReflectionHelper.ParseReflectionName(typeName);
373      IType typeInCurrentAssembly = typeReference.Resolve(new SimpleTypeResolveContext(currentResolvedAssembly));
374      if (typeInCurrentAssembly.Kind != TypeKind.Unknown)
375        return typeInCurrentAssembly;
376     
377      // look for the type in mscorlib
378      ITypeDefinition systemObject = currentResolvedAssembly.Compilation.FindType(KnownTypeCode.Object).GetDefinition();
379      if (systemObject != null) {
380        return typeReference.Resolve(new SimpleTypeResolveContext(systemObject.ParentAssembly));
381      } else {
382        // couldn't find corlib - return the unknown IType for the current assembly
383        return typeInCurrentAssembly;
384      }
385    }
386  }
387}
Note: See TracBrowser for help on using the repository browser.