#ifndef _PACKAGE__HPKG__PRIVATE__PACKAGE_FILE_HEAP_ACCESSOR_BASE_H_
#define _PACKAGE__HPKG__PRIVATE__PACKAGE_FILE_HEAP_ACCESSOR_BASE_H_
#include <new>
#include <Referenceable.h>
#include <CompressionAlgorithm.h>
#include <package/hpkg/DataReader.h>
namespace BPackageKit {
namespace BHPKG {
class BErrorOutput;
namespace BPrivate {
template<typename Parameters>
struct GenericCompressionAlgorithmOwner : BReferenceable {
BCompressionAlgorithm* algorithm;
Parameters* parameters;
GenericCompressionAlgorithmOwner(BCompressionAlgorithm* algorithm,
Parameters* parameters)
:
algorithm(algorithm),
parameters(parameters)
{
}
~GenericCompressionAlgorithmOwner()
{
delete algorithm;
delete parameters;
}
static GenericCompressionAlgorithmOwner* Create(
BCompressionAlgorithm* algorithm, Parameters* parameters)
{
GenericCompressionAlgorithmOwner* owner
= new(std::nothrow) GenericCompressionAlgorithmOwner(algorithm,
parameters);
if (owner == NULL) {
delete algorithm;
delete parameters;
}
return owner;
}
};
typedef GenericCompressionAlgorithmOwner<BCompressionParameters>
CompressionAlgorithmOwner;
typedef GenericCompressionAlgorithmOwner<BDecompressionParameters>
DecompressionAlgorithmOwner;
class PackageFileHeapAccessorBase : public BAbstractBufferedDataReader {
public:
class OffsetArray;
public:
PackageFileHeapAccessorBase(
BErrorOutput* errorOutput,
BPositionIO* file, off_t heapOffset,
DecompressionAlgorithmOwner*
decompressionAlgorithm);
virtual ~PackageFileHeapAccessorBase();
off_t HeapOffset() const
{ return fHeapOffset; }
off_t CompressedHeapSize() const
{ return fCompressedHeapSize; }
uint64 UncompressedHeapSize() const
{ return fUncompressedHeapSize; }
size_t ChunkSize() const
{ return kChunkSize; }
void SetErrorOutput(BErrorOutput* errorOutput)
{ fErrorOutput = errorOutput; }
void SetFile(BPositionIO* file)
{ fFile = file; }
virtual status_t ReadDataToOutput(off_t offset,
size_t size, BDataIO* output);
public:
static const size_t kChunkSize = 64 * 1024;
#if defined(_KERNEL_MODE)
static void* sQuadChunkCache;
static void* sQuadChunkFallbackBuffer;
#endif
protected:
virtual status_t ReadAndDecompressChunk(size_t chunkIndex,
void* compressedDataBuffer,
void* uncompressedDataBuffer,
iovec* scratchBuffer = NULL) = 0;
status_t ReadAndDecompressChunkData(uint64 offset,
size_t compressedSize,
size_t uncompressedSize,
void* compressedDataBuffer,
void* uncompressedDataBuffer,
iovec* scratchBuffer = NULL);
status_t DecompressChunkData(const iovec& compressedBuffer,
iovec& uncompressedBuffer,
iovec* scratchBuffer = NULL);
status_t ReadFileData(uint64 offset, void* buffer,
size_t size);
protected:
BErrorOutput* fErrorOutput;
BPositionIO* fFile;
off_t fHeapOffset;
uint64 fCompressedHeapSize;
uint64 fUncompressedHeapSize;
DecompressionAlgorithmOwner* fDecompressionAlgorithm;
};
class PackageFileHeapAccessorBase::OffsetArray {
public:
OffsetArray();
~OffsetArray();
bool InitUncompressedChunksOffsets(
size_t totalChunkCount);
bool InitChunksOffsets(size_t totalChunkCount,
size_t baseIndex, const uint16* chunkSizes,
size_t chunkCount);
bool Init(size_t totalChunkCount,
const OffsetArray& other);
uint64 operator[](size_t index) const;
private:
static uint32* _AllocateOffsetArray(size_t totalChunkCount,
size_t offset32BitChunkCount);
private:
uint32* fOffsets;
};
inline uint64
PackageFileHeapAccessorBase::OffsetArray::operator[](size_t index) const
{
if (index == 0)
return 0;
if (fOffsets[0] == 0 || index < fOffsets[0])
return fOffsets[index];
index += index - fOffsets[0];
return fOffsets[index] | ((uint64)fOffsets[index + 1] << 32);
}
}
}
}
#endif