コード例 #1
0
ファイル: filedecoder.cpp プロジェクト: peter-x/zfec_fs
int FileDecoder::Read(char *outBuffer, size_t size, off_t offset)
{
    if (offset >= Size())
        return 0;

    unsigned int sharesRequired = fecWrapper.GetSharesRequired();
    // read some more in case size is not a multiple of required
    int bytesToRead = (size + sharesRequired - 1) / sharesRequired + 1;
    int minBytesRead = bytesToRead;

    // TODO better to have only one vector? - avoid re-allocating the vectors
    std::vector<std::vector<char> >& readBuffers(threadLocalData.Get().readBuffers);
    readBuffers.resize(sharesRequired);
    for (unsigned int i = 0; i < sharesRequired; ++i) {
        readBuffers[i].resize(bytesToRead);
        int bytesRead = encodedFiles[i]->Read(readBuffers[i].data(), bytesToRead,
                                             offset / sharesRequired + Metadata::size);
        minBytesRead = std::min(minBytesRead, bytesRead);
    }
    if (minBytesRead == 0)
        return 0;

    std::vector<const char*> fecInputPtrs(sharesRequired);
    std::vector<unsigned int> fecInputIndices(fileIndices.begin(), fileIndices.end());
    for (unsigned int i = 0; i < sharesRequired; ++i)
        fecInputPtrs[i] = readBuffers[i].data();

    NormalizeIndices(fecInputPtrs, fecInputIndices);

    std::vector<char>& workBuffer(threadLocalData.Get().workBuffer);
    workBuffer.resize(minBytesRead * sharesRequired);
    std::vector<char*> fecOutputPtrs(sharesRequired);
    for (unsigned int i = 0; i < sharesRequired; ++i)
        fecOutputPtrs[i] = workBuffer.data() + i * minBytesRead;

    fecWrapper.Decode(fecOutputPtrs.data(), fecInputPtrs.data(),
                      fecInputIndices.data(), minBytesRead);

    unsigned int offsetCorrection = offset % sharesRequired;

    size = std::min<size_t>(std::min<size_t>(size, minBytesRead * sharesRequired - offsetCorrection), Size() - offset);
    for (unsigned int i = 0; i < sharesRequired; ++i) {
        const char* decoded = fecInputIndices[i] < sharesRequired ? fecInputPtrs[i] : fecOutputPtrs[i];
        char* out = outBuffer + i - offsetCorrection;
        if (i < offsetCorrection) {
            out += sharesRequired;
            ++decoded;
        }
        CopyToNthElement(out, outBuffer + size, decoded, sharesRequired);
    }
    return size;
}
コード例 #2
0
ファイル: BSCLib.cpp プロジェクト: carriercomm/Frost
    bool BSCLib::decompressData(uint8 *& out, size_t & outSize, const uint8 * in, const size_t inSize)
    {
        // We need to first read the number of blocks
        if (!in || inSize < sizeof(uint32)) return setError(BadFormat);
        uint32 nBlocks = 0;
        size_t processedSize = 0;
        #define POP(X, S) if ((processedSize + S) <= inSize) { memcpy(X, &in[processedSize], S); processedSize += S; } else return setError(UnexpectedEOD);
        POP(&nBlocks, sizeof(nBlocks));

        bool dryRun = out == 0;
        size_t requiredOut = 0;
        int8 recordSize = 1, sortingContext = 1;
        int64 inPos = 0;

        Utils::HeapBlock workBuffer(BSC::HeaderSize);
        size_t bufferSize = BSC::HeaderSize;

        uint32 curBlock = 0;
        do
        {
            // Check the block header
#ifndef BreakCompatibility
            POP(&inPos, sizeof(inPos));
            POP(&recordSize, sizeof(recordSize));
            POP(&sortingContext, sizeof(sortingContext));
#endif
            // Unsupported features ?
            if (recordSize < 1 || sortingContext < 1 || sortingContext > 2) return setError(BadFormat);

            // Read the block header
            POP(workBuffer, BSC::HeaderSize);

            // Figure out the block informations
            size_t blockSize = 0, dataSize = 0;
            if (opaque->getBlockInfo(workBuffer, BSC::HeaderSize, blockSize, dataSize) != BSC::Success)
                return setError(BadFormat);

            // From now, we need to allocate the work buffer
            if (blockSize > bufferSize) bufferSize = blockSize;
            if (dataSize > bufferSize)  bufferSize = dataSize;
            if (!workBuffer.resize(bufferSize)) return setError(NotEnoughMemory);

            POP(workBuffer + BSC::HeaderSize, blockSize - BSC::HeaderSize);

            if (dataSize != 0)
            {
                // Now decompress the cruft
                BSC::Error err = opaque->decompress(workBuffer, blockSize, workBuffer, dataSize);
                if (err != BSC::Success)
                {
                    return err == BSC::NotEnoughMemory ? setError(NotEnoughMemory) : setError(DataCorrupt);
                }

                // Depending on the sorting context, we might need to reverse the blocks
                err = opaque->postProcess(workBuffer, dataSize, sortingContext, recordSize);
                if (err != BSC::Success)
                {
                    return err == BSC::NotEnoughMemory ? setError(NotEnoughMemory) : setError(DataCorrupt);
                }

                // Write data now!
                if (out && requiredOut + dataSize <= outSize)
                    memcpy(&out[requiredOut], workBuffer, dataSize);

                requiredOut += dataSize;
            }
            curBlock++;
            if (curBlock == nBlocks || dataSize == 0)
            {
                // Check for dry run
                if (dryRun)
                {
                    if (!out && outSize) { outSize = requiredOut; return setError(UnexpectedEOD); }
                    outSize = requiredOut;
                    delete[] out;
                    out = new uint8[requiredOut];
                    if (!out) return setError(NotEnoughMemory);
                    // Ok, try again for real now
                    dryRun = false;
                    curBlock = 0; requiredOut = 0; processedSize = sizeof(nBlocks);
                } else break; // Done
            }
        } while (true);
#undef POP
        return setError(Success);
    }