1 /* 2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _PACKAGE__HPKG__PRIVATE__PACKAGE_FILE_HEAP_ACCESSOR_BASE_H_ 6 #define _PACKAGE__HPKG__PRIVATE__PACKAGE_FILE_HEAP_ACCESSOR_BASE_H_ 7 8 9 #include <SupportDefs.h> 10 11 #include <package/hpkg/DataReader.h> 12 13 14 namespace BPackageKit { 15 16 namespace BHPKG { 17 18 19 class BErrorOutput; 20 21 22 namespace BPrivate { 23 24 25 class PackageFileHeapAccessorBase : public BAbstractBufferedDataReader { 26 public: 27 class OffsetArray; 28 29 public: 30 PackageFileHeapAccessorBase( 31 BErrorOutput* errorOutput, int fd, 32 off_t heapOffset); 33 virtual ~PackageFileHeapAccessorBase(); 34 35 off_t HeapOffset() const 36 { return fHeapOffset; } 37 off_t CompressedHeapSize() const 38 { return fCompressedHeapSize; } 39 uint64 UncompressedHeapSize() const 40 { return fUncompressedHeapSize; } 41 size_t ChunkSize() const 42 { return kChunkSize; } 43 44 // normally used after cloning a PackageFileHeapReader only 45 void SetErrorOutput(BErrorOutput* errorOutput) 46 { fErrorOutput = errorOutput; } 47 void SetFD(int fd) 48 { fFD = fd; } 49 50 // BAbstractBufferedDataReader 51 virtual status_t ReadDataToOutput(off_t offset, size_t size, 52 BDataOutput* output); 53 54 public: 55 static const size_t kChunkSize = 64 * 1024; 56 57 protected: 58 virtual status_t ReadAndDecompressChunk(size_t chunkIndex, 59 void* compressedDataBuffer, 60 void* uncompressedDataBuffer) = 0; 61 status_t ReadAndDecompressChunkData(uint64 offset, 62 size_t compressedSize, 63 size_t uncompressedSize, 64 void* compressedDataBuffer, 65 void* uncompressedDataBuffer); 66 status_t DecompressChunkData( 67 void* compressedDataBuffer, 68 size_t compressedSize, 69 void* uncompressedDataBuffer, 70 size_t uncompressedSize); 71 status_t ReadFileData(uint64 offset, void* buffer, 72 size_t size); 73 74 protected: 75 BErrorOutput* fErrorOutput; 76 int fFD; 77 off_t fHeapOffset; 78 uint64 fCompressedHeapSize; 79 uint64 fUncompressedHeapSize; 80 }; 81 82 83 /*! Stores the chunk offsets in a compact way, while still providing quick 84 access. 85 - The object doesn't store the number of chunks/offsets it contains. During 86 initialization the chunk count is provided. Later, when getting an offset, 87 the caller is responsible for ensuring a valid index. 88 - The first (index 0) chunk offset is omitted, since it is always 0. 89 - The chunk offsets that fit in a 32 bit number use only one 32 bit element 90 in the offsets array. 91 - The chunk offsets that don't fit in a 32 bit number use two elements in 92 the offsets array. 93 Memory use is one pointer, if the chunk count is <= 1 (uncompressed heap size 94 <= 64 KiB). Afterwards it's one pointer plus 32 bit per chunk as long as the 95 last offset still fits 32 bit (compressed heap size < 4GiB). For any further 96 chunks it is 64 bit per chunk. So, for the common case we use sizeof(void*) 97 plus 1 KiB per 16 MiB of uncompressed heap, or about 64 KiB per 1 GiB. Which 98 seems reasonable for packagefs to keep in memory. 99 */ 100 class PackageFileHeapAccessorBase::OffsetArray { 101 public: 102 OffsetArray(); 103 ~OffsetArray(); 104 105 bool InitChunksOffsets(size_t totalChunkCount, 106 size_t baseIndex, const uint16* chunkSizes, 107 size_t chunkCount); 108 109 bool Init(size_t totalChunkCount, 110 const OffsetArray& other); 111 // "copy" init 112 113 uint64 operator[](size_t index) const; 114 115 private: 116 uint32* fOffsets; 117 // - NULL, if chunkCount <= 1 118 // - element 0 contains the number of 32 bit 119 // offsets that follow, or is 0, when all 120 // offsets are 32 bit only 121 // - the following offsets use two elements 122 // each (lower followed by upper 32 bit) 123 // to represent the 64 bit value 124 }; 125 126 127 inline uint64 128 PackageFileHeapAccessorBase::OffsetArray::operator[](size_t index) const 129 { 130 if (index == 0) 131 return 0; 132 133 if (fOffsets[0] == 0 || index < fOffsets[0]) 134 return fOffsets[index]; 135 136 index += index - fOffsets[0]; 137 return fOffsets[index] | ((uint64)fOffsets[index + 1] << 32); 138 } 139 140 141 } // namespace BPrivate 142 143 } // namespace BHPKG 144 145 } // namespace BPackageKit 146 147 148 #endif // _PACKAGE__HPKG__PRIVATE__PACKAGE_FILE_HEAP_ACCESSOR_BASE_H_ 149