btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / private / package / hpkg / PackageFileHeapAccessorBase.h
blob5af32a092cca0ab7084932eddecd688d567d3a37
1 /*
2 * Copyright 2013-2014, 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_
9 #include <new>
11 #include <Referenceable.h>
13 #include <CompressionAlgorithm.h>
14 #include <package/hpkg/DataReader.h>
17 namespace BPackageKit {
19 namespace BHPKG {
22 class BErrorOutput;
25 namespace BPrivate {
28 template<typename Parameters>
29 struct GenericCompressionAlgorithmOwner : BReferenceable {
30 BCompressionAlgorithm* algorithm;
31 Parameters* parameters;
33 GenericCompressionAlgorithmOwner(BCompressionAlgorithm* algorithm,
34 Parameters* parameters)
36 algorithm(algorithm),
37 parameters(parameters)
41 ~GenericCompressionAlgorithmOwner()
43 delete algorithm;
44 delete parameters;
47 static GenericCompressionAlgorithmOwner* Create(
48 BCompressionAlgorithm* algorithm, Parameters* parameters)
50 GenericCompressionAlgorithmOwner* owner
51 = new(std::nothrow) GenericCompressionAlgorithmOwner(algorithm,
52 parameters);
53 if (owner == NULL) {
54 delete algorithm;
55 delete parameters;
58 return owner;
62 typedef GenericCompressionAlgorithmOwner<BCompressionParameters>
63 CompressionAlgorithmOwner;
64 typedef GenericCompressionAlgorithmOwner<BDecompressionParameters>
65 DecompressionAlgorithmOwner;
68 class PackageFileHeapAccessorBase : public BAbstractBufferedDataReader {
69 public:
70 class OffsetArray;
72 public:
73 PackageFileHeapAccessorBase(
74 BErrorOutput* errorOutput,
75 BPositionIO* file, off_t heapOffset,
76 DecompressionAlgorithmOwner*
77 decompressionAlgorithm);
78 virtual ~PackageFileHeapAccessorBase();
80 off_t HeapOffset() const
81 { return fHeapOffset; }
82 off_t CompressedHeapSize() const
83 { return fCompressedHeapSize; }
84 uint64 UncompressedHeapSize() const
85 { return fUncompressedHeapSize; }
86 size_t ChunkSize() const
87 { return kChunkSize; }
89 // normally used after cloning a PackageFileHeapReader only
90 void SetErrorOutput(BErrorOutput* errorOutput)
91 { fErrorOutput = errorOutput; }
92 void SetFile(BPositionIO* file)
93 { fFile = file; }
95 // BAbstractBufferedDataReader
96 virtual status_t ReadDataToOutput(off_t offset,
97 size_t size, BDataIO* output);
99 public:
100 static const size_t kChunkSize = 64 * 1024;
102 protected:
103 virtual status_t ReadAndDecompressChunk(size_t chunkIndex,
104 void* compressedDataBuffer,
105 void* uncompressedDataBuffer) = 0;
106 status_t ReadAndDecompressChunkData(uint64 offset,
107 size_t compressedSize,
108 size_t uncompressedSize,
109 void* compressedDataBuffer,
110 void* uncompressedDataBuffer);
111 status_t DecompressChunkData(
112 void* compressedDataBuffer,
113 size_t compressedSize,
114 void* uncompressedDataBuffer,
115 size_t uncompressedSize);
116 status_t ReadFileData(uint64 offset, void* buffer,
117 size_t size);
119 protected:
120 BErrorOutput* fErrorOutput;
121 BPositionIO* fFile;
122 off_t fHeapOffset;
123 uint64 fCompressedHeapSize;
124 uint64 fUncompressedHeapSize;
125 DecompressionAlgorithmOwner* fDecompressionAlgorithm;
129 /*! Stores the chunk offsets in a compact way, while still providing quick
130 access.
131 - The object doesn't store the number of chunks/offsets it contains. During
132 initialization the chunk count is provided. Later, when getting an offset,
133 the caller is responsible for ensuring a valid index.
134 - The first (index 0) chunk offset is omitted, since it is always 0.
135 - The chunk offsets that fit in a 32 bit number use only one 32 bit element
136 in the offsets array.
137 - The chunk offsets that don't fit in a 32 bit number use two elements in
138 the offsets array.
139 Memory use is one pointer, if the chunk count is <= 1 (uncompressed heap size
140 <= 64 KiB). Afterwards it's one pointer plus 32 bit per chunk as long as the
141 last offset still fits 32 bit (compressed heap size < 4GiB). For any further
142 chunks it is 64 bit per chunk. So, for the common case we use sizeof(void*)
143 plus 1 KiB per 16 MiB of uncompressed heap, or about 64 KiB per 1 GiB. Which
144 seems reasonable for packagefs to keep in memory.
146 class PackageFileHeapAccessorBase::OffsetArray {
147 public:
148 OffsetArray();
149 ~OffsetArray();
151 bool InitUncompressedChunksOffsets(
152 size_t totalChunkCount);
153 bool InitChunksOffsets(size_t totalChunkCount,
154 size_t baseIndex, const uint16* chunkSizes,
155 size_t chunkCount);
157 bool Init(size_t totalChunkCount,
158 const OffsetArray& other);
159 // "copy" init
161 uint64 operator[](size_t index) const;
163 private:
164 static uint32* _AllocateOffsetArray(size_t totalChunkCount,
165 size_t offset32BitChunkCount);
167 private:
168 uint32* fOffsets;
169 // - NULL, if chunkCount <= 1
170 // - element 0 contains the number of 32 bit
171 // offsets that follow, or is 0, when all
172 // offsets are 32 bit only
173 // - the following offsets use two elements
174 // each (lower followed by upper 32 bit)
175 // to represent the 64 bit value
179 inline uint64
180 PackageFileHeapAccessorBase::OffsetArray::operator[](size_t index) const
182 if (index == 0)
183 return 0;
185 if (fOffsets[0] == 0 || index < fOffsets[0])
186 return fOffsets[index];
188 index += index - fOffsets[0];
189 return fOffsets[index] | ((uint64)fOffsets[index + 1] << 32);
193 } // namespace BPrivate
195 } // namespace BHPKG
197 } // namespace BPackageKit
200 #endif // _PACKAGE__HPKG__PRIVATE__PACKAGE_FILE_HEAP_ACCESSOR_BASE_H_