SortingCursorWrapper.java revision 5dfb345df7cb17b3a7e534a80a270b4afe7934da
15dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey/*
25dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * Copyright (C) 2013 The Android Open Source Project
35dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey *
45dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
55dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * you may not use this file except in compliance with the License.
65dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * You may obtain a copy of the License at
75dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey *
85dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
95dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey *
105dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * Unless required by applicable law or agreed to in writing, software
115dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
125dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * See the License for the specific language governing permissions and
145dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * limitations under the License.
155dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey */
165dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
175dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeypackage com.android.documentsui;
185dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
195dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.database.AbstractCursor;
205dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.database.Cursor;
215dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.provider.DocumentsContract.Document;
225dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
235dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport com.android.documentsui.DocumentsActivity.DisplayState;
245dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
255dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey/**
265dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * Cursor wrapper that presents a sorted view of the underlying cursor. Handles
275dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey * common {@link Document} sorting modes, such as ordering directories first.
285dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey */
295dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeypublic class SortingCursorWrapper extends AbstractCursor {
305dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    private final Cursor mCursor;
315dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
325dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    private final int[] mPosition;
335dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    private final String[] mValueString;
345dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    private final long[] mValueLong;
355dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
365dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public SortingCursorWrapper(Cursor cursor, int sortOrder) {
375dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        mCursor = cursor;
385dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
395dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        final int count = cursor.getCount();
405dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        mPosition = new int[count];
415dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        switch (sortOrder) {
425dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            case DisplayState.SORT_ORDER_DISPLAY_NAME:
435dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                mValueString = new String[count];
445dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                mValueLong = null;
455dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                break;
465dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            case DisplayState.SORT_ORDER_LAST_MODIFIED:
475dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            case DisplayState.SORT_ORDER_SIZE:
485dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                mValueString = null;
495dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                mValueLong = new long[count];
505dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                break;
515dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            default:
525dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                throw new IllegalArgumentException();
535dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
545dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
555dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        final int mimeTypeIndex = cursor.getColumnIndex(Document.COLUMN_MIME_TYPE);
565dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        final int displayNameIndex = cursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME);
575dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        final int lastModifiedIndex = cursor.getColumnIndex(Document.COLUMN_LAST_MODIFIED);
585dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        final int sizeIndex = cursor.getColumnIndex(Document.COLUMN_SIZE);
595dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
605dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        cursor.moveToPosition(-1);
615dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        for (int i = 0; i < count; i++) {
625dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            cursor.moveToNext();
635dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            mPosition[i] = i;
645dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
655dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            switch (sortOrder) {
665dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                case DisplayState.SORT_ORDER_DISPLAY_NAME:
675dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    final String mimeType = cursor.getString(mimeTypeIndex);
685dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    final String displayName = cursor.getString(displayNameIndex);
695dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    if (Document.MIME_TYPE_DIR.equals(mimeType)) {
705dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                        mValueString[i] = '\001' + displayName;
715dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    } else {
725dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                        mValueString[i] = displayName;
735dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    }
745dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    break;
755dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                case DisplayState.SORT_ORDER_LAST_MODIFIED:
765dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    mValueLong[i] = cursor.getLong(lastModifiedIndex);
775dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    break;
785dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                case DisplayState.SORT_ORDER_SIZE:
795dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    mValueLong[i] = cursor.getLong(sizeIndex);
805dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    break;
815dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            }
825dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
835dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
845dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        switch (sortOrder) {
855dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            case DisplayState.SORT_ORDER_DISPLAY_NAME:
865dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                synchronized (SortingCursorWrapper.class) {
875dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
885dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    binarySort(mPosition, mValueString);
895dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                }
905dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                break;
915dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            case DisplayState.SORT_ORDER_LAST_MODIFIED:
925dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            case DisplayState.SORT_ORDER_SIZE:
935dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                binarySort(mPosition, mValueLong);
945dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                break;
955dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
965dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
975dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
985dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
995dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public void close() {
1005dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        super.close();
1015dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        mCursor.close();
1025dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1035dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1045dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1055dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public boolean onMove(int oldPosition, int newPosition) {
1065dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.moveToPosition(mPosition[newPosition]);
1075dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1085dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1095dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1105dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public String[] getColumnNames() {
1115dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.getColumnNames();
1125dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1135dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1145dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1155dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public int getCount() {
1165dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.getCount();
1175dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1185dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1195dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1205dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public double getDouble(int column) {
1215dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.getDouble(column);
1225dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1235dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1245dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1255dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public float getFloat(int column) {
1265dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.getFloat(column);
1275dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1285dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1295dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1305dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public int getInt(int column) {
1315dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.getInt(column);
1325dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1335dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1345dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1355dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public long getLong(int column) {
1365dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.getLong(column);
1375dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1385dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1395dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1405dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public short getShort(int column) {
1415dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.getShort(column);
1425dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1435dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1445dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1455dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public String getString(int column) {
1465dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.getString(column);
1475dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1485dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1495dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1505dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public int getType(int column) {
1515dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.getType(column);
1525dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1535dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1545dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1555dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public boolean isNull(int column) {
1565dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        return mCursor.isNull(column);
1575dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
1585dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1595dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    /**
1605dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey     * Borrowed from TimSort.binarySort(), but modified to sort two column
1615dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey     * dataset.
1625dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey     */
1635dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    private static void binarySort(int[] position, String[] value) {
1645dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        final int count = position.length;
1655dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        for (int start = 1; start < count; start++) {
1665dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            final int pivotPosition = position[start];
1675dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            final String pivotValue = value[start];
1685dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1695dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            int left = 0;
1705dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            int right = start;
1715dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1725dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            while (left < right) {
1735dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                int mid = (left + right) >>> 1;
1745dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1755dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                final String lhs = pivotValue;
1765dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                final String rhs = value[mid];
1775dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                final int compare;
1785dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                if (lhs == null) {
1795dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    compare = -1;
1805dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                } else if (rhs == null) {
1815dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    compare = 1;
1825dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                } else {
1835dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    compare = lhs.compareToIgnoreCase(rhs);
1845dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                }
1855dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1865dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                if (compare < 0) {
1875dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    right = mid;
1885dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                } else {
1895dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    left = mid + 1;
1905dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                }
1915dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            }
1925dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
1935dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            int n = start - left;
1945dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            switch (n) {
1955dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                case 2:
1965dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    position[left + 2] = position[left + 1];
1975dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    value[left + 2] = value[left + 1];
1985dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                case 1:
1995dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    position[left + 1] = position[left];
2005dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    value[left + 1] = value[left];
2015dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    break;
2025dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                default:
2035dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    System.arraycopy(position, left, position, left + 1, n);
2045dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    System.arraycopy(value, left, value, left + 1, n);
2055dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            }
2065dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2075dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            position[left] = pivotPosition;
2085dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            value[left] = pivotValue;
2095dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
2105dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
2115dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2125dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    /**
2135dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey     * Borrowed from TimSort.binarySort(), but modified to sort two column
2145dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey     * dataset.
2155dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey     */
2165dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    private static void binarySort(int[] position, long[] value) {
2175dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        final int count = position.length;
2185dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        for (int start = 1; start < count; start++) {
2195dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            final int pivotPosition = position[start];
2205dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            final long pivotValue = value[start];
2215dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2225dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            int left = 0;
2235dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            int right = start;
2245dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2255dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            while (left < right) {
2265dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                int mid = (left + right) >>> 1;
2275dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2285dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                final long lhs = pivotValue;
2295dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                final long rhs = value[mid];
2305dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                final int compare = Long.compare(lhs, rhs);
2315dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                if (compare > 0) {
2325dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    right = mid;
2335dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                } else {
2345dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    left = mid + 1;
2355dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                }
2365dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            }
2375dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2385dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            int n = start - left;
2395dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            switch (n) {
2405dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                case 2:
2415dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    position[left + 2] = position[left + 1];
2425dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    value[left + 2] = value[left + 1];
2435dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                case 1:
2445dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    position[left + 1] = position[left];
2455dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    value[left + 1] = value[left];
2465dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    break;
2475dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                default:
2485dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    System.arraycopy(position, left, position, left + 1, n);
2495dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                    System.arraycopy(value, left, value, left + 1, n);
2505dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            }
2515dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2525dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            position[left] = pivotPosition;
2535dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            value[left] = pivotValue;
2545dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
2555dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
2565dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey}
257