CursorWindow.java revision 8b0dd7da360d70920a37802eb455ba41500d3b45
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     * @deprecated use {@link #getType(int, int)} instead
221     */
222    @Deprecated
223    public boolean isNull(int row, int col) {
224        return getType(row, col) == Cursor.FIELD_TYPE_NULL;
225    }
226
227    private native boolean isNull_native(int row, int col);
228
229    /**
230     * Returns a byte array for the given field.
231     *
232     * @param row the row to read from, row - getStartPosition() being the actual row in the window
233     * @param col the column to read from
234     * @return a String value for the given field
235     */
236    public byte[] getBlob(int row, int col) {
237        acquireReference();
238        try {
239            return getBlob_native(row - mStartPos, col);
240        } finally {
241            releaseReference();
242        }
243    }
244
245    private native byte[] getBlob_native(int row, int col);
246
247    /**
248     * Returns data type of the given column's value.
249     *<p>
250     * Returned column types are
251     * <ul>
252     *   <li>{@link Cursor#FIELD_TYPE_NULL}</li>
253     *   <li>{@link Cursor#FIELD_TYPE_INTEGER}</li>
254     *   <li>{@link Cursor#FIELD_TYPE_FLOAT}</li>
255     *   <li>{@link Cursor#FIELD_TYPE_STRING}</li>
256     *   <li>{@link Cursor#FIELD_TYPE_BLOB}</li>
257     *</ul>
258     *</p>
259     *
260     * @param row the row to read from, row - getStartPosition() being the actual row in the window
261     * @param col the column to read from
262     * @return the value type
263     */
264    public int getType(int row, int col) {
265        acquireReference();
266        try {
267            return getType_native(row - mStartPos, col);
268        } finally {
269            releaseReference();
270        }
271    }
272
273    /**
274     * Checks if a field contains either a blob or is null.
275     *
276     * @param row the row to read from, row - getStartPosition() being the actual row in the window
277     * @param col the column to read from
278     * @return {@code true} if given field is {@code NULL} or a blob
279     * @deprecated use {@link #getType(int, int)} instead
280     */
281    @Deprecated
282    public boolean isBlob(int row, int col) {
283        return getType(row, col) == Cursor.FIELD_TYPE_BLOB;
284    }
285
286    /**
287     * Checks if a field contains a long
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     * @return {@code true} if given field is a long
292     * @deprecated use {@link #getType(int, int)} instead
293     */
294    @Deprecated
295    public boolean isLong(int row, int col) {
296        return getType(row, col) == Cursor.FIELD_TYPE_INTEGER;
297    }
298
299    /**
300     * Checks if a field contains a float.
301     *
302     * @param row the row to read from, row - getStartPosition() being the actual row in the window
303     * @param col the column to read from
304     * @return {@code true} if given field is a float
305     * @deprecated use {@link #getType(int, int)} instead
306     */
307    @Deprecated
308    public boolean isFloat(int row, int col) {
309        return getType(row, col) == Cursor.FIELD_TYPE_FLOAT;
310    }
311
312    /**
313     * Checks if a field contains either a String or is null.
314     *
315     * @param row the row to read from, row - getStartPosition() being the actual row in the window
316     * @param col the column to read from
317     * @return {@code true} if given field is {@code NULL} or a String
318     * @deprecated use {@link #getType(int, int)} instead
319     */
320    @Deprecated
321    public boolean isString(int row, int col) {
322        return getType(row, col) == Cursor.FIELD_TYPE_STRING;
323    }
324
325    private native boolean isBlob_native(int row, int col);
326    private native boolean isString_native(int row, int col);
327    private native boolean isInteger_native(int row, int col);
328    private native boolean isFloat_native(int row, int col);
329    private native int getType_native(int row, int col);
330
331    /**
332     * Returns a String for the given field.
333     *
334     * @param row the row to read from, row - getStartPosition() being the actual row in the window
335     * @param col the column to read from
336     * @return a String value for the given field
337     */
338    public String getString(int row, int col) {
339        acquireReference();
340        try {
341            return getString_native(row - mStartPos, col);
342        } finally {
343            releaseReference();
344        }
345    }
346
347    private native String getString_native(int row, int col);
348
349    /**
350     * copy the text for the given field in the provided char array.
351     *
352     * @param row the row to read from, row - getStartPosition() being the actual row in the window
353     * @param col the column to read from
354     * @param buffer the CharArrayBuffer to copy the text into,
355     * If the requested string is larger than the buffer
356     * a new char buffer will be created to hold the string. and assigne to
357     * CharArrayBuffer.data
358      */
359    public void copyStringToBuffer(int row, int col, CharArrayBuffer buffer) {
360        if (buffer == null) {
361            throw new IllegalArgumentException("CharArrayBuffer should not be null");
362        }
363        if (buffer.data == null) {
364            buffer.data = new char[64];
365        }
366        acquireReference();
367        try {
368            char[] newbuf = copyStringToBuffer_native(
369                    row - mStartPos, col, buffer.data.length, buffer);
370            if (newbuf != null) {
371                buffer.data = newbuf;
372            }
373        } finally {
374            releaseReference();
375        }
376    }
377
378    private native char[] copyStringToBuffer_native(
379            int row, int col, int bufferSize, CharArrayBuffer buffer);
380
381    /**
382     * Returns a long for the given field.
383     * row is 0 based
384     *
385     * @param row the row to read from, row - getStartPosition() being the actual row in the window
386     * @param col the column to read from
387     * @return a long value for the given field
388     */
389    public long getLong(int row, int col) {
390        acquireReference();
391        try {
392            return getLong_native(row - mStartPos, col);
393        } finally {
394            releaseReference();
395        }
396    }
397
398    private native long getLong_native(int row, int col);
399
400    /**
401     * Returns a double for the given field.
402     * row is 0 based
403     *
404     * @param row the row to read from, row - getStartPosition() being the actual row in the window
405     * @param col the column to read from
406     * @return a double value for the given field
407     */
408    public double getDouble(int row, int col) {
409        acquireReference();
410        try {
411            return getDouble_native(row - mStartPos, col);
412        } finally {
413            releaseReference();
414        }
415    }
416
417    private native double getDouble_native(int row, int col);
418
419    /**
420     * Returns a short for the given field.
421     * row is 0 based
422     *
423     * @param row the row to read from, row - getStartPosition() being the actual row in the window
424     * @param col the column to read from
425     * @return a short value for the given field
426     */
427    public short getShort(int row, int col) {
428        acquireReference();
429        try {
430            return (short) getLong_native(row - mStartPos, col);
431        } finally {
432            releaseReference();
433        }
434    }
435
436    /**
437     * Returns an int for the given field.
438     *
439     * @param row the row to read from, row - getStartPosition() being the actual row in the window
440     * @param col the column to read from
441     * @return an int value for the given field
442     */
443    public int getInt(int row, int col) {
444        acquireReference();
445        try {
446            return (int) getLong_native(row - mStartPos, col);
447        } finally {
448            releaseReference();
449        }
450    }
451
452    /**
453     * Returns a float for the given field.
454     * row is 0 based
455     *
456     * @param row the row to read from, row - getStartPosition() being the actual row in the window
457     * @param col the column to read from
458     * @return a float value for the given field
459     */
460    public float getFloat(int row, int col) {
461        acquireReference();
462        try {
463            return (float) getDouble_native(row - mStartPos, col);
464        } finally {
465            releaseReference();
466        }
467    }
468
469    /**
470     * Clears out the existing contents of the window, making it safe to reuse
471     * for new data. Note that the number of columns in the window may NOT
472     * change across a call to clear().
473     */
474    public void clear() {
475        acquireReference();
476        try {
477            mStartPos = 0;
478            native_clear();
479        } finally {
480            releaseReference();
481        }
482    }
483
484    /** Clears out the native side of things */
485    private native void native_clear();
486
487    /**
488     * Cleans up the native resources associated with the window.
489     */
490    public void close() {
491        releaseReference();
492    }
493
494    private native void close_native();
495
496    @Override
497    protected void finalize() {
498        // Just in case someone forgot to call close...
499        close_native();
500    }
501
502    public static final Parcelable.Creator<CursorWindow> CREATOR
503            = new Parcelable.Creator<CursorWindow>() {
504        public CursorWindow createFromParcel(Parcel source) {
505            return new CursorWindow(source);
506        }
507
508        public CursorWindow[] newArray(int size) {
509            return new CursorWindow[size];
510        }
511    };
512
513    public static CursorWindow newFromParcel(Parcel p) {
514        return CREATOR.createFromParcel(p);
515    }
516
517    public int describeContents() {
518        return 0;
519    }
520
521    public void writeToParcel(Parcel dest, int flags) {
522        dest.writeStrongBinder(native_getBinder());
523        dest.writeInt(mStartPos);
524    }
525
526    private CursorWindow(Parcel source) {
527        IBinder nativeBinder = source.readStrongBinder();
528        mStartPos = source.readInt();
529
530        native_init(nativeBinder);
531    }
532
533    /** Get the binder for the native side of the window */
534    private native IBinder native_getBinder();
535
536    /** Does the native side initialization for an empty window */
537    private native void native_init(boolean localOnly);
538
539    /** Does the native side initialization with an existing binder from another process */
540    private native void native_init(IBinder nativeBinder);
541
542    @Override
543    protected void onAllReferencesReleased() {
544        close_native();
545    }
546}
547