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