xref: /haiku/headers/private/package/hpkg/PackageFileHeapAccessorBase.h (revision 040a81419dda83d1014e9dc94936a4cb3f027303)
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