ILRepack/LineNumberWriter.cs (121 lines of code) (raw):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ILRepacking
{
// copied from IKVM source
internal sealed class LineNumberWriter
{
private System.IO.MemoryStream stream;
private int prevILOffset;
private int prevLineNum;
private int count;
public LineNumberWriter(int estimatedCount)
{
stream = new System.IO.MemoryStream(estimatedCount * 2);
}
public void AddMapping(int ilOffset, int linenumber)
{
if (count == 0)
{
if (ilOffset == 0 && linenumber != 0)
{
prevLineNum = linenumber;
count++;
WritePackedInteger(linenumber - (64 + 50));
return;
}
else
{
prevLineNum = linenumber & ~3;
WritePackedInteger(((-prevLineNum / 4) - (64 + 50)));
}
}
bool pc_overflow;
bool lineno_overflow;
byte lead;
int deltaPC = ilOffset - prevILOffset;
if (deltaPC >= 0 && deltaPC < 31)
{
lead = (byte)deltaPC;
pc_overflow = false;
}
else
{
lead = (byte)31;
pc_overflow = true;
}
int deltaLineNo = linenumber - prevLineNum;
const int bias = 2;
if (deltaLineNo >= -bias && deltaLineNo < 7 - bias)
{
lead |= (byte)((deltaLineNo + bias) << 5);
lineno_overflow = false;
}
else
{
lead |= (byte)(7 << 5);
lineno_overflow = true;
}
stream.WriteByte(lead);
if (pc_overflow)
{
WritePackedInteger(deltaPC - (64 + 31));
}
if (lineno_overflow)
{
WritePackedInteger(deltaLineNo);
}
prevILOffset = ilOffset;
prevLineNum = linenumber;
count++;
}
public int Count
{
get
{
return count;
}
}
public int LineNo
{
get
{
return prevLineNum;
}
}
public byte[] ToArray()
{
return stream.ToArray();
}
/*
* packed integer format:
* ----------------------
*
* First byte:
* 00 - 7F Single byte integer (-64 - 63)
* 80 - BF Double byte integer (-8192 - 8191)
* C0 - DF Triple byte integer (-1048576 - 1048576)
* E0 - FE Reserved
* FF Five byte integer
*/
private void WritePackedInteger(int val)
{
if (val >= -64 && val < 64)
{
val += 64;
stream.WriteByte((byte)val);
}
else if (val >= -8192 && val < 8192)
{
val += 8192;
stream.WriteByte((byte)(0x80 + (val >> 8)));
stream.WriteByte((byte)val);
}
else if (val >= -1048576 && val < 1048576)
{
val += 1048576;
stream.WriteByte((byte)(0xC0 + (val >> 16)));
stream.WriteByte((byte)(val >> 8));
stream.WriteByte((byte)val);
}
else
{
stream.WriteByte(0xFF);
stream.WriteByte((byte)(val >> 24));
stream.WriteByte((byte)(val >> 16));
stream.WriteByte((byte)(val >> 8));
stream.WriteByte((byte)(val >> 0));
}
}
}
}