root/src/kits/package/hpkg/PackageDataReader.cpp
/*
 * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */


#include <package/hpkg/PackageDataReader.h>

#include <string.h>

#include <algorithm>
#include <new>

#include <package/hpkg/HPKGDefsPrivate.h>
#include <package/hpkg/PackageData.h>


namespace BPackageKit {

namespace BHPKG {


using namespace BPrivate;


// #pragma mark - PackageDataHeapReader


class PackageDataHeapReader : public BAbstractBufferedDataReader {
public:
        PackageDataHeapReader(BAbstractBufferedDataReader* dataReader,
                const BPackageData& data)
                :
                fDataReader(dataReader),
                fOffset(data.Offset()),
                fSize(data.Size())
        {
        }

        virtual status_t ReadData(off_t offset, void* buffer, size_t size)
        {
                if (size == 0)
                        return B_OK;

                if (offset < 0)
                        return B_BAD_VALUE;

                if ((uint64)offset > fSize || size > fSize - offset)
                        return B_BAD_VALUE;

                return fDataReader->ReadData(fOffset + offset, buffer, size);
        }

        virtual status_t ReadDataToOutput(off_t offset, size_t size,
                BDataIO* output)
        {
                if (size == 0)
                        return B_OK;

                if (offset < 0)
                        return B_BAD_VALUE;

                if ((uint64)offset > fSize || size > fSize - offset)
                        return B_BAD_VALUE;

                return fDataReader->ReadDataToOutput(fOffset + offset, size, output);
        }

private:
        BAbstractBufferedDataReader*    fDataReader;
        uint64                                                  fOffset;
        uint64                                                  fSize;
};


// #pragma mark - PackageDataInlineReader


class PackageDataInlineReader : public BBufferDataReader {
public:
        PackageDataInlineReader(const BPackageData& data)
                :
                BBufferDataReader(data.InlineData(), data.Size()),
                fData(data)
        {
        }

private:
        BPackageData    fData;
};


// #pragma mark - BPackageDataReaderFactory


BPackageDataReaderFactory::BPackageDataReaderFactory()
{
}


status_t
BPackageDataReaderFactory::CreatePackageDataReader(
        BAbstractBufferedDataReader* dataReader, const BPackageData& data,
        BAbstractBufferedDataReader*& _reader)
{
        BAbstractBufferedDataReader* reader;
        if (data.IsEncodedInline())
                reader = new(std::nothrow) PackageDataInlineReader(data);
        else
                reader = new(std::nothrow) PackageDataHeapReader(dataReader, data);

        if (reader == NULL)
                return B_NO_MEMORY;

        _reader = reader;
        return B_OK;
}


}       // namespace BHPKG

}       // namespace BPackageKit