OLD | NEW |
| (Empty) |
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 | |
23 SkStream::~SkStream() {} | |
24 | |
25 const char* SkStream::getFileName() | |
26 { | |
27 // override in subclass if you represent a file | |
28 return NULL; | |
29 } | |
30 | |
31 const void* SkStream::getMemoryBase() | |
32 { | |
33 // override in subclass if you represent a memory block | |
34 return NULL; | |
35 } | |
36 | |
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 | |
46 int8_t SkStream::readS8() { | |
47 int8_t value; | |
48 size_t len = this->read(&value, 1); | |
49 SkASSERT(1 == len); | |
50 return value; | |
51 } | |
52 | |
53 int16_t SkStream::readS16() { | |
54 int16_t value; | |
55 size_t len = this->read(&value, 2); | |
56 SkASSERT(2 == len); | |
57 return value; | |
58 } | |
59 | |
60 int32_t SkStream::readS32() { | |
61 int32_t value; | |
62 size_t len = this->read(&value, 4); | |
63 SkASSERT(4 == len); | |
64 return value; | |
65 } | |
66 | |
67 SkScalar SkStream::readScalar() { | |
68 SkScalar value; | |
69 size_t len = this->read(&value, sizeof(SkScalar)); | |
70 SkASSERT(sizeof(SkScalar) == len); | |
71 return value; | |
72 } | |
73 | |
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 | |
100 SkWStream::~SkWStream() | |
101 { | |
102 } | |
103 | |
104 void SkWStream::newline() | |
105 { | |
106 this->write("\n", 1); | |
107 } | |
108 | |
109 void SkWStream::flush() | |
110 { | |
111 } | |
112 | |
113 bool SkWStream::writeText(const char text[]) | |
114 { | |
115 SkASSERT(text); | |
116 return this->write(text, strlen(text)); | |
117 } | |
118 | |
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 | |
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 | |
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 | |
140 bool SkWStream::write8(U8CPU value) { | |
141 uint8_t v = SkToU8(value); | |
142 return this->write(&v, 1); | |
143 } | |
144 | |
145 bool SkWStream::write16(U16CPU value) { | |
146 uint16_t v = SkToU16(value); | |
147 return this->write(&v, 2); | |
148 } | |
149 | |
150 bool SkWStream::write32(uint32_t value) { | |
151 return this->write(&value, 4); | |
152 } | |
153 | |
154 bool SkWStream::writeScalar(SkScalar value) { | |
155 return this->write(&value, sizeof(value)); | |
156 } | |
157 | |
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 | |
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 | |
188 SkFILEStream::SkFILEStream(const char file[]) : fName(file) | |
189 { | |
190 #ifdef SK_BUILD_FOR_BREW | |
191 if (SkStrEndsWith(fName.c_str(), ".xml")) | |
192 fName.writable_str()[fName.size()-3] = 'b'; | |
193 #endif | |
194 | |
195 fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL; | |
196 } | |
197 | |
198 SkFILEStream::~SkFILEStream() | |
199 { | |
200 if (fFILE) | |
201 sk_fclose(fFILE); | |
202 } | |
203 | |
204 void SkFILEStream::setPath(const char path[]) | |
205 { | |
206 fName.set(path); | |
207 #ifdef SK_BUILD_FOR_BREW | |
208 if (SkStrEndsWith(fName.c_str(), ".xml")) | |
209 fName.writable_str()[fName.size()-3] = 'b'; | |
210 #endif | |
211 | |
212 if (fFILE) | |
213 { | |
214 sk_fclose(fFILE); | |
215 fFILE = NULL; | |
216 } | |
217 if (path) | |
218 fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag); | |
219 } | |
220 | |
221 const char* SkFILEStream::getFileName() | |
222 { | |
223 return fName.c_str(); | |
224 } | |
225 | |
226 bool SkFILEStream::rewind() | |
227 { | |
228 if (fFILE) | |
229 { | |
230 if (sk_frewind(fFILE)) | |
231 return true; | |
232 // we hit an error | |
233 sk_fclose(fFILE); | |
234 fFILE = NULL; | |
235 } | |
236 return false; | |
237 } | |
238 | |
239 size_t SkFILEStream::read(void* buffer, size_t size) | |
240 { | |
241 if (fFILE) | |
242 { | |
243 if (buffer == NULL && size == 0) // special signature, they want the
total size | |
244 return sk_fgetsize(fFILE); | |
245 else | |
246 return sk_fread(buffer, size, fFILE); | |
247 } | |
248 return 0; | |
249 } | |
250 | |
251 //////////////////////////////////////////////////////////////////////////// | |
252 | |
253 SkMemoryStream::SkMemoryStream() | |
254 { | |
255 fWeOwnTheData = false; | |
256 this->setMemory(NULL, 0); | |
257 } | |
258 | |
259 SkMemoryStream::SkMemoryStream(size_t size) { | |
260 fWeOwnTheData = true; | |
261 fOffset = 0; | |
262 fSize = size; | |
263 fSrc = sk_malloc_throw(size); | |
264 } | |
265 | |
266 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData) | |
267 { | |
268 fWeOwnTheData = false; | |
269 this->setMemory(src, size, copyData); | |
270 } | |
271 | |
272 SkMemoryStream::~SkMemoryStream() | |
273 { | |
274 if (fWeOwnTheData) | |
275 sk_free((void*)fSrc); | |
276 } | |
277 | |
278 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData) | |
279 { | |
280 if (fWeOwnTheData) | |
281 sk_free((void*)fSrc); | |
282 | |
283 fSize = size; | |
284 fOffset = 0; | |
285 fWeOwnTheData = copyData; | |
286 | |
287 if (copyData) | |
288 { | |
289 void* copy = sk_malloc_throw(size); | |
290 memcpy(copy, src, size); | |
291 src = copy; | |
292 } | |
293 fSrc = src; | |
294 } | |
295 | |
296 void SkMemoryStream::skipToAlign4() | |
297 { | |
298 // cast to remove unary-minus warning | |
299 fOffset += -(int)fOffset & 0x03; | |
300 } | |
301 | |
302 bool SkMemoryStream::rewind() | |
303 { | |
304 fOffset = 0; | |
305 return true; | |
306 } | |
307 | |
308 size_t SkMemoryStream::read(void* buffer, size_t size) | |
309 { | |
310 if (buffer == NULL && size == 0) // special signature, they want the tota
l size | |
311 return fSize; | |
312 | |
313 // if buffer is NULL, seek ahead by size | |
314 | |
315 if (size == 0) | |
316 return 0; | |
317 if (size > fSize - fOffset) | |
318 size = fSize - fOffset; | |
319 if (buffer) { | |
320 memcpy(buffer, (const char*)fSrc + fOffset, size); | |
321 } | |
322 fOffset += size; | |
323 return size; | |
324 } | |
325 | |
326 const void* SkMemoryStream::getMemoryBase() | |
327 { | |
328 return fSrc; | |
329 } | |
330 | |
331 const void* SkMemoryStream::getAtPos() | |
332 { | |
333 return (const char*)fSrc + fOffset; | |
334 } | |
335 | |
336 size_t SkMemoryStream::seek(size_t offset) | |
337 { | |
338 if (offset > fSize) | |
339 offset = fSize; | |
340 fOffset = offset; | |
341 return offset; | |
342 } | |
343 | |
344 ////////////////////////////////////////////////////////////////////////////////
///////////////////////// | |
345 | |
346 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize) | |
347 : fProxy(proxy) | |
348 { | |
349 SkASSERT(proxy != NULL); | |
350 proxy->ref(); | |
351 this->init(NULL, bufferSize); | |
352 } | |
353 | |
354 SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize) | |
355 : fProxy(proxy) | |
356 { | |
357 SkASSERT(proxy != NULL); | |
358 SkASSERT(buffer == NULL || bufferSize != 0); // init(addr, 0) makes no se
nse, we must know how big their buffer is | |
359 proxy->ref(); | |
360 this->init(buffer, bufferSize); | |
361 } | |
362 | |
363 void SkBufferStream::init(void* buffer, size_t bufferSize) | |
364 { | |
365 if (bufferSize == 0) | |
366 bufferSize = kDefaultBufferSize; | |
367 | |
368 fOrigBufferSize = bufferSize; | |
369 fBufferSize = bufferSize; | |
370 fBufferOffset = bufferSize; // to trigger a reload on the first read() | |
371 | |
372 if (buffer == NULL) | |
373 { | |
374 fBuffer = (char*)sk_malloc_throw(fBufferSize); | |
375 fWeOwnTheBuffer = true; | |
376 } | |
377 else | |
378 { | |
379 fBuffer = (char*)buffer; | |
380 fWeOwnTheBuffer = false; | |
381 } | |
382 } | |
383 | |
384 SkBufferStream::~SkBufferStream() | |
385 { | |
386 fProxy->unref(); | |
387 if (fWeOwnTheBuffer) | |
388 sk_free(fBuffer); | |
389 } | |
390 | |
391 bool SkBufferStream::rewind() | |
392 { | |
393 fBufferOffset = fBufferSize = fOrigBufferSize; | |
394 return fProxy->rewind(); | |
395 } | |
396 | |
397 const char* SkBufferStream::getFileName() | |
398 { | |
399 return fProxy->getFileName(); | |
400 } | |
401 | |
402 #ifdef SK_DEBUG | |
403 // #define SK_TRACE_BUFFERSTREAM | |
404 #endif | |
405 | |
406 size_t SkBufferStream::read(void* buffer, size_t size) { | |
407 #ifdef SK_TRACE_BUFFERSTREAM | |
408 SkDebugf("Request %d", size); | |
409 #endif | |
410 | |
411 if (buffer == NULL && size == 0) { | |
412 return fProxy->read(buffer, size); // requesting total size | |
413 } | |
414 | |
415 if (0 == size) { | |
416 return 0; | |
417 } | |
418 | |
419 // skip size bytes | |
420 if (NULL == buffer) { | |
421 size_t remaining = fBufferSize - fBufferOffset; | |
422 if (remaining >= size) { | |
423 fBufferOffset += size; | |
424 return size; | |
425 } | |
426 // if we get here, we are being asked to skip beyond our current buffer | |
427 // so reset our offset to force a read next time, and skip the diff | |
428 // in our proxy | |
429 fBufferOffset = fOrigBufferSize; | |
430 return remaining + fProxy->read(NULL, size - remaining); | |
431 } | |
432 | |
433 size_t s = size; | |
434 size_t actuallyRead = 0; | |
435 | |
436 // flush what we can from our fBuffer | |
437 if (fBufferOffset < fBufferSize) | |
438 { | |
439 if (s > fBufferSize - fBufferOffset) | |
440 s = fBufferSize - fBufferOffset; | |
441 memcpy(buffer, fBuffer + fBufferOffset, s); | |
442 #ifdef SK_TRACE_BUFFERSTREAM | |
443 SkDebugf(" flush %d", s); | |
444 #endif | |
445 size -= s; | |
446 fBufferOffset += s; | |
447 buffer = (char*)buffer + s; | |
448 actuallyRead = s; | |
449 } | |
450 | |
451 // check if there is more to read | |
452 if (size) | |
453 { | |
454 SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer | |
455 | |
456 if (size < fBufferSize) // lets try to read more than the request | |
457 { | |
458 s = fProxy->read(fBuffer, fBufferSize); | |
459 #ifdef SK_TRACE_BUFFERSTREAM | |
460 SkDebugf(" read %d into fBuffer", s); | |
461 #endif | |
462 if (size > s) // they asked for too much | |
463 size = s; | |
464 if (size) | |
465 { | |
466 memcpy(buffer, fBuffer, size); | |
467 actuallyRead += size; | |
468 #ifdef SK_TRACE_BUFFERSTREAM | |
469 SkDebugf(" memcpy %d into dst", size); | |
470 #endif | |
471 } | |
472 | |
473 fBufferOffset = size; | |
474 fBufferSize = s; // record the (possibly smaller) size for th
e buffer | |
475 } | |
476 else // just do a direct read | |
477 { | |
478 actuallyRead += fProxy->read(buffer, size); | |
479 #ifdef SK_TRACE_BUFFERSTREAM | |
480 SkDebugf(" direct read %d", size); | |
481 #endif | |
482 } | |
483 } | |
484 #ifdef SK_TRACE_BUFFERSTREAM | |
485 SkDebugf("\n"); | |
486 #endif | |
487 return actuallyRead; | |
488 } | |
489 | |
490 const void* SkBufferStream::getMemoryBase() | |
491 { | |
492 return fProxy->getMemoryBase(); | |
493 } | |
494 | |
495 ////////////////////////////////////////////////////////////////////////////////
///////////////////////// | |
496 ////////////////////////////////////////////////////////////////////////////////
///////////////////////// | |
497 | |
498 SkFILEWStream::SkFILEWStream(const char path[]) | |
499 { | |
500 fFILE = sk_fopen(path, kWrite_SkFILE_Flag); | |
501 } | |
502 | |
503 SkFILEWStream::~SkFILEWStream() | |
504 { | |
505 if (fFILE) | |
506 sk_fclose(fFILE); | |
507 } | |
508 | |
509 bool SkFILEWStream::write(const void* buffer, size_t size) | |
510 { | |
511 if (fFILE == NULL) | |
512 return false; | |
513 | |
514 if (sk_fwrite(buffer, size, fFILE) != size) | |
515 { | |
516 SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);) | |
517 sk_fclose(fFILE); | |
518 fFILE = NULL; | |
519 return false; | |
520 } | |
521 return true; | |
522 } | |
523 | |
524 void SkFILEWStream::flush() | |
525 { | |
526 if (fFILE) | |
527 sk_fflush(fFILE); | |
528 } | |
529 | |
530 //////////////////////////////////////////////////////////////////////// | |
531 | |
532 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size) | |
533 : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0) | |
534 { | |
535 } | |
536 | |
537 bool SkMemoryWStream::write(const void* buffer, size_t size) | |
538 { | |
539 size = SkMin32(size, fMaxLength - fBytesWritten); | |
540 if (size > 0) | |
541 { | |
542 memcpy(fBuffer + fBytesWritten, buffer, size); | |
543 fBytesWritten += size; | |
544 return true; | |
545 } | |
546 return false; | |
547 } | |
548 | |
549 //////////////////////////////////////////////////////////////////////// | |
550 | |
551 #define SkDynamicMemoryWStream_MinBlockSize 256 | |
552 | |
553 struct SkDynamicMemoryWStream::Block { | |
554 Block* fNext; | |
555 char* fCurr; | |
556 char* fStop; | |
557 | |
558 const char* start() const { return (const char*)(this + 1); } | |
559 char* start() { return (char*)(this + 1); } | |
560 size_t avail() const { return fStop - fCurr; } | |
561 size_t written() const { return fCurr - this->start(); } | |
562 | |
563 void init(size_t size) | |
564 { | |
565 fNext = NULL; | |
566 fCurr = this->start(); | |
567 fStop = this->start() + size; | |
568 } | |
569 | |
570 const void* append(const void* data, size_t size) | |
571 { | |
572 SkASSERT((size_t)(fStop - fCurr) >= size); | |
573 memcpy(fCurr, data, size); | |
574 fCurr += size; | |
575 return (const void*)((const char*)data + size); | |
576 } | |
577 }; | |
578 | |
579 SkDynamicMemoryWStream::SkDynamicMemoryWStream() : fHead(NULL), fTail(NULL), fBy
tesWritten(0), fCopyToCache(NULL) | |
580 { | |
581 } | |
582 | |
583 SkDynamicMemoryWStream::~SkDynamicMemoryWStream() | |
584 { | |
585 reset(); | |
586 } | |
587 | |
588 const char* SkDynamicMemoryWStream::detach() | |
589 { | |
590 const char* result = getStream(); | |
591 fCopyToCache = NULL; | |
592 return result; | |
593 } | |
594 | |
595 void SkDynamicMemoryWStream::reset() | |
596 { | |
597 sk_free(fCopyToCache); | |
598 Block* block = fHead; | |
599 | |
600 while (block != NULL) { | |
601 Block* next = block->fNext; | |
602 sk_free(block); | |
603 block = next; | |
604 } | |
605 fHead = fTail = NULL; | |
606 fBytesWritten = 0; | |
607 fCopyToCache = NULL; | |
608 } | |
609 | |
610 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count) | |
611 { | |
612 if (count > 0) { | |
613 | |
614 if (fCopyToCache) { | |
615 sk_free(fCopyToCache); | |
616 fCopyToCache = NULL; | |
617 } | |
618 fBytesWritten += count; | |
619 | |
620 size_t size; | |
621 | |
622 if (fTail != NULL && fTail->avail() > 0) { | |
623 size = SkMin32(fTail->avail(), count); | |
624 buffer = fTail->append(buffer, size); | |
625 SkASSERT(count >= size); | |
626 count -= size; | |
627 if (count == 0) | |
628 return true; | |
629 } | |
630 | |
631 size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize); | |
632 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); | |
633 block->init(size); | |
634 block->append(buffer, count); | |
635 | |
636 if (fTail != NULL) | |
637 fTail->fNext = block; | |
638 else | |
639 fHead = fTail = block; | |
640 fTail = block; | |
641 } | |
642 return true; | |
643 } | |
644 | |
645 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t cou
nt) | |
646 { | |
647 if (offset + count > fBytesWritten) | |
648 return false; // test does not partially modify | |
649 Block* block = fHead; | |
650 while (block != NULL) { | |
651 size_t size = block->written(); | |
652 if (offset < size) { | |
653 size_t part = offset + count > size ? size - offset : count; | |
654 memcpy(block->start() + offset, buffer, part); | |
655 if (count <= part) | |
656 return true; | |
657 count -= part; | |
658 buffer = (const void*) ((char* ) buffer + part); | |
659 } | |
660 offset = offset > size ? offset - size : 0; | |
661 block = block->fNext; | |
662 } | |
663 return false; | |
664 } | |
665 | |
666 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count) | |
667 { | |
668 if (offset + count > fBytesWritten) | |
669 return false; // test does not partially modify | |
670 Block* block = fHead; | |
671 while (block != NULL) { | |
672 size_t size = block->written(); | |
673 if (offset < size) { | |
674 size_t part = offset + count > size ? size - offset : count; | |
675 memcpy(buffer, block->start() + offset, part); | |
676 if (count <= part) | |
677 return true; | |
678 count -= part; | |
679 buffer = (void*) ((char* ) buffer + part); | |
680 } | |
681 offset = offset > size ? offset - size : 0; | |
682 block = block->fNext; | |
683 } | |
684 return false; | |
685 } | |
686 | |
687 void SkDynamicMemoryWStream::copyTo(void* dst) const | |
688 { | |
689 Block* block = fHead; | |
690 | |
691 while (block != NULL) { | |
692 size_t size = block->written(); | |
693 memcpy(dst, block->start(), size); | |
694 dst = (void*)((char*)dst + size); | |
695 block = block->fNext; | |
696 } | |
697 } | |
698 | |
699 const char* SkDynamicMemoryWStream::getStream() const | |
700 { | |
701 if (fCopyToCache == NULL) { | |
702 fCopyToCache = (char*)sk_malloc_throw(fBytesWritten); | |
703 this->copyTo(fCopyToCache); | |
704 } | |
705 return fCopyToCache; | |
706 } | |
707 | |
708 void SkDynamicMemoryWStream::padToAlign4() | |
709 { | |
710 // cast to remove unary-minus warning | |
711 int padBytes = -(int)fBytesWritten & 0x03; | |
712 if (padBytes == 0) | |
713 return; | |
714 int zero = 0; | |
715 write(&zero, padBytes); | |
716 } | |
717 | |
718 ////////////////////////////////////////////////////////////////////////////////
///////////////////////// | |
719 | |
720 void SkDebugWStream::newline() | |
721 { | |
722 #ifdef SK_DEBUG | |
723 SkDebugf("\n"); | |
724 #endif | |
725 } | |
726 | |
727 bool SkDebugWStream::write(const void* buffer, size_t size) | |
728 { | |
729 #ifdef SK_DEBUG | |
730 char* s = new char[size+1]; | |
731 memcpy(s, buffer, size); | |
732 s[size] = 0; | |
733 SkDebugf("%s", s); | |
734 delete[] s; | |
735 #endif | |
736 return true; | |
737 } | |
738 | |
739 ////////////////////////////////////////////////////////////////////////////////
///////////////////////// | |
740 ////////////////////////////////////////////////////////////////////////////////
///////////////////////// | |
741 | |
742 #ifdef SK_DEBUG | |
743 | |
744 #include "SkRandom.h" | |
745 | |
746 #ifdef SK_SUPPORT_UNITTEST | |
747 #define MAX_SIZE (256 * 1024) | |
748 | |
749 static void random_fill(SkRandom& rand, void* buffer, size_t size) { | |
750 char* p = (char*)buffer; | |
751 char* stop = p + size; | |
752 while (p < stop) { | |
753 *p++ = (char)(rand.nextU() >> 8); | |
754 } | |
755 } | |
756 | |
757 static void test_buffer() { | |
758 SkRandom rand; | |
759 SkAutoMalloc am(MAX_SIZE * 2); | |
760 char* storage = (char*)am.get(); | |
761 char* storage2 = storage + MAX_SIZE; | |
762 | |
763 random_fill(rand, storage, MAX_SIZE); | |
764 | |
765 for (int sizeTimes = 0; sizeTimes < 100; sizeTimes++) { | |
766 int size = rand.nextU() % MAX_SIZE; | |
767 if (size == 0) { | |
768 size = MAX_SIZE; | |
769 } | |
770 for (int times = 0; times < 100; times++) { | |
771 int bufferSize = 1 + (rand.nextU() & 0xFFFF); | |
772 SkMemoryStream mstream(storage, size); | |
773 SkBufferStream bstream(&mstream, bufferSize); | |
774 | |
775 int bytesRead = 0; | |
776 while (bytesRead < size) { | |
777 int s = 17 + (rand.nextU() & 0xFFFF); | |
778 int ss = bstream.read(storage2, s); | |
779 SkASSERT(ss > 0 && ss <= s); | |
780 SkASSERT(bytesRead + ss <= size); | |
781 SkASSERT(memcmp(storage + bytesRead, storage2, ss) == 0); | |
782 bytesRead += ss; | |
783 } | |
784 SkASSERT(bytesRead == size); | |
785 } | |
786 } | |
787 } | |
788 #endif | |
789 | |
790 void SkStream::UnitTest() { | |
791 #ifdef SK_SUPPORT_UNITTEST | |
792 { | |
793 static const char s[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstu
vwxyz"; | |
794 char copy[sizeof(s)]; | |
795 SkRandom rand; | |
796 | |
797 for (int i = 0; i < 65; i++) | |
798 { | |
799 char* copyPtr = copy; | |
800 SkMemoryStream mem(s, sizeof(s)); | |
801 SkBufferStream buff(&mem, i); | |
802 | |
803 do { | |
804 copyPtr += buff.read(copyPtr, rand.nextU() & 15); | |
805 } while (copyPtr < copy + sizeof(s)); | |
806 SkASSERT(copyPtr == copy + sizeof(s)); | |
807 SkASSERT(memcmp(s, copy, sizeof(s)) == 0); | |
808 } | |
809 } | |
810 test_buffer(); | |
811 #endif | |
812 } | |
813 | |
814 void SkWStream::UnitTest() | |
815 { | |
816 #ifdef SK_SUPPORT_UNITTEST | |
817 { | |
818 SkDebugWStream s; | |
819 | |
820 s.writeText("testing wstream helpers\n"); | |
821 s.writeText("compare: 0 "); s.writeDecAsText(0); s.newline(); | |
822 s.writeText("compare: 591 "); s.writeDecAsText(591); s.newline(); | |
823 s.writeText("compare: -9125 "); s.writeDecAsText(-9125); s.newlin
e(); | |
824 s.writeText("compare: 0 "); s.writeHexAsText(0, 0); s.newline(); | |
825 s.writeText("compare: 03FA "); s.writeHexAsText(0x3FA, 4); s.newlin
e(); | |
826 s.writeText("compare: DEADBEEF "); s.writeHexAsText(0xDEADBEEF, 4);
s.newline(); | |
827 s.writeText("compare: 0 "); s.writeScalarAsText(SkIntToScalar(0)
); s.newline(); | |
828 s.writeText("compare: 27 "); s.writeScalarAsText(SkIntToScalar(27
)); s.newline(); | |
829 s.writeText("compare: -119 "); s.writeScalarAsText(SkIntToScalar(-1
19)); s.newline(); | |
830 s.writeText("compare: 851.3333 "); s.writeScalarAsText(SkIntToScalar(85
1) + SK_Scalar1/3); s.newline(); | |
831 s.writeText("compare: -0.08 "); s.writeScalarAsText(-SK_Scalar1*8/10
0); s.newline(); | |
832 } | |
833 | |
834 { | |
835 SkDynamicMemoryWStream ds; | |
836 const char s[] = "abcdefghijklmnopqrstuvwxyz"; | |
837 int i; | |
838 for (i = 0; i < 100; i++) { | |
839 bool result = ds.write(s, 26); | |
840 SkASSERT(result); | |
841 } | |
842 SkASSERT(ds.getOffset() == 100 * 26); | |
843 char* dst = new char[100 * 26 + 1]; | |
844 dst[100*26] = '*'; | |
845 ds.copyTo(dst); | |
846 SkASSERT(dst[100*26] == '*'); | |
847 // char* p = dst; | |
848 for (i = 0; i < 100; i++) | |
849 SkASSERT(memcmp(&dst[i * 26], s, 26) == 0); | |
850 SkASSERT(memcmp(dst, ds.getStream(), 100*26) == 0); | |
851 delete[] dst; | |
852 } | |
853 #endif | |
854 } | |
855 | |
856 #endif | |
OLD | NEW |