Exemple #1
0
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;
}