public static string CleanHex()

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;
        }