/// <summary>
        ///     Generates a sequence of DiffItems representing differences in rawDiffStream.
        /// </summary>
        /// <param name="includeUnchangedBlocks">
        ///     Indicates whether to generate DiffItems for unchanged blocks.
        /// </param>
        /// <returns>A DiffItem generator.</returns>
        public static IEnumerable<DiffItem> EnumerateDifferences(StreamCombiner rawDiffStream, bool includeUnchangedBlocks)
        {
            DiffItem prevItem = null;
            DiffItem item = null;
            string line = null;
            do
            {
                line = rawDiffStream == null ? null : rawDiffStream.ReadLine();

                if (line != null && line.StartsWith("<"))
                {
                    ++item.BaseLineCount;
                }
                else if (line != null && line.StartsWith("-"))
                {
                    continue;
                }
                else if (line != null && line.StartsWith(">"))
                {
                    ++item.DiffLineCount;
                }
                else if (line != null && line.Equals("\\ No newline at end of file"))
                {
                    // This is a very annoying perforce thing. But we have to account for it.
                    continue;
                }
                else
                {
                    if (item != null)
                    {
                        if (item.DiffLineCount == 0)
                            item.DiffType = DiffType.Deleted;
                        else if (item.BaseLineCount == 0)
                            item.DiffType = DiffType.Added;
                        else
                            item.DiffType = DiffType.Changed;

                        yield return item;
                        prevItem = item;
                        item = null;
                    }

                    if (line != null)
                    {
                        item = new DiffItem();

                        var m = DiffDecoder.Match(line);
                        if (!m.Success)
                            yield break;

                        item.BaseStartLineNumber = Int32.Parse(m.Groups[1].Value);

                        // 'a' adds AFTER the line, but we do processing once we get to the line.
                        // So we need to really get to the next line.
                        if (m.Groups[3].Value.Equals("a"))
                            item.BaseStartLineNumber += 1;
                    }

                    if (includeUnchangedBlocks)
                    {
                        var unchangedItem = new DiffItem();
                        unchangedItem.DiffType = DiffType.Unchanged;
                        unchangedItem.BaseStartLineNumber =
                            prevItem == null ? 1 : prevItem.BaseStartLineNumber + prevItem.BaseLineCount;
                        unchangedItem.BaseLineCount = item == null
                                                          ? int.MaxValue
                                                          : item.BaseStartLineNumber - unchangedItem.BaseStartLineNumber;
                        unchangedItem.DiffLineCount = unchangedItem.BaseLineCount;

                        if (unchangedItem.BaseLineCount != 0)
                            yield return unchangedItem;
                    }
                }
            } while (line != null);
        }