private void WriteAlignedBlobHeap(BlobBuilder builder) { int alignment = BitArithmetic.Align(_blobHeapSize, 4) - _blobHeapSize; var writer = new BlobWriter(builder.ReserveBytes(_blobHeapSize + alignment)); // Perf consideration: With large heap the following loop may cause a lot of cache misses // since the order of entries in _blobs dictionary depends on the hash of the array values, // which is not correlated to the heap index. If we observe such issue we should order // the entries by heap position before running this loop. int startOffset = _blobHeapStartOffset; foreach (var entry in _blobs) { int heapOffset = entry.Value.GetHeapOffset(); var blob = entry.Key; writer.Offset = (heapOffset == 0) ? 0 : heapOffset - startOffset; writer.WriteCompressedInteger(blob.Length); writer.WriteBytes(blob); } writer.Offset = _blobHeapSize; writer.WriteBytes(0, alignment); }
// TODO: // WriteBytes(byte*) // WriteBytes(stream) // WriteBytes(byte[]) // WriteBytes(IA<byte>) // WriteReference private static void TestCompressedUnsignedInteger(byte[] expected, int value) { var writer = new BlobWriter(4); writer.WriteCompressedInteger(value); AssertEx.Equal(expected, writer.ToArray()); var builder = new BlobBuilder(); builder.WriteCompressedInteger(value); AssertEx.Equal(expected, builder.ToArray()); }
public void CompressUnsignedIntegersFromSpecExamples() { // These examples are straight from the CLI spec. TestCompressedUnsignedInteger(new byte[] { 0x00 }, 0); TestCompressedUnsignedInteger(new byte[] { 0x03 }, 0x03); TestCompressedUnsignedInteger(new byte[] { 0x7f }, 0x7F); TestCompressedUnsignedInteger(new byte[] { 0x80, 0x80 }, 0x80); TestCompressedUnsignedInteger(new byte[] { 0xAE, 0x57 }, 0x2E57); TestCompressedUnsignedInteger(new byte[] { 0xBF, 0xFF }, 0x3FFF); TestCompressedUnsignedInteger(new byte[] { 0xC0, 0x00, 0x40, 0x00 }, 0x4000); TestCompressedUnsignedInteger(new byte[] { 0xDF, 0xFF, 0xFF, 0xFF }, 0x1FFFFFFF); var writer = new BlobWriter(4); var builder = new BlobBuilder(); Assert.Throws <ArgumentOutOfRangeException>(() => writer.WriteCompressedInteger(-1)); Assert.Throws <ArgumentOutOfRangeException>(() => writer.WriteCompressedInteger(BlobWriterImpl.MaxCompressedIntegerValue + 1)); Assert.Throws <ArgumentOutOfRangeException>(() => builder.WriteCompressedInteger(-1)); Assert.Throws <ArgumentOutOfRangeException>(() => builder.WriteCompressedInteger(BlobWriterImpl.MaxCompressedIntegerValue + 1)); }
private void WriteBlobHeap(BlobBuilder builder) { var writer = new BlobWriter(builder.ReserveBytes(_blobHeapSize)); // Perf consideration: With large heap the following loop may cause a lot of cache misses // since the order of entries in _blobs dictionary depends on the hash of the array values, // which is not correlated to the heap index. If we observe such issue we should order // the entries by heap position before running this loop. foreach (var entry in _blobs) { int heapOffset = MetadataTokens.GetHeapOffset(entry.Value); var blob = entry.Key; writer.Offset = heapOffset; writer.WriteCompressedInteger(blob.Length); writer.WriteBytes(blob); } }
private void InitializeValueAndSignature() { var mdReader = _symReader.MetadataReader; var constant = mdReader.GetLocalConstant(_handle); var sigReader = mdReader.GetBlobReader(constant.Signature); var sigWriter = new BlobWriter(sigReader.Length); // custom modifiers: int rawTypeCode; while (true) { rawTypeCode = sigReader.ReadCompressedInteger(); if (rawTypeCode == (int)SignatureTypeCode.OptionalModifier || rawTypeCode == (int)SignatureTypeCode.RequiredModifier) { sigReader.ReadCompressedInteger(); } else { break; } } int customModifiersLength = sigReader.Offset - 1; if (customModifiersLength > 0) { sigWriter.Write(mdReader.GetBlobBytes(constant.Signature), 0, customModifiersLength); } object translatedValue; if (rawTypeCode == (int)MetadataUtilities.SignatureTypeCode_ValueType || rawTypeCode == (int)MetadataUtilities.SignatureTypeCode_Class) { var typeHandle = sigReader.ReadTypeHandle(); if (sigReader.RemainingBytes == 0) { // null reference is returned as a boxed integer 0: translatedValue = NullReferenceValue; } else { string qualifiedName = _symReader.PdbReader.GetMetadataImport().GetQualifiedTypeName(typeHandle); if (qualifiedName == "System.Decimal") { translatedValue = sigReader.ReadDecimal(); } else if (qualifiedName == "System.DateTime") { translatedValue = BitConverter.Int64BitsToDouble(sigReader.ReadDateTime().Ticks); } else { // unknown (not produced by C# or VB) translatedValue = null; } } sigWriter.Write((byte)rawTypeCode); sigWriter.WriteCompressedInteger(MetadataUtilities.GetTypeDefOrRefOrSpecCodedIndex(typeHandle)); } else { bool isEnumTypeCode; translatedValue = ReadAndTranslateValue(ref sigReader, (SignatureTypeCode)rawTypeCode, out isEnumTypeCode); if (sigReader.RemainingBytes == 0) { // primitive type code: sigWriter.Write((byte)rawTypeCode); } else if (isEnumTypeCode) { var enumTypeHandle = sigReader.ReadTypeHandle(); // enum type signature: sigWriter.Write((byte)MetadataUtilities.SignatureTypeCode_ValueType); sigWriter.WriteCompressedInteger(MetadataUtilities.GetTypeDefOrRefOrSpecCodedIndex(enumTypeHandle)); } else { throw new BadImageFormatException(); } } _lazyValue = translatedValue; _lazySignature = sigWriter.ToArray(); }
public void CompressUnsignedIntegersFromSpecExamples() { // These examples are straight from the CLI spec. TestCompressedUnsignedInteger(new byte[] { 0x00 }, 0); TestCompressedUnsignedInteger(new byte[] { 0x03 }, 0x03); TestCompressedUnsignedInteger(new byte[] { 0x7f }, 0x7F); TestCompressedUnsignedInteger(new byte[] { 0x80, 0x80 }, 0x80); TestCompressedUnsignedInteger(new byte[] { 0xAE, 0x57 }, 0x2E57); TestCompressedUnsignedInteger(new byte[] { 0xBF, 0xFF }, 0x3FFF); TestCompressedUnsignedInteger(new byte[] { 0xC0, 0x00, 0x40, 0x00 }, 0x4000); TestCompressedUnsignedInteger(new byte[] { 0xDF, 0xFF, 0xFF, 0xFF }, 0x1FFFFFFF); var writer = new BlobWriter(4); var builder = new BlobBuilder(); Assert.Throws<ArgumentOutOfRangeException>(() => writer.WriteCompressedInteger(-1)); Assert.Throws<ArgumentOutOfRangeException>(() => writer.WriteCompressedInteger(BlobWriterImpl.MaxCompressedIntegerValue + 1)); Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteCompressedInteger(-1)); Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteCompressedInteger(BlobWriterImpl.MaxCompressedIntegerValue + 1)); }