CursorWindow.java revision f013e1afd1e68af5e3b868c26a653bbfb39538f8
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.database;
18
19import android.database.sqlite.SQLiteClosable;
20import android.os.IBinder;
21import android.os.Parcel;
22import android.os.Parcelable;
23
24/**
25 * A buffer containing multiple cursor rows.
26 */
27public class CursorWindow extends SQLiteClosable implements Parcelable {
28    /** The pointer to the native window class */
29    @SuppressWarnings("unused")
30    private int nWindow;
31
32    private int mStartPos;
33
34    /**
35     * Creates a new empty window.
36     *
37     * @param localWindow true if this window will be used in this process only
38     */
39    public CursorWindow(boolean localWindow) {
40        mStartPos = 0;
41        native_init(localWindow);
42    }
43
44    /**
45     * Returns the starting position of this window within the entire
46     * Cursor's result set.
47     *
48     * @return the starting position of this window within the entire
49     * Cursor's result set.
50     */
51    public int getStartPosition() {
52        return mStartPos;
53    }
54
55    /**
56     * Set the start position of cursor window
57     * @param pos
58     */
59    public void setStartPosition(int pos) {
60        mStartPos = pos;
61    }
62
63    /**
64     * Returns the number of rows in this window.
65     *
66     * @return the number of rows in this window.
67     */
68    public int getNumRows() {
69        acquireReference();
70        try {
71            return getNumRows_native();
72        } finally {
73            releaseReference();
74        }
75    }
76
77    private native int getNumRows_native();
78    /**
79     * Set number of Columns
80     * @param columnNum
81     * @return true if success
82     */
83    public boolean setNumColumns(int columnNum) {
84        acquireReference();
85        try {
86            return setNumColumns_native(columnNum);
87        } finally {
88            releaseReference();
89        }
90    }
91
92    private native boolean setNumColumns_native(int columnNum);
93
94    /**
95     * Allocate a row in cursor window
96     * @return false if cursor window is out of memory
97     */
98    public boolean allocRow(){
99        acquireReference();
100        try {
101            return allocRow_native();
102        } finally {
103            releaseReference();
104        }
105    }
106
107    private native boolean allocRow_native();
108
109    /**
110     * Free the last row
111     */
112    public void freeLastRow(){
113        acquireReference();
114        try {
115            freeLastRow_native();
116        } finally {
117            releaseReference();
118        }
119    }
120
121    private native void freeLastRow_native();
122
123    /**
124     * copy byte array to cursor window
125     * @param value
126     * @param row
127     * @param col
128     * @return false if fail to copy
129     */
130    public boolean putBlob(byte[] value, int row, int col) {
131        acquireReference();
132        try {
133            return putBlob_native(value, row - mStartPos, col);
134        } finally {
135            releaseReference();
136        }
137    }
138
139    private native boolean putBlob_native(byte[] value, int row, int col);
140
141    /**
142     * Copy String to cursor window
143     * @param value
144     * @param row
145     * @param col
146     * @return false if fail to copy
147     */
148    public boolean putString(String value, int row, int col) {
149        acquireReference();
150        try {
151            return putString_native(value, row - mStartPos, col);
152        } finally {
153            releaseReference();
154        }
155    }
156
157    private native boolean putString_native(String value, int row, int col);
158
159    /**
160     * Copy integer to cursor window
161     * @param value
162     * @param row
163     * @param col
164     * @return false if fail to copy
165     */
166    public boolean putLong(long value, int row, int col) {
167        acquireReference();
168        try {
169            return putLong_native(value, row - mStartPos, col);
170        } finally {
171            releaseReference();
172        }
173    }
174
175    private native boolean putLong_native(long value, int row, int col);
176
177
178    /**
179     * Copy double to cursor window
180     * @param value
181     * @param row
182     * @param col
183     * @return false if fail to copy
184     */
185    public boolean putDouble(double value, int row, int col) {
186        acquireReference();
187        try {
188            return putDouble_native(value, row - mStartPos, col);
189        } finally {
190            releaseReference();
191        }
192    }
193
194    private native boolean putDouble_native(double value, int row, int col);
195
196    /**
197     * Set the [row, col] value to NULL
198     * @param row
199     * @param col
200     * @return false if fail to copy
201     */
202    public boolean putNull(int row, int col) {
203        acquireReference();
204        try {
205            return putNull_native(row - mStartPos, col);
206        } finally {
207            releaseReference();
208        }
209    }
210
211    private native boolean putNull_native(int row, int col);
212
213
214    /**
215     * Returns {@code true} if given field is {@code NULL}.
216     *
217     * @param row the row to read from, row - getStartPosition() being the actual row in the window
218     * @param col the column to read from
219     * @return {@code true} if given field is {@code NULL}
220     */
221    public boolean isNull(int row, int col) {
222        acquireReference();
223        try {
224            return isNull_native(row - mStartPos, col);
225        } finally {
226            releaseReference();
227        }
228    }
229
230    private native boolean isNull_native(int row, int col);
231
232    /**
233     * Returns a byte array for the given field.
234     *
235     * @param row the row to read from, row - getStartPosition() being the actual row in the window
236     * @param col the column to read from
237     * @return a String value for the given field
238     */
239    public byte[] getBlob(int row, int col) {
240        acquireReference();
241        try {
242            return getBlob_native(row - mStartPos, col);
243        } finally {
244            releaseReference();
245        }
246    }
247
248    private native byte[] getBlob_native(int row, int col);
249
250    /**
251     * Checks if a field contains either a blob or is null.
252     *
253     * @param row the row to read from, row - getStartPosition() being the actual row in the window
254     * @param col the column to read from
255     * @return {@code true} if given field is {@code NULL} or a blob
256     */
257    public boolean isBlob(int row, int col) {
258        acquireReference();
259        try {
260            return isBlob_native(row - mStartPos, col);
261        } finally {
262            releaseReference();
263        }
264    }
265
266    private native boolean isBlob_native(int row, int col);
267
268    /**
269     * Returns a String for the given field.
270     *
271     * @param row the row to read from, row - getStartPosition() being the actual row in the window
272     * @param col the column to read from
273     * @return a String value for the given field
274     */
275    public String getString(int row, int col) {
276        acquireReference();
277        try {
278            return getString_native(row - mStartPos, col);
279        } finally {
280            releaseReference();
281        }
282    }
283
284    private native String getString_native(int row, int col);
285
286    /**
287     * copy the text for the given field in the provided char array.
288     *
289     * @param row the row to read from, row - getStartPosition() being the actual row in the window
290     * @param col the column to read from
291     * @param buffer the CharArrayBuffer to copy the text into,
292     * If the requested string is larger than the buffer
293     * a new char buffer will be created to hold the string. and assigne to
294     * CharArrayBuffer.data
295      */
296    public void copyStringToBuffer(int row, int col, CharArrayBuffer buffer) {
297        if (buffer == null) {
298            throw new IllegalArgumentException("CharArrayBuffer should not be null");
299        }
300        if (buffer.data == null) {
301            buffer.data = new char[64];
302        }
303        acquireReference();
304        try {
305            char[] newbuf = copyStringToBuffer_native(
306                    row - mStartPos, col, buffer.data.length, buffer);
307            if (newbuf != null) {
308                buffer.data = newbuf;
309            }
310        } finally {
311            releaseReference();
312        }
313    }
314
315    private native char[] copyStringToBuffer_native(
316            int row, int col, int bufferSize, CharArrayBuffer buffer);
317
318    /**
319     * Returns a long for the given field.
320     * row is 0 based
321     *
322     * @param row the row to read from, row - getStartPosition() being the actual row in the window
323     * @param col the column to read from
324     * @return a long value for the given field
325     */
326    public long getLong(int row, int col) {
327        acquireReference();
328        try {
329            return getLong_native(row - mStartPos, col);
330        } finally {
331            releaseReference();
332        }
333    }
334
335    private native long getLong_native(int row, int col);
336
337    /**
338     * Returns a double for the given field.
339     * row is 0 based
340     *
341     * @param row the row to read from, row - getStartPosition() being the actual row in the window
342     * @param col the column to read from
343     * @return a double value for the given field
344     */
345    public double getDouble(int row, int col) {
346        acquireReference();
347        try {
348            return getDouble_native(row - mStartPos, col);
349        } finally {
350            releaseReference();
351        }
352    }
353
354    private native double getDouble_native(int row, int col);
355
356    /**
357     * Returns a short for the given field.
358     * row is 0 based
359     *
360     * @param row the row to read from, row - getStartPosition() being the actual row in the window
361     * @param col the column to read from
362     * @return a short value for the given field
363     */
364    public short getShort(int row, int col) {
365        acquireReference();
366        try {
367            return (short) getLong_native(row - mStartPos, col);
368        } finally {
369            releaseReference();
370        }
371    }
372
373    /**
374     * Returns an int for the given field.
375     *
376     * @param row the row to read from, row - getStartPosition() being the actual row in the window
377     * @param col the column to read from
378     * @return an int value for the given field
379     */
380    public int getInt(int row, int col) {
381        acquireReference();
382        try {
383            return (int) getLong_native(row - mStartPos, col);
384        } finally {
385            releaseReference();
386        }
387    }
388
389    /**
390     * Returns a float for the given field.
391     * row is 0 based
392     *
393     * @param row the row to read from, row - getStartPosition() being the actual row in the window
394     * @param col the column to read from
395     * @return a float value for the given field
396     */
397    public float getFloat(int row, int col) {
398        acquireReference();
399        try {
400            return (float) getDouble_native(row - mStartPos, col);
401        } finally {
402            releaseReference();
403        }
404    }
405
406    /**
407     * Clears out the existing contents of the window, making it safe to reuse
408     * for new data. Note that the number of columns in the window may NOT
409     * change across a call to clear().
410     */
411    public void clear() {
412        acquireReference();
413        try {
414            mStartPos = 0;
415            native_clear();
416        } finally {
417            releaseReference();
418        }
419    }
420
421    /** Clears out the native side of things */
422    private native void native_clear();
423
424    /**
425     * Cleans up the native resources associated with the window.
426     */
427    public void close() {
428        releaseReference();
429    }
430
431    private native void close_native();
432
433    @Override
434    protected void finalize() {
435        // Just in case someone forgot to call close...
436        close_native();
437    }
438
439    public static final Parcelable.Creator<CursorWindow> CREATOR
440            = new Parcelable.Creator<CursorWindow>() {
441        public CursorWindow createFromParcel(Parcel source) {
442            return new CursorWindow(source);
443        }
444
445        public CursorWindow[] newArray(int size) {
446            return new CursorWindow[size];
447        }
448    };
449
450    public static CursorWindow newFromParcel(Parcel p) {
451        return CREATOR.createFromParcel(p);
452    }
453
454    public int describeContents() {
455        return 0;
456    }
457
458    public void writeToParcel(Parcel dest, int flags) {
459        dest.writeStrongBinder(native_getBinder());
460        dest.writeInt(mStartPos);
461    }
462
463    private CursorWindow(Parcel source) {
464        IBinder nativeBinder = source.readStrongBinder();
465        mStartPos = source.readInt();
466
467        native_init(nativeBinder);
468    }
469
470    /** Get the binder for the native side of the window */
471    private native IBinder native_getBinder();
472
473    /** Does the native side initialization for an empty window */
474    private native void native_init(boolean localOnly);
475
476    /** Does the native side initialization with an existing binder from another process */
477    private native void native_init(IBinder nativeBinder);
478
479    @Override
480    protected void onAllReferencesReleased() {
481        close_native();
482    }
483}
484