1 /* libs/graphics/images/SkStream.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include "SkStream.h"
19 #include "SkFixed.h"
20 #include "SkString.h"
21 #include "SkOSFile.h"
22
~SkStream()23 SkStream::~SkStream() {}
24
getFileName()25 const char* SkStream::getFileName()
26 {
27 // override in subclass if you represent a file
28 return NULL;
29 }
30
getMemoryBase()31 const void* SkStream::getMemoryBase()
32 {
33 // override in subclass if you represent a memory block
34 return NULL;
35 }
36
skip(size_t size)37 size_t SkStream::skip(size_t size)
38 {
39 /* Check for size == 0, and just return 0. If we passed that
40 to read(), it would interpret it as a request for the entire
41 size of the stream.
42 */
43 return size ? this->read(NULL, size) : 0;
44 }
45
readS8()46 int8_t SkStream::readS8() {
47 int8_t value;
48 SkDEBUGCODE(size_t len =) this->read(&value, 1);
49 SkASSERT(1 == len);
50 return value;
51 }
52
readS16()53 int16_t SkStream::readS16() {
54 int16_t value;
55 SkDEBUGCODE(size_t len =) this->read(&value, 2);
56 SkASSERT(2 == len);
57 return value;
58 }
59
readS32()60 int32_t SkStream::readS32() {
61 int32_t value;
62 SkDEBUGCODE(size_t len =) this->read(&value, 4);
63 SkASSERT(4 == len);
64 return value;
65 }
66
readScalar()67 SkScalar SkStream::readScalar() {
68 SkScalar value;
69 SkDEBUGCODE(size_t len =) this->read(&value, sizeof(SkScalar));
70 SkASSERT(sizeof(SkScalar) == len);
71 return value;
72 }
73
readPackedUInt()74 size_t SkStream::readPackedUInt() {
75 uint8_t byte;
76 if (!this->read(&byte, 1)) {
77 return 0;
78 }
79 if (byte != 0xFF) {
80 return byte;
81 }
82
83 uint16_t word;
84 if (!this->read(&word, 2)) {
85 return 0;
86 }
87 if (word != 0xFFFF) {
88 return word;
89 }
90
91 uint32_t quad;
92 if (!this->read(&quad, 4)) {
93 return 0;
94 }
95 return quad;
96 }
97
98 //////////////////////////////////////////////////////////////////////////////////////
99
~SkWStream()100 SkWStream::~SkWStream()
101 {
102 }
103
newline()104 void SkWStream::newline()
105 {
106 this->write("\n", 1);
107 }
108
flush()109 void SkWStream::flush()
110 {
111 }
112
writeText(const char text[])113 bool SkWStream::writeText(const char text[])
114 {
115 SkASSERT(text);
116 return this->write(text, strlen(text));
117 }
118
writeDecAsText(int32_t dec)119 bool SkWStream::writeDecAsText(int32_t dec)
120 {
121 SkString tmp;
122 tmp.appendS32(dec);
123 return this->write(tmp.c_str(), tmp.size());
124 }
125
writeHexAsText(uint32_t hex,int digits)126 bool SkWStream::writeHexAsText(uint32_t hex, int digits)
127 {
128 SkString tmp;
129 tmp.appendHex(hex, digits);
130 return this->write(tmp.c_str(), tmp.size());
131 }
132
writeScalarAsText(SkScalar value)133 bool SkWStream::writeScalarAsText(SkScalar value)
134 {
135 SkString tmp;
136 tmp.appendScalar(value);
137 return this->write(tmp.c_str(), tmp.size());
138 }
139
write8(U8CPU value)140 bool SkWStream::write8(U8CPU value) {
141 uint8_t v = SkToU8(value);
142 return this->write(&v, 1);
143 }
144
write16(U16CPU value)145 bool SkWStream::write16(U16CPU value) {
146 uint16_t v = SkToU16(value);
147 return this->write(&v, 2);
148 }
149
write32(uint32_t value)150 bool SkWStream::write32(uint32_t value) {
151 return this->write(&value, 4);
152 }
153
writeScalar(SkScalar value)154 bool SkWStream::writeScalar(SkScalar value) {
155 return this->write(&value, sizeof(value));
156 }
157
writePackedUInt(size_t value)158 bool SkWStream::writePackedUInt(size_t value) {
159 if (value < 0xFF) {
160 return this->write8(value);
161 } else if (value < 0xFFFF) {
162 return this->write8(0xFF) && this->write16(value);
163 } else {
164 return this->write16(0xFFFF) && this->write32(value);
165 }
166 }
167
writeStream(SkStream * stream,size_t length)168 bool SkWStream::writeStream(SkStream* stream, size_t length) {
169 char scratch[1024];
170 const size_t MAX = sizeof(scratch);
171
172 while (length != 0) {
173 size_t n = length;
174 if (n > MAX) {
175 n = MAX;
176 }
177 stream->read(scratch, n);
178 if (!this->write(scratch, n)) {
179 return false;
180 }
181 length -= n;
182 }
183 return true;
184 }
185
186 ////////////////////////////////////////////////////////////////////////////
187
SkFILEStream(const char file[])188 SkFILEStream::SkFILEStream(const char file[]) : fName(file)
189 {
190 fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
191 }
192
~SkFILEStream()193 SkFILEStream::~SkFILEStream()
194 {
195 if (fFILE)
196 sk_fclose(fFILE);
197 }
198
setPath(const char path[])199 void SkFILEStream::setPath(const char path[])
200 {
201 fName.set(path);
202 if (fFILE)
203 {
204 sk_fclose(fFILE);
205 fFILE = NULL;
206 }
207 if (path)
208 fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
209 }
210
getFileName()211 const char* SkFILEStream::getFileName()
212 {
213 return fName.c_str();
214 }
215
rewind()216 bool SkFILEStream::rewind()
217 {
218 if (fFILE)
219 {
220 if (sk_frewind(fFILE))
221 return true;
222 // we hit an error
223 sk_fclose(fFILE);
224 fFILE = NULL;
225 }
226 return false;
227 }
228
read(void * buffer,size_t size)229 size_t SkFILEStream::read(void* buffer, size_t size)
230 {
231 if (fFILE)
232 {
233 if (buffer == NULL && size == 0) // special signature, they want the total size
234 return sk_fgetsize(fFILE);
235 else
236 return sk_fread(buffer, size, fFILE);
237 }
238 return 0;
239 }
240
241 ////////////////////////////////////////////////////////////////////////////
242
SkMemoryStream()243 SkMemoryStream::SkMemoryStream()
244 {
245 fWeOwnTheData = false;
246 this->setMemory(NULL, 0);
247 }
248
SkMemoryStream(size_t size)249 SkMemoryStream::SkMemoryStream(size_t size) {
250 fWeOwnTheData = true;
251 fOffset = 0;
252 fSize = size;
253 fSrc = sk_malloc_throw(size);
254 }
255
SkMemoryStream(const void * src,size_t size,bool copyData)256 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData)
257 {
258 fWeOwnTheData = false;
259 this->setMemory(src, size, copyData);
260 }
261
~SkMemoryStream()262 SkMemoryStream::~SkMemoryStream()
263 {
264 if (fWeOwnTheData)
265 sk_free((void*)fSrc);
266 }
267
setMemoryOwned(const void * src,size_t size)268 void SkMemoryStream::setMemoryOwned(const void* src, size_t size)
269 {
270 if (fWeOwnTheData)
271 sk_free((void*)fSrc);
272
273 fSize = size;
274 fOffset = 0;
275 fWeOwnTheData = true;
276
277 fSrc = src;
278 }
279
setMemory(const void * src,size_t size,bool copyData)280 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData)
281 {
282 if (fWeOwnTheData)
283 sk_free((void*)fSrc);
284
285 fSize = size;
286 fOffset = 0;
287 fWeOwnTheData = copyData;
288
289 if (copyData)
290 {
291 void* copy = sk_malloc_throw(size);
292 memcpy(copy, src, size);
293 src = copy;
294 }
295 fSrc = src;
296 }
297
skipToAlign4()298 void SkMemoryStream::skipToAlign4()
299 {
300 // cast to remove unary-minus warning
301 fOffset += -(int)fOffset & 0x03;
302 }
303
rewind()304 bool SkMemoryStream::rewind()
305 {
306 fOffset = 0;
307 return true;
308 }
309
read(void * buffer,size_t size)310 size_t SkMemoryStream::read(void* buffer, size_t size)
311 {
312 if (buffer == NULL && size == 0) // special signature, they want the total size
313 return fSize;
314
315 // if buffer is NULL, seek ahead by size
316
317 if (size == 0)
318 return 0;
319 if (size > fSize - fOffset)
320 size = fSize - fOffset;
321 if (buffer) {
322 memcpy(buffer, (const char*)fSrc + fOffset, size);
323 }
324 fOffset += size;
325 return size;
326 }
327
getMemoryBase()328 const void* SkMemoryStream::getMemoryBase()
329 {
330 return fSrc;
331 }
332
getAtPos()333 const void* SkMemoryStream::getAtPos()
334 {
335 return (const char*)fSrc + fOffset;
336 }
337
seek(size_t offset)338 size_t SkMemoryStream::seek(size_t offset)
339 {
340 if (offset > fSize)
341 offset = fSize;
342 fOffset = offset;
343 return offset;
344 }
345
346 /////////////////////////////////////////////////////////////////////////////////////////////////////////
347
SkBufferStream(SkStream * proxy,size_t bufferSize)348 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
349 : fProxy(proxy)
350 {
351 SkASSERT(proxy != NULL);
352 proxy->ref();
353 this->init(NULL, bufferSize);
354 }
355
SkBufferStream(SkStream * proxy,void * buffer,size_t bufferSize)356 SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize)
357 : fProxy(proxy)
358 {
359 SkASSERT(proxy != NULL);
360 SkASSERT(buffer == NULL || bufferSize != 0); // init(addr, 0) makes no sense, we must know how big their buffer is
361 proxy->ref();
362 this->init(buffer, bufferSize);
363 }
364
init(void * buffer,size_t bufferSize)365 void SkBufferStream::init(void* buffer, size_t bufferSize)
366 {
367 if (bufferSize == 0)
368 bufferSize = kDefaultBufferSize;
369
370 fOrigBufferSize = bufferSize;
371 fBufferSize = bufferSize;
372 fBufferOffset = bufferSize; // to trigger a reload on the first read()
373
374 if (buffer == NULL)
375 {
376 fBuffer = (char*)sk_malloc_throw(fBufferSize);
377 fWeOwnTheBuffer = true;
378 }
379 else
380 {
381 fBuffer = (char*)buffer;
382 fWeOwnTheBuffer = false;
383 }
384 }
385
~SkBufferStream()386 SkBufferStream::~SkBufferStream()
387 {
388 fProxy->unref();
389 if (fWeOwnTheBuffer)
390 sk_free(fBuffer);
391 }
392
rewind()393 bool SkBufferStream::rewind()
394 {
395 fBufferOffset = fBufferSize = fOrigBufferSize;
396 return fProxy->rewind();
397 }
398
getFileName()399 const char* SkBufferStream::getFileName()
400 {
401 return fProxy->getFileName();
402 }
403
404 #ifdef SK_DEBUG
405 // #define SK_TRACE_BUFFERSTREAM
406 #endif
407
read(void * buffer,size_t size)408 size_t SkBufferStream::read(void* buffer, size_t size) {
409 #ifdef SK_TRACE_BUFFERSTREAM
410 SkDebugf("Request %d", size);
411 #endif
412
413 if (buffer == NULL && size == 0) {
414 return fProxy->read(buffer, size); // requesting total size
415 }
416
417 if (0 == size) {
418 return 0;
419 }
420
421 // skip size bytes
422 if (NULL == buffer) {
423 size_t remaining = fBufferSize - fBufferOffset;
424 if (remaining >= size) {
425 fBufferOffset += size;
426 return size;
427 }
428 // if we get here, we are being asked to skip beyond our current buffer
429 // so reset our offset to force a read next time, and skip the diff
430 // in our proxy
431 fBufferOffset = fOrigBufferSize;
432 return remaining + fProxy->read(NULL, size - remaining);
433 }
434
435 size_t s = size;
436 size_t actuallyRead = 0;
437
438 // flush what we can from our fBuffer
439 if (fBufferOffset < fBufferSize)
440 {
441 if (s > fBufferSize - fBufferOffset)
442 s = fBufferSize - fBufferOffset;
443 memcpy(buffer, fBuffer + fBufferOffset, s);
444 #ifdef SK_TRACE_BUFFERSTREAM
445 SkDebugf(" flush %d", s);
446 #endif
447 size -= s;
448 fBufferOffset += s;
449 buffer = (char*)buffer + s;
450 actuallyRead = s;
451 }
452
453 // check if there is more to read
454 if (size)
455 {
456 SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer
457
458 if (size < fBufferSize) // lets try to read more than the request
459 {
460 s = fProxy->read(fBuffer, fBufferSize);
461 #ifdef SK_TRACE_BUFFERSTREAM
462 SkDebugf(" read %d into fBuffer", s);
463 #endif
464 if (size > s) // they asked for too much
465 size = s;
466 if (size)
467 {
468 memcpy(buffer, fBuffer, size);
469 actuallyRead += size;
470 #ifdef SK_TRACE_BUFFERSTREAM
471 SkDebugf(" memcpy %d into dst", size);
472 #endif
473 }
474
475 fBufferOffset = size;
476 fBufferSize = s; // record the (possibly smaller) size for the buffer
477 }
478 else // just do a direct read
479 {
480 actuallyRead += fProxy->read(buffer, size);
481 #ifdef SK_TRACE_BUFFERSTREAM
482 SkDebugf(" direct read %d", size);
483 #endif
484 }
485 }
486 #ifdef SK_TRACE_BUFFERSTREAM
487 SkDebugf("\n");
488 #endif
489 return actuallyRead;
490 }
491
getMemoryBase()492 const void* SkBufferStream::getMemoryBase()
493 {
494 return fProxy->getMemoryBase();
495 }
496
497 /////////////////////////////////////////////////////////////////////////////////////////////////////////
498 /////////////////////////////////////////////////////////////////////////////////////////////////////////
499
SkFILEWStream(const char path[])500 SkFILEWStream::SkFILEWStream(const char path[])
501 {
502 fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
503 }
504
~SkFILEWStream()505 SkFILEWStream::~SkFILEWStream()
506 {
507 if (fFILE)
508 sk_fclose(fFILE);
509 }
510
write(const void * buffer,size_t size)511 bool SkFILEWStream::write(const void* buffer, size_t size)
512 {
513 if (fFILE == NULL)
514 return false;
515
516 if (sk_fwrite(buffer, size, fFILE) != size)
517 {
518 SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
519 sk_fclose(fFILE);
520 fFILE = NULL;
521 return false;
522 }
523 return true;
524 }
525
flush()526 void SkFILEWStream::flush()
527 {
528 if (fFILE)
529 sk_fflush(fFILE);
530 }
531
532 ////////////////////////////////////////////////////////////////////////
533
SkMemoryWStream(void * buffer,size_t size)534 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
535 : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
536 {
537 }
538
write(const void * buffer,size_t size)539 bool SkMemoryWStream::write(const void* buffer, size_t size)
540 {
541 size = SkMin32(size, fMaxLength - fBytesWritten);
542 if (size > 0)
543 {
544 memcpy(fBuffer + fBytesWritten, buffer, size);
545 fBytesWritten += size;
546 return true;
547 }
548 return false;
549 }
550
551 ////////////////////////////////////////////////////////////////////////
552
553 #define SkDynamicMemoryWStream_MinBlockSize 256
554
555 struct SkDynamicMemoryWStream::Block {
556 Block* fNext;
557 char* fCurr;
558 char* fStop;
559
startSkDynamicMemoryWStream::Block560 const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block561 char* start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block562 size_t avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block563 size_t written() const { return fCurr - this->start(); }
564
initSkDynamicMemoryWStream::Block565 void init(size_t size)
566 {
567 fNext = NULL;
568 fCurr = this->start();
569 fStop = this->start() + size;
570 }
571
appendSkDynamicMemoryWStream::Block572 const void* append(const void* data, size_t size)
573 {
574 SkASSERT((size_t)(fStop - fCurr) >= size);
575 memcpy(fCurr, data, size);
576 fCurr += size;
577 return (const void*)((const char*)data + size);
578 }
579 };
580
SkDynamicMemoryWStream()581 SkDynamicMemoryWStream::SkDynamicMemoryWStream() : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopyToCache(NULL)
582 {
583 }
584
~SkDynamicMemoryWStream()585 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
586 {
587 reset();
588 }
589
detach()590 const char* SkDynamicMemoryWStream::detach()
591 {
592 const char* result = getStream();
593 fCopyToCache = NULL;
594 return result;
595 }
596
reset()597 void SkDynamicMemoryWStream::reset()
598 {
599 sk_free(fCopyToCache);
600 Block* block = fHead;
601
602 while (block != NULL) {
603 Block* next = block->fNext;
604 sk_free(block);
605 block = next;
606 }
607 fHead = fTail = NULL;
608 fBytesWritten = 0;
609 fCopyToCache = NULL;
610 }
611
write(const void * buffer,size_t count)612 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
613 {
614 if (count > 0) {
615
616 if (fCopyToCache) {
617 sk_free(fCopyToCache);
618 fCopyToCache = NULL;
619 }
620 fBytesWritten += count;
621
622 size_t size;
623
624 if (fTail != NULL && fTail->avail() > 0) {
625 size = SkMin32(fTail->avail(), count);
626 buffer = fTail->append(buffer, size);
627 SkASSERT(count >= size);
628 count -= size;
629 if (count == 0)
630 return true;
631 }
632
633 size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
634 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
635 block->init(size);
636 block->append(buffer, count);
637
638 if (fTail != NULL)
639 fTail->fNext = block;
640 else
641 fHead = fTail = block;
642 fTail = block;
643 }
644 return true;
645 }
646
write(const void * buffer,size_t offset,size_t count)647 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
648 {
649 if (offset + count > fBytesWritten)
650 return false; // test does not partially modify
651 Block* block = fHead;
652 while (block != NULL) {
653 size_t size = block->written();
654 if (offset < size) {
655 size_t part = offset + count > size ? size - offset : count;
656 memcpy(block->start() + offset, buffer, part);
657 if (count <= part)
658 return true;
659 count -= part;
660 buffer = (const void*) ((char* ) buffer + part);
661 }
662 offset = offset > size ? offset - size : 0;
663 block = block->fNext;
664 }
665 return false;
666 }
667
read(void * buffer,size_t offset,size_t count)668 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
669 {
670 if (offset + count > fBytesWritten)
671 return false; // test does not partially modify
672 Block* block = fHead;
673 while (block != NULL) {
674 size_t size = block->written();
675 if (offset < size) {
676 size_t part = offset + count > size ? size - offset : count;
677 memcpy(buffer, block->start() + offset, part);
678 if (count <= part)
679 return true;
680 count -= part;
681 buffer = (void*) ((char* ) buffer + part);
682 }
683 offset = offset > size ? offset - size : 0;
684 block = block->fNext;
685 }
686 return false;
687 }
688
copyTo(void * dst) const689 void SkDynamicMemoryWStream::copyTo(void* dst) const
690 {
691 Block* block = fHead;
692
693 while (block != NULL) {
694 size_t size = block->written();
695 memcpy(dst, block->start(), size);
696 dst = (void*)((char*)dst + size);
697 block = block->fNext;
698 }
699 }
700
getStream() const701 const char* SkDynamicMemoryWStream::getStream() const
702 {
703 if (fCopyToCache == NULL) {
704 fCopyToCache = (char*)sk_malloc_throw(fBytesWritten);
705 this->copyTo(fCopyToCache);
706 }
707 return fCopyToCache;
708 }
709
padToAlign4()710 void SkDynamicMemoryWStream::padToAlign4()
711 {
712 // cast to remove unary-minus warning
713 int padBytes = -(int)fBytesWritten & 0x03;
714 if (padBytes == 0)
715 return;
716 int zero = 0;
717 write(&zero, padBytes);
718 }
719
720 /////////////////////////////////////////////////////////////////////////////////////////////////////////
721
newline()722 void SkDebugWStream::newline()
723 {
724 #ifdef SK_DEBUG
725 SkDebugf("\n");
726 #endif
727 }
728
write(const void * buffer,size_t size)729 bool SkDebugWStream::write(const void* buffer, size_t size)
730 {
731 #ifdef SK_DEBUG
732 char* s = new char[size+1];
733 memcpy(s, buffer, size);
734 s[size] = 0;
735 SkDebugf("%s", s);
736 delete[] s;
737 #endif
738 return true;
739 }
740
741