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 17 package android.database; 18 19 import android.database.sqlite.SQLiteClosable; 20 import android.os.IBinder; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 24 /** 25 * A buffer containing multiple cursor rows. 26 */ 27 public 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