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