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