int StaticCompressor::compressBuffer(const unsigned char *plainBuffer, const unsigned int plainSize, unsigned char *&compressedBuffer, unsigned int &compressedSize, EncodeBuffer &encodeBuffer) { if (control -> LocalDataCompression == 0 || compressBuffer(plainBuffer, plainSize, compressedBuffer, compressedSize) <= 0) { encodeBuffer.encodeBoolValue(0); encodeBuffer.encodeMemory(plainBuffer, plainSize); return 0; } else { encodeBuffer.encodeBoolValue(1); encodeBuffer.encodeValue(compressedSize, 32, 14); encodeBuffer.encodeValue(plainSize, 32, 14); encodeBuffer.encodeMemory(compressedBuffer, compressedSize); return 1; } }
bool ResourcePackager::WritePackageFile(const String& destFilePath) { buildBase_->BuildLog("Writing package"); SharedPtr<File> dest(new File(context_, destFilePath, FILE_WRITE)); if (!dest->IsOpen()) { buildBase_->BuildError("Could not open output file " + destFilePath); return false; } // Write ID, number of files & placeholder for checksum WriteHeader(dest); for (unsigned i = 0; i < resourceEntries_.Size(); i++) { BuildResourceEntry* entry = resourceEntries_[i]; // Write entry (correct offset is still unknown, will be filled in later) dest->WriteString(entry->packagePath_); dest->WriteUInt(entry->offset_); dest->WriteUInt(entry->size_); dest->WriteUInt(entry->checksum_); } unsigned totalDataSize = 0; // Write file data, calculate checksums & correct offsets for (unsigned i = 0; i < resourceEntries_.Size(); i++) { BuildResourceEntry* entry = resourceEntries_[i]; entry->offset_ = dest->GetSize(); File srcFile(context_, entry->absolutePath_); if (!srcFile.IsOpen()) { buildBase_->BuildError("Could not open input file " + entry->absolutePath_); return false; } unsigned dataSize = entry->size_; totalDataSize += dataSize; SharedArrayPtr<unsigned char> buffer(new unsigned char[dataSize]); if (srcFile.Read(&buffer[0], dataSize) != dataSize) { buildBase_->BuildError("Could not read input file " + entry->absolutePath_); return false; } srcFile.Close(); for (unsigned j = 0; j < dataSize; ++j) { checksum_ = SDBMHash(checksum_, buffer[j]); entry->checksum_ = SDBMHash(entry->checksum_, buffer[j]); } // might not want to compress for WebGL //if (!compress_) //{ // PrintLine(entries_[i].name_ + " size " + String(dataSize)); // dest.Write(&buffer[0], entries_[i].size_); //} //else //{ unsigned compressedBlockSize_ = 32768; SharedArrayPtr<unsigned char> compressBuffer(new unsigned char[LZ4_compressBound(compressedBlockSize_)]); unsigned pos = 0; unsigned totalPackedBytes = 0; while (pos < dataSize) { unsigned unpackedSize = compressedBlockSize_; if (pos + unpackedSize > dataSize) unpackedSize = dataSize - pos; unsigned packedSize = LZ4_compressHC((const char*)&buffer[pos], (char*)compressBuffer.Get(), unpackedSize); if (!packedSize) { buildBase_->BuildError("LZ4 compression failed for file " + entry->absolutePath_ + " at offset " + pos); return false; } dest->WriteUShort(unpackedSize); dest->WriteUShort(packedSize); dest->Write(compressBuffer.Get(), packedSize); totalPackedBytes += 6 + packedSize; pos += unpackedSize; } buildBase_->BuildLog(entry->absolutePath_ + " in " + String(dataSize) + " out " + String(totalPackedBytes)); } //} // Write package size to the end of file to allow finding it linked to an executable file unsigned currentSize = dest->GetSize(); dest->WriteUInt(currentSize + sizeof(unsigned)); // Write header again with correct offsets & checksums dest->Seek(0); WriteHeader(dest); for (unsigned i = 0; i < resourceEntries_.Size(); i++) { BuildResourceEntry* entry = resourceEntries_[i]; dest->WriteString(entry->packagePath_); dest->WriteUInt(entry->offset_); dest->WriteUInt(entry->size_); dest->WriteUInt(entry->checksum_); } buildBase_->BuildLog("Number of files " + String(resourceEntries_.Size())); buildBase_->BuildLog("File data size " + String(totalDataSize)); buildBase_->BuildLog("Package size " + String(dest->GetSize())); return true; }