1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkDeflate.h" 9 #include "SkRandom.h" 10 #include "Test.h" 11 12 namespace { 13 14 #ifdef ZLIB_INCLUDE 15 #include ZLIB_INCLUDE 16 #else 17 #include "zlib.h" 18 #endif 19 20 // Different zlib implementations use different T. 21 // We've seen size_t and unsigned. 22 template <typename T> void* skia_alloc_func(void*, T items, T size) { 23 return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size)); 24 } 25 26 void skia_free_func(void*, void* address) { sk_free(address); } 27 28 /** 29 * Use the un-deflate compression algorithm to decompress the data in src, 30 * returning the result. Returns nullptr if an error occurs. 31 */ 32 SkStreamAsset* stream_inflate(SkStream* src) { 33 SkDynamicMemoryWStream decompressedDynamicMemoryWStream; 34 SkWStream* dst = &decompressedDynamicMemoryWStream; 35 36 static const size_t kBufferSize = 1024; 37 uint8_t inputBuffer[kBufferSize]; 38 uint8_t outputBuffer[kBufferSize]; 39 z_stream flateData; 40 flateData.zalloc = &skia_alloc_func; 41 flateData.zfree = &skia_free_func; 42 flateData.opaque = nullptr; 43 flateData.next_in = nullptr; 44 flateData.avail_in = 0; 45 flateData.next_out = outputBuffer; 46 flateData.avail_out = kBufferSize; 47 int rc; 48 rc = inflateInit(&flateData); 49 if (rc != Z_OK) 50 return nullptr; 51 52 uint8_t* input = (uint8_t*)src->getMemoryBase(); 53 size_t inputLength = src->getLength(); 54 if (input == nullptr || inputLength == 0) { 55 input = nullptr; 56 flateData.next_in = inputBuffer; 57 flateData.avail_in = 0; 58 } else { 59 flateData.next_in = input; 60 flateData.avail_in = SkToUInt(inputLength); 61 } 62 63 rc = Z_OK; 64 while (true) { 65 if (flateData.avail_out < kBufferSize) { 66 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) { 67 rc = Z_BUF_ERROR; 68 break; 69 } 70 flateData.next_out = outputBuffer; 71 flateData.avail_out = kBufferSize; 72 } 73 if (rc != Z_OK) 74 break; 75 if (flateData.avail_in == 0) { 76 if (input != nullptr) 77 break; 78 size_t read = src->read(&inputBuffer, kBufferSize); 79 if (read == 0) 80 break; 81 flateData.next_in = inputBuffer; 82 flateData.avail_in = SkToUInt(read); 83 } 84 rc = inflate(&flateData, Z_NO_FLUSH); 85 } 86 while (rc == Z_OK) { 87 rc = inflate(&flateData, Z_FINISH); 88 if (flateData.avail_out < kBufferSize) { 89 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) 90 return nullptr; 91 flateData.next_out = outputBuffer; 92 flateData.avail_out = kBufferSize; 93 } 94 } 95 96 inflateEnd(&flateData); 97 if (rc != Z_STREAM_END) { 98 return nullptr; 99 } 100 return decompressedDynamicMemoryWStream.detachAsStream(); 101 } 102 } // namespace 103 104 DEF_TEST(SkDeflateWStream, r) { 105 SkRandom random(123456); 106 for (int i = 0; i < 50; ++i) { 107 uint32_t size = random.nextULessThan(10000); 108 SkAutoTMalloc<uint8_t> buffer(size); 109 for (uint32_t j = 0; j < size; ++j) { 110 buffer[j] = random.nextU() & 0xff; 111 } 112 113 SkDynamicMemoryWStream dynamicMemoryWStream; 114 { 115 SkDeflateWStream deflateWStream(&dynamicMemoryWStream); 116 uint32_t j = 0; 117 while (j < size) { 118 uint32_t writeSize = 119 SkTMin(size - j, random.nextRangeU(1, 400)); 120 if (!deflateWStream.write(&buffer[j], writeSize)) { 121 ERRORF(r, "something went wrong."); 122 return; 123 } 124 j += writeSize; 125 } 126 } 127 SkAutoTDelete<SkStreamAsset> compressed( 128 dynamicMemoryWStream.detachAsStream()); 129 SkAutoTDelete<SkStreamAsset> decompressed(stream_inflate(compressed)); 130 131 if (decompressed->getLength() != size) { 132 ERRORF(r, "Decompression failed to get right size [%d]." 133 " %u != %u", i, (unsigned)(decompressed->getLength()), 134 (unsigned)size); 135 SkString s = SkStringPrintf("/tmp/deftst_compressed_%d", i); 136 SkFILEWStream o(s.c_str()); 137 o.writeStream(compressed.get(), compressed->getLength()); 138 compressed->rewind(); 139 140 s = SkStringPrintf("/tmp/deftst_input_%d", i); 141 SkFILEWStream o2(s.c_str()); 142 o2.write(&buffer[0], size); 143 144 continue; 145 } 146 uint32_t minLength = SkTMin(size, 147 (uint32_t)(decompressed->getLength())); 148 for (uint32_t i = 0; i < minLength; ++i) { 149 uint8_t c; 150 SkDEBUGCODE(size_t rb =)decompressed->read(&c, sizeof(uint8_t)); 151 SkASSERT(sizeof(uint8_t) == rb); 152 if (buffer[i] != c) { 153 ERRORF(r, "Decompression failed at byte %u.", (unsigned)i); 154 break; 155 } 156 } 157 } 158 } 159