in TPM Parser/Tpm2Lib/Tpm2.cs [1157:1313]
public static string CleanHex(string s)
{
// split into lines
string[] lines = s.Split(new[] { '\n', '\r' });
List<string> nonEmptyLines = new List<string>();
foreach (string line in lines)
{
// if line ended with "\r\n", empty line is created, eliminate those
if (string.IsNullOrEmpty(line.Trim()))
continue;
// replace each character that cannot be interpreted as hexadecimal
// number with a space.
string allowedChars = "0123456789abcdefABCDEF ";
char[] lineChars = line.ToCharArray();
for (int index = 0; index < lineChars.Length; index++)
{
if (!allowedChars.Contains(lineChars[index]))
{
lineChars[index] = ' ';
}
}
string hexLine = new string(lineChars);
nonEmptyLines.Add(hexLine.Trim());
}
// lines may start with an index, which is a hexadecimal number
// that number increases in each line and should be the count of all
// other hexadecimal characters (except the index).
List<uint> indices = new List<uint>();
List<uint> remainingHexCharacters = new List<uint>();
bool haveIndices = true;
foreach (string line in nonEmptyLines)
{
string[] lineSegments = line.Split(new[] { ' ' });
bool first = true;
int segmentCount = 0;
int characterCount = 0;
foreach (string segment in lineSegments)
{
if (string.IsNullOrEmpty(segment))
continue;
segmentCount++;
if (first)
{
uint index;
if (UInt32.TryParse(segment, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out index))
{
indices.Add(index);
}
first = false;
}
else
{
characterCount += segment.Length;
}
}
if (segmentCount > 1)
{
remainingHexCharacters.Add((uint)characterCount);
}
else
{
// a line with indices has at least 2 segments: the index
// and the hexadecimal numbers
haveIndices = false;
break;
}
}
if (haveIndices)
{
if (indices.Count != remainingHexCharacters.Count)
haveIndices = false;
}
if (haveIndices &&
indices.Count > 1)
{
// check if indices are equally spaced
uint step = indices[1] - indices[0];
for (int currentLine = 2;
haveIndices && (currentLine < indices.Count);
currentLine++)
{
if (step != (indices[currentLine] - indices[currentLine - 1]))
haveIndices = false;
}
}
if (haveIndices)
{
// check if count of numbers after indices match
uint expectedIndex = 0;
for (int currentLine = 0;
haveIndices && (currentLine < indices.Count);
currentLine++)
{
// there may be extra characters beyond the hexadecimal
// numbers. They are currently counted as if they are
// hexadecimal numbers. That's why the test is only for
// greater than, not for strict inequality.
if (indices[currentLine] > expectedIndex)
{
haveIndices = false;
break;
}
// the index field would indicate number of bytes. For each byte
// two hexadecimal characters are printed. Divide characterCount before
// recording. Also add counted bytes to current index to keep error
// small.
expectedIndex = indices[currentLine] + remainingHexCharacters[currentLine] / 2;
}
}
string retVal = "";
if (haveIndices)
{
// when aggregating lines with indices, leave out any extra
// hexadecimal numbers at the end of the line.
int currentLine = 0;
foreach (string line in nonEmptyLines)
{
string[] lineSegments = line.Split(new[] { ' ' });
foreach (string segment in lineSegments.Skip(1))
{
if (string.IsNullOrEmpty(segment))
continue;
// do not divide segment.Length by 2, or segments of size 1 don't have
// a size.
if ((currentLine < nonEmptyLines.Count - 1) &&
(retVal.Length + segment.Length <= indices[currentLine + 1] * 2))
{
retVal += segment;
}
else if (currentLine == nonEmptyLines.Count - 1)
{
// add all segments for last line
retVal += segment;
}
}
currentLine++;
}
}
else
{
foreach (string line in nonEmptyLines)
retVal += string.Join("", line.Split(new[] { ' ' }));
}
// Stick it back together
return retVal;
}