static TableFragment Combine(LinkedList <TableFragmentTag> startFragmentTags, LinkedList <TableFragmentTag> endFragmentTags) { var finalFragments = new LinkedList <TableFragmentTag>(); while (startFragmentTags.Count > 0 && endFragmentTags.Count > 0) { var tailNode = startFragmentTags.First; var leadNode = endFragmentTags.First; if (tailNode.Value.Fragment == leadNode.Value.Fragment) { /* * if the tailNode and leadNode reference the same fragment, then try to replace one * of them as bad things happen when overlapping a fragment with itself. */ if (leadNode.Next != null) { leadNode = leadNode.Next; } else if (tailNode.Next != null) { tailNode = tailNode.Next; } else { break; } } var leadEnd = leadNode.Value.EndValue; var tailStart = tailNode.Value.EndValue; if (leadEnd < tailStart) { endFragmentTags.Remove(leadNode); } else if (tailStart < leadEnd) { startFragmentTags.Remove(tailNode); finalFragments.AddLast(tailNode); } else { endFragmentTags.Remove(leadNode); startFragmentTags.Remove(tailNode); TableFragment.Combine(leadNode.Value, tailNode.Value); } } while (startFragmentTags.Count > 0) { var node = startFragmentTags.First; startFragmentTags.Remove(node); finalFragments.AddLast(node); } return(ForceCombine(finalFragments)); }
static void CreateTags(TableFragment fragment, out TableFragmentTag startTag, out TableFragmentTag endTag, out int hash) { if (fragment == null) { throw new ArgumentNullException(nameof(fragment)); } var values = fragment._values; var startIndex = 0; var startValue = values[0]; var endIndex = 0; var endValue = values[values.Length - 1]; uint currentHash = 0; var startSet = false; for (var i = 0; i < values.Length; i++) { var val = values[i]; if (!startSet && val != startValue) { startSet = true; startIndex = i; } if (val != endValue) { endIndex = i; } currentHash = unchecked (((currentHash >> 5) | (currentHash << 27)) ^ (uint)val); } startTag = new TableFragmentTag() { Fragment = fragment, EndLen = startSet ? startIndex : values.Length, EndValue = startValue, }; endTag = new TableFragmentTag() { Fragment = fragment, EndLen = startSet ? values.Length - endIndex - 1 : values.Length, EndValue = endValue, }; startTag.Partner = endTag; endTag.Partner = startTag; hash = (int)currentHash; }
static TableFragment Combine(TableFragment fragment1, TableFragment fragment2, int overlap) { var values1 = fragment1._values; var values2 = fragment2._values; var states1 = fragment1._states; var states2 = fragment2._states; var offsets1 = fragment1._offsets; var offsets2 = fragment2._offsets; var offset = values1.Length - overlap; var values = new int[offset + values2.Length]; var states = new int[states1.Length + states2.Length]; var offsets = new int[states.Length]; Array.Copy(values1, values, offset); Array.Copy(values2, 0, values, offset, values2.Length); var read1 = 0; var read2 = 0; var write = 0; while (read1 < states1.Length && read2 < states2.Length) { var diff = states1[read1] - states2[read2]; if (diff == 0) { throw new InvalidOperationException("attempting to combine 2 fragments that both contain the state " + states1[read1]); } if (diff < 0) { states[write] = states1[read1]; offsets[write] = offsets1[read1]; write++; read1++; } else { states[write] = states2[read2]; offsets[write] = offsets2[read2] + offset; write++; read2++; } } while (read1 < states1.Length) { states[write] = states1[read1]; offsets[write] = offsets1[read1]; write++; read1++; } while (read2 < states2.Length) { states[write] = states2[read2]; offsets[write] = offsets2[read2] + offset; write++; read2++; } return(new TableFragment(values, states, offsets, Math.Max(fragment1.Skip, fragment2.Skip - offset))); }