OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkStream.h" | 10 #include "SkStream.h" |
11 #include "SkData.h" | 11 #include "SkData.h" |
12 #include "SkFixed.h" | 12 #include "SkFixed.h" |
13 #include "SkString.h" | 13 #include "SkString.h" |
14 #include "SkOSFile.h" | 14 #include "SkOSFile.h" |
15 | 15 |
16 SK_DEFINE_INST_COUNT(SkStream) | 16 SK_DEFINE_INST_COUNT(SkStream) |
17 SK_DEFINE_INST_COUNT(SkWStream) | 17 SK_DEFINE_INST_COUNT(SkWStream) |
18 SK_DEFINE_INST_COUNT(SkFILEStream) | 18 SK_DEFINE_INST_COUNT(SkFILEStream) |
19 SK_DEFINE_INST_COUNT(SkFDStream) | |
20 SK_DEFINE_INST_COUNT(SkMemoryStream) | 19 SK_DEFINE_INST_COUNT(SkMemoryStream) |
21 SK_DEFINE_INST_COUNT(SkBufferStream) | |
22 SK_DEFINE_INST_COUNT(SkFILEWStream) | 20 SK_DEFINE_INST_COUNT(SkFILEWStream) |
23 SK_DEFINE_INST_COUNT(SkMemoryWStream) | 21 SK_DEFINE_INST_COUNT(SkMemoryWStream) |
24 SK_DEFINE_INST_COUNT(SkDynamicMemoryWStream) | 22 SK_DEFINE_INST_COUNT(SkDynamicMemoryWStream) |
25 SK_DEFINE_INST_COUNT(SkDebugWStream) | 23 SK_DEFINE_INST_COUNT(SkDebugWStream) |
26 | 24 |
27 /////////////////////////////////////////////////////////////////////////////// | 25 /////////////////////////////////////////////////////////////////////////////// |
28 | 26 |
29 const char* SkStream::getFileName() | |
30 { | |
31 // override in subclass if you represent a file | |
32 return NULL; | |
33 } | |
34 | |
35 const void* SkStream::getMemoryBase() | |
36 { | |
37 // override in subclass if you represent a memory block | |
38 return NULL; | |
39 } | |
40 | |
41 size_t SkStream::skip(size_t size) | |
42 { | |
43 /* Check for size == 0, and just return 0. If we passed that | |
44 to read(), it would interpret it as a request for the entire | |
45 size of the stream. | |
46 */ | |
47 return size ? this->read(NULL, size) : 0; | |
48 } | |
49 | 27 |
50 int8_t SkStream::readS8() { | 28 int8_t SkStream::readS8() { |
51 int8_t value; | 29 int8_t value; |
52 SkDEBUGCODE(size_t len =) this->read(&value, 1); | 30 SkDEBUGCODE(size_t len =) this->read(&value, 1); |
53 SkASSERT(1 == len); | 31 SkASSERT(1 == len); |
54 return value; | 32 return value; |
55 } | 33 } |
56 | 34 |
57 int16_t SkStream::readS16() { | 35 int16_t SkStream::readS16() { |
58 int16_t value; | 36 int16_t value; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 this->write32(data->size()); | 192 this->write32(data->size()); |
215 this->write(data->data(), data->size()); | 193 this->write(data->data(), data->size()); |
216 } else { | 194 } else { |
217 this->write32(0); | 195 this->write32(0); |
218 } | 196 } |
219 return true; | 197 return true; |
220 } | 198 } |
221 | 199 |
222 /////////////////////////////////////////////////////////////////////////////// | 200 /////////////////////////////////////////////////////////////////////////////// |
223 | 201 |
224 SkFILEStream::SkFILEStream(const char file[]) : fName(file) { | 202 SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerP
asses_Ownership) { |
225 fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL; | 203 fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL; |
226 } | 204 } |
227 | 205 |
| 206 SkFILEStream::SkFILEStream(FILE* file, Ownership ownership) |
| 207 : fFILE((SkFILE*)file) |
| 208 , fOwnership(ownership) { |
| 209 } |
| 210 |
228 SkFILEStream::~SkFILEStream() { | 211 SkFILEStream::~SkFILEStream() { |
229 if (fFILE) { | 212 if (fFILE && fOwnership != kCallerRetains_Ownership) { |
230 sk_fclose(fFILE); | 213 sk_fclose(fFILE); |
231 } | 214 } |
232 } | 215 } |
233 | 216 |
234 void SkFILEStream::setPath(const char path[]) { | 217 void SkFILEStream::setPath(const char path[]) { |
235 fName.set(path); | 218 fName.set(path); |
236 if (fFILE) { | 219 if (fFILE) { |
237 sk_fclose(fFILE); | 220 sk_fclose(fFILE); |
238 fFILE = NULL; | 221 fFILE = NULL; |
239 } | 222 } |
240 if (path) { | 223 if (path) { |
241 fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag); | 224 fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag); |
242 } | 225 } |
243 } | 226 } |
244 | 227 |
245 const char* SkFILEStream::getFileName() { | 228 size_t SkFILEStream::read(void* buffer, size_t size) { |
246 return fName.c_str(); | 229 if (fFILE) { |
| 230 return sk_fread(buffer, size, fFILE); |
| 231 } |
| 232 return 0; |
| 233 } |
| 234 |
| 235 bool SkFILEStream::atEnd() const { |
| 236 return sk_feof(fFILE); |
247 } | 237 } |
248 | 238 |
249 bool SkFILEStream::rewind() { | 239 bool SkFILEStream::rewind() { |
250 if (fFILE) { | 240 if (fFILE) { |
251 if (sk_frewind(fFILE)) { | 241 if (sk_frewind(fFILE)) { |
252 return true; | 242 return true; |
253 } | 243 } |
254 // we hit an error | 244 // we hit an error |
255 sk_fclose(fFILE); | 245 sk_fclose(fFILE); |
256 fFILE = NULL; | 246 fFILE = NULL; |
257 } | 247 } |
258 return false; | 248 return false; |
259 } | 249 } |
260 | 250 |
261 size_t SkFILEStream::read(void* buffer, size_t size) { | 251 SkStreamAsset* SkFILEStream::duplicate() const { |
262 if (fFILE) { | 252 if (NULL == fFILE) { |
263 if (buffer == NULL && size == 0) { // special signature, they want the
total size | 253 return new SkMemoryStream(); |
264 return sk_fgetsize(fFILE); | 254 } |
265 } else { | 255 |
266 return sk_fread(buffer, size, fFILE); | 256 if (NULL != fData.get()) { |
| 257 return new SkMemoryStream(fData); |
| 258 } |
| 259 |
| 260 if (!fName.isEmpty()) { |
| 261 SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str())); |
| 262 if (sk_fidentical(that->fFILE, this->fFILE)) { |
| 263 return that.detach(); |
267 } | 264 } |
268 } | 265 } |
269 return 0; | 266 |
| 267 fData.reset(SkData::NewFromFILE(fFILE)); |
| 268 if (NULL == fData.get()) { |
| 269 return NULL; |
| 270 } |
| 271 return new SkMemoryStream(fData); |
| 272 } |
| 273 |
| 274 size_t SkFILEStream::getPosition() const { |
| 275 return sk_ftell(fFILE); |
| 276 } |
| 277 |
| 278 bool SkFILEStream::seek(size_t position) { |
| 279 return sk_fseek(fFILE, position); |
| 280 } |
| 281 |
| 282 bool SkFILEStream::move(long offset) { |
| 283 return sk_fmove(fFILE, offset); |
| 284 } |
| 285 |
| 286 SkStreamAsset* SkFILEStream::fork() const { |
| 287 SkAutoTUnref<SkStreamAsset> that(this->duplicate()); |
| 288 that->seek(this->getPosition()); |
| 289 return that.detach(); |
| 290 } |
| 291 |
| 292 size_t SkFILEStream::getLength() const { |
| 293 return sk_fgetsize(fFILE); |
| 294 } |
| 295 |
| 296 const void* SkFILEStream::getMemoryBase() { |
| 297 if (NULL == fData.get()) { |
| 298 return NULL; |
| 299 } |
| 300 return fData->data(); |
270 } | 301 } |
271 | 302 |
272 /////////////////////////////////////////////////////////////////////////////// | 303 /////////////////////////////////////////////////////////////////////////////// |
273 | 304 |
274 static SkData* newFromParams(const void* src, size_t size, bool copyData) { | 305 static SkData* newFromParams(const void* src, size_t size, bool copyData) { |
275 if (copyData) { | 306 if (copyData) { |
276 return SkData::NewWithCopy(src, size); | 307 return SkData::NewWithCopy(src, size); |
277 } else { | 308 } else { |
278 return SkData::NewWithProc(src, size, NULL, NULL); | 309 return SkData::NewWithProc(src, size, NULL, NULL); |
279 } | 310 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 fData->ref(); | 365 fData->ref(); |
335 } | 366 } |
336 return data; | 367 return data; |
337 } | 368 } |
338 | 369 |
339 void SkMemoryStream::skipToAlign4() { | 370 void SkMemoryStream::skipToAlign4() { |
340 // cast to remove unary-minus warning | 371 // cast to remove unary-minus warning |
341 fOffset += -(int)fOffset & 0x03; | 372 fOffset += -(int)fOffset & 0x03; |
342 } | 373 } |
343 | 374 |
344 bool SkMemoryStream::rewind() { | |
345 fOffset = 0; | |
346 return true; | |
347 } | |
348 | |
349 size_t SkMemoryStream::read(void* buffer, size_t size) { | 375 size_t SkMemoryStream::read(void* buffer, size_t size) { |
350 size_t dataSize = fData->size(); | 376 size_t dataSize = fData->size(); |
351 | 377 |
352 if (buffer == NULL && size == 0) // special signature, they want the tota
l size | |
353 return dataSize; | |
354 | |
355 // if buffer is NULL, seek ahead by size | |
356 | |
357 if (size == 0) { | |
358 return 0; | |
359 } | |
360 if (size > dataSize - fOffset) { | 378 if (size > dataSize - fOffset) { |
361 size = dataSize - fOffset; | 379 size = dataSize - fOffset; |
362 } | 380 } |
363 if (buffer) { | 381 if (buffer) { |
364 memcpy(buffer, fData->bytes() + fOffset, size); | 382 memcpy(buffer, fData->bytes() + fOffset, size); |
365 } | 383 } |
366 fOffset += size; | 384 fOffset += size; |
367 return size; | 385 return size; |
368 } | 386 } |
369 | 387 |
| 388 bool SkMemoryStream::atEnd() const { |
| 389 return fOffset == fData->size(); |
| 390 } |
| 391 |
| 392 bool SkMemoryStream::rewind() { |
| 393 fOffset = 0; |
| 394 return true; |
| 395 } |
| 396 |
| 397 SkMemoryStream* SkMemoryStream::duplicate() const { |
| 398 return SkNEW_ARGS(SkMemoryStream, (fData)); |
| 399 } |
| 400 |
| 401 size_t SkMemoryStream::getPosition() const { |
| 402 return fOffset; |
| 403 } |
| 404 |
| 405 bool SkMemoryStream::seek(size_t position) { |
| 406 fOffset = position > fData->size() |
| 407 ? fData->size() |
| 408 : position; |
| 409 return true; |
| 410 } |
| 411 |
| 412 bool SkMemoryStream::move(long offset) { |
| 413 return this->seek(fOffset + offset); |
| 414 } |
| 415 |
| 416 SkMemoryStream* SkMemoryStream::fork() const { |
| 417 SkAutoTUnref<SkMemoryStream> that(this->duplicate()); |
| 418 that->seek(fOffset); |
| 419 return that.detach(); |
| 420 } |
| 421 |
| 422 size_t SkMemoryStream::getLength() const { |
| 423 return fData->size(); |
| 424 } |
| 425 |
370 const void* SkMemoryStream::getMemoryBase() { | 426 const void* SkMemoryStream::getMemoryBase() { |
371 return fData->data(); | 427 return fData->data(); |
372 } | 428 } |
373 | 429 |
374 const void* SkMemoryStream::getAtPos() { | 430 const void* SkMemoryStream::getAtPos() { |
375 return fData->bytes() + fOffset; | 431 return fData->bytes() + fOffset; |
376 } | 432 } |
377 | 433 |
378 size_t SkMemoryStream::seek(size_t offset) { | |
379 if (offset > fData->size()) { | |
380 offset = fData->size(); | |
381 } | |
382 fOffset = offset; | |
383 return offset; | |
384 } | |
385 | |
386 /////////////////////////////////////////////////////////////////////////////// | |
387 | |
388 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize) | |
389 : fProxy(proxy) | |
390 { | |
391 SkASSERT(proxy != NULL); | |
392 proxy->ref(); | |
393 this->init(NULL, bufferSize); | |
394 } | |
395 | |
396 SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize) | |
397 : fProxy(proxy) | |
398 { | |
399 SkASSERT(proxy != NULL); | |
400 SkASSERT(buffer == NULL || bufferSize != 0); // init(addr, 0) makes no se
nse, we must know how big their buffer is | |
401 proxy->ref(); | |
402 this->init(buffer, bufferSize); | |
403 } | |
404 | |
405 void SkBufferStream::init(void* buffer, size_t bufferSize) | |
406 { | |
407 if (bufferSize == 0) | |
408 bufferSize = kDefaultBufferSize; | |
409 | |
410 fOrigBufferSize = bufferSize; | |
411 fBufferSize = bufferSize; | |
412 fBufferOffset = bufferSize; // to trigger a reload on the first read() | |
413 | |
414 if (buffer == NULL) | |
415 { | |
416 fBuffer = (char*)sk_malloc_throw(fBufferSize); | |
417 fWeOwnTheBuffer = true; | |
418 } | |
419 else | |
420 { | |
421 fBuffer = (char*)buffer; | |
422 fWeOwnTheBuffer = false; | |
423 } | |
424 } | |
425 | |
426 SkBufferStream::~SkBufferStream() | |
427 { | |
428 fProxy->unref(); | |
429 if (fWeOwnTheBuffer) | |
430 sk_free(fBuffer); | |
431 } | |
432 | |
433 bool SkBufferStream::rewind() | |
434 { | |
435 fBufferOffset = fBufferSize = fOrigBufferSize; | |
436 return fProxy->rewind(); | |
437 } | |
438 | |
439 const char* SkBufferStream::getFileName() | |
440 { | |
441 return fProxy->getFileName(); | |
442 } | |
443 | |
444 #ifdef SK_DEBUG | |
445 // #define SK_TRACE_BUFFERSTREAM | |
446 #endif | |
447 | |
448 size_t SkBufferStream::read(void* buffer, size_t size) { | |
449 #ifdef SK_TRACE_BUFFERSTREAM | |
450 SkDebugf("Request %d", size); | |
451 #endif | |
452 | |
453 if (buffer == NULL && size == 0) { | |
454 return fProxy->read(buffer, size); // requesting total size | |
455 } | |
456 | |
457 if (0 == size) { | |
458 return 0; | |
459 } | |
460 | |
461 // skip size bytes | |
462 if (NULL == buffer) { | |
463 size_t remaining = fBufferSize - fBufferOffset; | |
464 if (remaining >= size) { | |
465 fBufferOffset += size; | |
466 return size; | |
467 } | |
468 // if we get here, we are being asked to skip beyond our current buffer | |
469 // so reset our offset to force a read next time, and skip the diff | |
470 // in our proxy | |
471 fBufferOffset = fOrigBufferSize; | |
472 return remaining + fProxy->read(NULL, size - remaining); | |
473 } | |
474 | |
475 size_t s = size; | |
476 size_t actuallyRead = 0; | |
477 | |
478 // flush what we can from our fBuffer | |
479 if (fBufferOffset < fBufferSize) | |
480 { | |
481 if (s > fBufferSize - fBufferOffset) | |
482 s = fBufferSize - fBufferOffset; | |
483 memcpy(buffer, fBuffer + fBufferOffset, s); | |
484 #ifdef SK_TRACE_BUFFERSTREAM | |
485 SkDebugf(" flush %d", s); | |
486 #endif | |
487 size -= s; | |
488 fBufferOffset += s; | |
489 buffer = (char*)buffer + s; | |
490 actuallyRead = s; | |
491 } | |
492 | |
493 // check if there is more to read | |
494 if (size) | |
495 { | |
496 SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer | |
497 | |
498 if (size < fBufferSize) // lets try to read more than the request | |
499 { | |
500 s = fProxy->read(fBuffer, fBufferSize); | |
501 #ifdef SK_TRACE_BUFFERSTREAM | |
502 SkDebugf(" read %d into fBuffer", s); | |
503 #endif | |
504 if (size > s) // they asked for too much | |
505 size = s; | |
506 if (size) | |
507 { | |
508 memcpy(buffer, fBuffer, size); | |
509 actuallyRead += size; | |
510 #ifdef SK_TRACE_BUFFERSTREAM | |
511 SkDebugf(" memcpy %d into dst", size); | |
512 #endif | |
513 } | |
514 | |
515 fBufferOffset = size; | |
516 fBufferSize = s; // record the (possibly smaller) size for th
e buffer | |
517 } | |
518 else // just do a direct read | |
519 { | |
520 actuallyRead += fProxy->read(buffer, size); | |
521 #ifdef SK_TRACE_BUFFERSTREAM | |
522 SkDebugf(" direct read %d", size); | |
523 #endif | |
524 } | |
525 } | |
526 #ifdef SK_TRACE_BUFFERSTREAM | |
527 SkDebugf("\n"); | |
528 #endif | |
529 return actuallyRead; | |
530 } | |
531 | |
532 const void* SkBufferStream::getMemoryBase() | |
533 { | |
534 return fProxy->getMemoryBase(); | |
535 } | |
536 | |
537 ////////////////////////////////////////////////////////////////////////////////
///////////////////////// | 434 ////////////////////////////////////////////////////////////////////////////////
///////////////////////// |
538 ////////////////////////////////////////////////////////////////////////////////
///////////////////////// | 435 ////////////////////////////////////////////////////////////////////////////////
///////////////////////// |
539 | 436 |
540 SkFILEWStream::SkFILEWStream(const char path[]) | 437 SkFILEWStream::SkFILEWStream(const char path[]) |
541 { | 438 { |
542 fFILE = sk_fopen(path, kWrite_SkFILE_Flag); | 439 fFILE = sk_fopen(path, kWrite_SkFILE_Flag); |
543 } | 440 } |
544 | 441 |
545 SkFILEWStream::~SkFILEWStream() | 442 SkFILEWStream::~SkFILEWStream() |
546 { | 443 { |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag); | 690 SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag); |
794 if (NULL == file) { | 691 if (NULL == file) { |
795 return NULL; | 692 return NULL; |
796 } | 693 } |
797 | 694 |
798 SkData* data = SkData::NewFromFILE(file); | 695 SkData* data = SkData::NewFromFILE(file); |
799 sk_fclose(file); | 696 sk_fclose(file); |
800 return data; | 697 return data; |
801 } | 698 } |
802 | 699 |
803 SkStream* SkStream::NewFromFile(const char path[]) { | 700 SkStreamAsset* SkStream::NewFromFile(const char path[]) { |
804 SkAutoTUnref<SkData> data(mmap_filename(path)); | 701 SkAutoTUnref<SkData> data(mmap_filename(path)); |
805 if (data.get()) { | 702 if (data.get()) { |
806 return SkNEW_ARGS(SkMemoryStream, (data.get())); | 703 return SkNEW_ARGS(SkMemoryStream, (data.get())); |
807 } | 704 } |
808 | 705 |
809 // If we get here, then our attempt at using mmap failed, so try normal | 706 // If we get here, then our attempt at using mmap failed, so try normal |
810 // file access. | 707 // file access. |
811 SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path)); | 708 SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path)); |
812 if (!stream->isValid()) { | 709 if (!stream->isValid()) { |
813 stream->unref(); | 710 stream->unref(); |
814 stream = NULL; | 711 stream = NULL; |
815 } | 712 } |
816 return stream; | 713 return stream; |
817 } | 714 } |
OLD | NEW |