コード例 #1
0
            /**
             * Finds a matching item that is before the given coordinates in the matrix
             * (before : left and above).
             *
             * @param x The x position in the matrix (position in the old list)
             * @param y The y position in the matrix (position in the new list)
             * @param snakeIndex The current snake index
             * @param removal True if we are looking for a removal, false otherwise
             *
             * @return True if such item is found.
             */
            private bool FindMatchingItem(int x, int y, int snakeIndex, bool removal)
            {
                int myItemPos;
                int curX;
                int curY;

                if (removal)
                {
                    myItemPos = y - 1;
                    curX      = x;
                    curY      = y - 1;
                }
                else
                {
                    myItemPos = x - 1;
                    curX      = x - 1;
                    curY      = y;
                }
                for (int i = snakeIndex; i >= 0; i--)
                {
                    Snake snake = mSnakes[i];
                    int   endX  = snake.x + snake.size;
                    int   endY  = snake.y + snake.size;
                    if (removal)
                    {
                        // check removals for a match
                        for (int pos = curX - 1; pos >= endX; pos--)
                        {
                            if (mCallback.AreItemsTheSame(pos, myItemPos))
                            {
                                // found!
                                bool theSame    = mCallback.AreContentsTheSame(pos, myItemPos);
                                int  changeFlag = theSame ? FLAG_MOVED_NOT_CHANGED
                                        : FLAG_MOVED_CHANGED;
                                mNewItemStatuses[myItemPos] = (pos << FLAG_OFFSET) | FLAG_IGNORE;
                                mOldItemStatuses[pos]       = (myItemPos << FLAG_OFFSET) | changeFlag;
                                return(true);
                            }
                        }
                    }
                    else
                    {
                        // check for additions for a match
                        for (int pos = curY - 1; pos >= endY; pos--)
                        {
                            if (mCallback.AreItemsTheSame(myItemPos, pos))
                            {
                                // found
                                bool theSame    = mCallback.AreContentsTheSame(myItemPos, pos);
                                int  changeFlag = theSame ? FLAG_MOVED_NOT_CHANGED
                                        : FLAG_MOVED_CHANGED;
                                mOldItemStatuses[x - 1] = (pos << FLAG_OFFSET) | FLAG_IGNORE;
                                mNewItemStatuses[pos]   = ((x - 1) << FLAG_OFFSET) | changeFlag;
                                return(true);
                            }
                        }
                    }
                    curX = snake.x;
                    curY = snake.y;
                }
                return(false);
            }
コード例 #2
0
        private static Snake DiffPartial(Callback cb, int startOld, int endOld,
                                         int startNew, int endNew, int[] forward, int[] backward, int kOffset)
        {
            int oldSize = endOld - startOld;
            int newSize = endNew - startNew;

            if (endOld - startOld < 1 || endNew - startNew < 1)
            {
                return(null);
            }

            int delta  = oldSize - newSize;
            int dLimit = (oldSize + newSize + 1) / 2;

            Array.Fill(forward, 0, kOffset - dLimit - 1, kOffset + dLimit + 1 - (kOffset - dLimit - 1));
            Array.Fill(backward, oldSize, kOffset - dLimit - 1 + delta, kOffset + dLimit + 1 + delta - (kOffset - dLimit - 1 + delta));
            bool checkInFwd = delta % 2 != 0;

            for (int d = 0; d <= dLimit; d++)
            {
                for (int k = -d; k <= d; k += 2)
                {
                    // find forward path
                    // we can reach k from k - 1 or k + 1. Check which one is further in the graph
                    int  x;
                    bool removal;
                    if (k == -d || (k != d && forward[kOffset + k - 1] < forward[kOffset + k + 1]))
                    {
                        x       = forward[kOffset + k + 1];
                        removal = false;
                    }
                    else
                    {
                        x       = forward[kOffset + k - 1] + 1;
                        removal = true;
                    }
                    // set y based on x
                    int y = x - k;
                    // move diagonal as long as items match
                    while (x < oldSize && y < newSize &&
                           cb.AreItemsTheSame(startOld + x, startNew + y))
                    {
                        x++;
                        y++;
                    }
                    forward[kOffset + k] = x;
                    if (checkInFwd && k >= delta - d + 1 && k <= delta + d - 1)
                    {
                        if (forward[kOffset + k] >= backward[kOffset + k])
                        {
                            Snake outSnake = new Snake();
                            outSnake.x       = backward[kOffset + k];
                            outSnake.y       = outSnake.x - k;
                            outSnake.size    = forward[kOffset + k] - backward[kOffset + k];
                            outSnake.removal = removal;
                            outSnake.reverse = false;
                            return(outSnake);
                        }
                    }
                }
                for (int k = -d; k <= d; k += 2)
                {
                    // find reverse path at k + delta, in reverse
                    int  backwardK = k + delta;
                    int  x;
                    bool removal;
                    if (backwardK == d + delta || (backwardK != -d + delta &&
                                                   backward[kOffset + backwardK - 1] < backward[kOffset + backwardK + 1]))
                    {
                        x       = backward[kOffset + backwardK - 1];
                        removal = false;
                    }
                    else
                    {
                        x       = backward[kOffset + backwardK + 1] - 1;
                        removal = true;
                    }

                    // set y based on x
                    int y = x - backwardK;
                    // move diagonal as long as items match
                    while (x > 0 && y > 0 &&
                           cb.AreItemsTheSame(startOld + x - 1, startNew + y - 1))
                    {
                        x--;
                        y--;
                    }
                    backward[kOffset + backwardK] = x;
                    if (!checkInFwd && k + delta >= -d && k + delta <= d)
                    {
                        if (forward[kOffset + backwardK] >= backward[kOffset + backwardK])
                        {
                            Snake outSnake = new Snake();
                            outSnake.x    = backward[kOffset + backwardK];
                            outSnake.y    = outSnake.x - backwardK;
                            outSnake.size =
                                forward[kOffset + backwardK] - backward[kOffset + backwardK];
                            outSnake.removal = removal;
                            outSnake.reverse = true;
                            return(outSnake);
                        }
                    }
                }
            }
            throw new Exception("DiffUtil hit an unexpected case while trying to calculate"
                                + " the optimal path. Please make sure your data is not changing during the"
                                + " diff calculation.");
        }