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