/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.database; import android.database.sqlite.SQLiteClosable; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; /** * A buffer containing multiple cursor rows. */ public class CursorWindow extends SQLiteClosable implements Parcelable { /** The pointer to the native window class */ @SuppressWarnings("unused") private int nWindow; private int mStartPos; /** * Creates a new empty window. * * @param localWindow true if this window will be used in this process only */ public CursorWindow(boolean localWindow) { mStartPos = 0; native_init(localWindow); } /** * Returns the starting position of this window within the entire * Cursor's result set. * * @return the starting position of this window within the entire * Cursor's result set. */ public int getStartPosition() { return mStartPos; } /** * Set the start position of cursor window * @param pos */ public void setStartPosition(int pos) { mStartPos = pos; } /** * Returns the number of rows in this window. * * @return the number of rows in this window. */ public int getNumRows() { acquireReference(); try { return getNumRows_native(); } finally { releaseReference(); } } private native int getNumRows_native(); /** * Set number of Columns * @param columnNum * @return true if success */ public boolean setNumColumns(int columnNum) { acquireReference(); try { return setNumColumns_native(columnNum); } finally { releaseReference(); } } private native boolean setNumColumns_native(int columnNum); /** * Allocate a row in cursor window * @return false if cursor window is out of memory */ public boolean allocRow(){ acquireReference(); try { return allocRow_native(); } finally { releaseReference(); } } private native boolean allocRow_native(); /** * Free the last row */ public void freeLastRow(){ acquireReference(); try { freeLastRow_native(); } finally { releaseReference(); } } private native void freeLastRow_native(); /** * copy byte array to cursor window * @param value * @param row * @param col * @return false if fail to copy */ public boolean putBlob(byte[] value, int row, int col) { acquireReference(); try { return putBlob_native(value, row - mStartPos, col); } finally { releaseReference(); } } private native boolean putBlob_native(byte[] value, int row, int col); /** * Copy String to cursor window * @param value * @param row * @param col * @return false if fail to copy */ public boolean putString(String value, int row, int col) { acquireReference(); try { return putString_native(value, row - mStartPos, col); } finally { releaseReference(); } } private native boolean putString_native(String value, int row, int col); /** * Copy integer to cursor window * @param value * @param row * @param col * @return false if fail to copy */ public boolean putLong(long value, int row, int col) { acquireReference(); try { return putLong_native(value, row - mStartPos, col); } finally { releaseReference(); } } private native boolean putLong_native(long value, int row, int col); /** * Copy double to cursor window * @param value * @param row * @param col * @return false if fail to copy */ public boolean putDouble(double value, int row, int col) { acquireReference(); try { return putDouble_native(value, row - mStartPos, col); } finally { releaseReference(); } } private native boolean putDouble_native(double value, int row, int col); /** * Set the [row, col] value to NULL * @param row * @param col * @return false if fail to copy */ public boolean putNull(int row, int col) { acquireReference(); try { return putNull_native(row - mStartPos, col); } finally { releaseReference(); } } private native boolean putNull_native(int row, int col); /** * Returns {@code true} if given field is {@code NULL}. * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return {@code true} if given field is {@code NULL} */ public boolean isNull(int row, int col) { acquireReference(); try { return isNull_native(row - mStartPos, col); } finally { releaseReference(); } } private native boolean isNull_native(int row, int col); /** * Returns a byte array for the given field. * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return a String value for the given field */ public byte[] getBlob(int row, int col) { acquireReference(); try { return getBlob_native(row - mStartPos, col); } finally { releaseReference(); } } private native byte[] getBlob_native(int row, int col); /** * Checks if a field contains either a blob or is null. * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return {@code true} if given field is {@code NULL} or a blob */ public boolean isBlob(int row, int col) { acquireReference(); try { return isBlob_native(row - mStartPos, col); } finally { releaseReference(); } } private native boolean isBlob_native(int row, int col); /** * Returns a String for the given field. * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return a String value for the given field */ public String getString(int row, int col) { acquireReference(); try { return getString_native(row - mStartPos, col); } finally { releaseReference(); } } private native String getString_native(int row, int col); /** * copy the text for the given field in the provided char array. * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @param buffer the CharArrayBuffer to copy the text into, * If the requested string is larger than the buffer * a new char buffer will be created to hold the string. and assigne to * CharArrayBuffer.data */ public void copyStringToBuffer(int row, int col, CharArrayBuffer buffer) { if (buffer == null) { throw new IllegalArgumentException("CharArrayBuffer should not be null"); } if (buffer.data == null) { buffer.data = new char[64]; } acquireReference(); try { char[] newbuf = copyStringToBuffer_native( row - mStartPos, col, buffer.data.length, buffer); if (newbuf != null) { buffer.data = newbuf; } } finally { releaseReference(); } } private native char[] copyStringToBuffer_native( int row, int col, int bufferSize, CharArrayBuffer buffer); /** * Returns a long for the given field. * row is 0 based * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return a long value for the given field */ public long getLong(int row, int col) { acquireReference(); try { return getLong_native(row - mStartPos, col); } finally { releaseReference(); } } private native long getLong_native(int row, int col); /** * Returns a double for the given field. * row is 0 based * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return a double value for the given field */ public double getDouble(int row, int col) { acquireReference(); try { return getDouble_native(row - mStartPos, col); } finally { releaseReference(); } } private native double getDouble_native(int row, int col); /** * Returns a short for the given field. * row is 0 based * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return a short value for the given field */ public short getShort(int row, int col) { acquireReference(); try { return (short) getLong_native(row - mStartPos, col); } finally { releaseReference(); } } /** * Returns an int for the given field. * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return an int value for the given field */ public int getInt(int row, int col) { acquireReference(); try { return (int) getLong_native(row - mStartPos, col); } finally { releaseReference(); } } /** * Returns a float for the given field. * row is 0 based * * @param row the row to read from, row - getStartPosition() being the actual row in the window * @param col the column to read from * @return a float value for the given field */ public float getFloat(int row, int col) { acquireReference(); try { return (float) getDouble_native(row - mStartPos, col); } finally { releaseReference(); } } /** * Clears out the existing contents of the window, making it safe to reuse * for new data. Note that the number of columns in the window may NOT * change across a call to clear(). */ public void clear() { acquireReference(); try { mStartPos = 0; native_clear(); } finally { releaseReference(); } } /** Clears out the native side of things */ private native void native_clear(); /** * Cleans up the native resources associated with the window. */ public void close() { releaseReference(); } private native void close_native(); @Override protected void finalize() { // Just in case someone forgot to call close... close_native(); } public static final Parcelable.Creator<CursorWindow> CREATOR = new Parcelable.Creator<CursorWindow>() { public CursorWindow createFromParcel(Parcel source) { return new CursorWindow(source); } public CursorWindow[] newArray(int size) { return new CursorWindow[size]; } }; public static CursorWindow newFromParcel(Parcel p) { return CREATOR.createFromParcel(p); } public int describeContents() { return 0; } public void writeToParcel(Parcel dest, int flags) { dest.writeStrongBinder(native_getBinder()); dest.writeInt(mStartPos); } private CursorWindow(Parcel source) { IBinder nativeBinder = source.readStrongBinder(); mStartPos = source.readInt(); native_init(nativeBinder); } /** Get the binder for the native side of the window */ private native IBinder native_getBinder(); /** Does the native side initialization for an empty window */ private native void native_init(boolean localOnly); /** Does the native side initialization with an existing binder from another process */ private native void native_init(IBinder nativeBinder); @Override protected void onAllReferencesReleased() { close_native(); } }