Пример #1
0
        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));
        }
Пример #2
0
        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;
        }
Пример #3
0
        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)));
        }