xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Chm/ChmIn.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Archive/ChmIn.h
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_ARCHIVE_CHM_IN_H
4*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_ARCHIVE_CHM_IN_H
5*f6dc9357SAndroid Build Coastguard Worker 
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyBuffer.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyString.h"
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "../../IStream.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/InBuffer.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
14*f6dc9357SAndroid Build Coastguard Worker namespace NChm {
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker struct CItem
17*f6dc9357SAndroid Build Coastguard Worker {
18*f6dc9357SAndroid Build Coastguard Worker   UInt64 Section;
19*f6dc9357SAndroid Build Coastguard Worker   UInt64 Offset;
20*f6dc9357SAndroid Build Coastguard Worker   UInt64 Size;
21*f6dc9357SAndroid Build Coastguard Worker   AString Name;
22*f6dc9357SAndroid Build Coastguard Worker 
IsFormatRelatedItemCItem23*f6dc9357SAndroid Build Coastguard Worker   bool IsFormatRelatedItem() const
24*f6dc9357SAndroid Build Coastguard Worker   {
25*f6dc9357SAndroid Build Coastguard Worker     if (Name.Len() < 2)
26*f6dc9357SAndroid Build Coastguard Worker       return false;
27*f6dc9357SAndroid Build Coastguard Worker     return Name[0] == ':' && Name[1] == ':';
28*f6dc9357SAndroid Build Coastguard Worker   }
29*f6dc9357SAndroid Build Coastguard Worker 
IsUserItemCItem30*f6dc9357SAndroid Build Coastguard Worker   bool IsUserItem() const
31*f6dc9357SAndroid Build Coastguard Worker   {
32*f6dc9357SAndroid Build Coastguard Worker     if (Name.Len() < 2)
33*f6dc9357SAndroid Build Coastguard Worker       return false;
34*f6dc9357SAndroid Build Coastguard Worker     return Name[0] == '/';
35*f6dc9357SAndroid Build Coastguard Worker   }
36*f6dc9357SAndroid Build Coastguard Worker 
IsDirCItem37*f6dc9357SAndroid Build Coastguard Worker   bool IsDir() const
38*f6dc9357SAndroid Build Coastguard Worker   {
39*f6dc9357SAndroid Build Coastguard Worker     if (Name.IsEmpty())
40*f6dc9357SAndroid Build Coastguard Worker       return false;
41*f6dc9357SAndroid Build Coastguard Worker     return (Name.Back() == '/');
42*f6dc9357SAndroid Build Coastguard Worker   }
43*f6dc9357SAndroid Build Coastguard Worker };
44*f6dc9357SAndroid Build Coastguard Worker 
45*f6dc9357SAndroid Build Coastguard Worker 
46*f6dc9357SAndroid Build Coastguard Worker struct CDatabase
47*f6dc9357SAndroid Build Coastguard Worker {
48*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CItem> Items;
49*f6dc9357SAndroid Build Coastguard Worker   UInt64 StartPosition;
50*f6dc9357SAndroid Build Coastguard Worker   UInt64 ContentOffset;
51*f6dc9357SAndroid Build Coastguard Worker   AString NewFormatString;
52*f6dc9357SAndroid Build Coastguard Worker   bool Help2Format;
53*f6dc9357SAndroid Build Coastguard Worker   bool NewFormat;
54*f6dc9357SAndroid Build Coastguard Worker   UInt64 PhySize;
55*f6dc9357SAndroid Build Coastguard Worker 
UpdatePhySizeCDatabase56*f6dc9357SAndroid Build Coastguard Worker   void UpdatePhySize(UInt64 v) { if (PhySize < v) PhySize = v; }
57*f6dc9357SAndroid Build Coastguard Worker 
FindItemCDatabase58*f6dc9357SAndroid Build Coastguard Worker   int FindItem(const AString &name) const
59*f6dc9357SAndroid Build Coastguard Worker   {
60*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, Items)
61*f6dc9357SAndroid Build Coastguard Worker       if (Items[i].Name == name)
62*f6dc9357SAndroid Build Coastguard Worker         return (int)i;
63*f6dc9357SAndroid Build Coastguard Worker     return -1;
64*f6dc9357SAndroid Build Coastguard Worker   }
65*f6dc9357SAndroid Build Coastguard Worker 
ClearCDatabase66*f6dc9357SAndroid Build Coastguard Worker   void Clear()
67*f6dc9357SAndroid Build Coastguard Worker   {
68*f6dc9357SAndroid Build Coastguard Worker     NewFormat = false;
69*f6dc9357SAndroid Build Coastguard Worker     NewFormatString.Empty();
70*f6dc9357SAndroid Build Coastguard Worker     Help2Format = false;
71*f6dc9357SAndroid Build Coastguard Worker     Items.Clear();
72*f6dc9357SAndroid Build Coastguard Worker     StartPosition = 0;
73*f6dc9357SAndroid Build Coastguard Worker     PhySize = 0;
74*f6dc9357SAndroid Build Coastguard Worker   }
75*f6dc9357SAndroid Build Coastguard Worker };
76*f6dc9357SAndroid Build Coastguard Worker 
77*f6dc9357SAndroid Build Coastguard Worker 
78*f6dc9357SAndroid Build Coastguard Worker const UInt32 kBlockSize = 1 << 15;
79*f6dc9357SAndroid Build Coastguard Worker 
80*f6dc9357SAndroid Build Coastguard Worker struct CResetTable
81*f6dc9357SAndroid Build Coastguard Worker {
82*f6dc9357SAndroid Build Coastguard Worker   UInt64 UncompressedSize;
83*f6dc9357SAndroid Build Coastguard Worker   UInt64 CompressedSize;
84*f6dc9357SAndroid Build Coastguard Worker   // unsigned BlockSizeBits;
85*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt64> ResetOffsets;
86*f6dc9357SAndroid Build Coastguard Worker 
CResetTableCResetTable87*f6dc9357SAndroid Build Coastguard Worker   CResetTable():
88*f6dc9357SAndroid Build Coastguard Worker       UncompressedSize(0),
89*f6dc9357SAndroid Build Coastguard Worker       CompressedSize(0)
90*f6dc9357SAndroid Build Coastguard Worker       {}
91*f6dc9357SAndroid Build Coastguard Worker 
GetCompressedSizeOfBlocksCResetTable92*f6dc9357SAndroid Build Coastguard Worker   bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const
93*f6dc9357SAndroid Build Coastguard Worker   {
94*f6dc9357SAndroid Build Coastguard Worker     if (blockIndex >= ResetOffsets.Size())
95*f6dc9357SAndroid Build Coastguard Worker       return false;
96*f6dc9357SAndroid Build Coastguard Worker     UInt64 startPos = ResetOffsets[(unsigned)blockIndex];
97*f6dc9357SAndroid Build Coastguard Worker     if (blockIndex + numBlocks >= ResetOffsets.Size())
98*f6dc9357SAndroid Build Coastguard Worker       size = CompressedSize - startPos;
99*f6dc9357SAndroid Build Coastguard Worker     else
100*f6dc9357SAndroid Build Coastguard Worker       size = ResetOffsets[(unsigned)(blockIndex + numBlocks)] - startPos;
101*f6dc9357SAndroid Build Coastguard Worker     return true;
102*f6dc9357SAndroid Build Coastguard Worker   }
103*f6dc9357SAndroid Build Coastguard Worker 
GetCompressedSizeOfBlockCResetTable104*f6dc9357SAndroid Build Coastguard Worker   bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const
105*f6dc9357SAndroid Build Coastguard Worker   {
106*f6dc9357SAndroid Build Coastguard Worker     return GetCompressedSizeOfBlocks(blockIndex, 1, size);
107*f6dc9357SAndroid Build Coastguard Worker   }
108*f6dc9357SAndroid Build Coastguard Worker 
GetNumBlocksCResetTable109*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetNumBlocks(UInt64 size) const
110*f6dc9357SAndroid Build Coastguard Worker   {
111*f6dc9357SAndroid Build Coastguard Worker     return (size + kBlockSize - 1) / kBlockSize;
112*f6dc9357SAndroid Build Coastguard Worker   }
113*f6dc9357SAndroid Build Coastguard Worker };
114*f6dc9357SAndroid Build Coastguard Worker 
115*f6dc9357SAndroid Build Coastguard Worker 
116*f6dc9357SAndroid Build Coastguard Worker struct CLzxInfo
117*f6dc9357SAndroid Build Coastguard Worker {
118*f6dc9357SAndroid Build Coastguard Worker   UInt32 Version;
119*f6dc9357SAndroid Build Coastguard Worker 
120*f6dc9357SAndroid Build Coastguard Worker   unsigned ResetIntervalBits;
121*f6dc9357SAndroid Build Coastguard Worker   unsigned WindowSizeBits;
122*f6dc9357SAndroid Build Coastguard Worker   UInt32 CacheSize;
123*f6dc9357SAndroid Build Coastguard Worker 
124*f6dc9357SAndroid Build Coastguard Worker   CResetTable ResetTable;
125*f6dc9357SAndroid Build Coastguard Worker 
CLzxInfoCLzxInfo126*f6dc9357SAndroid Build Coastguard Worker   CLzxInfo():
127*f6dc9357SAndroid Build Coastguard Worker       Version(0),
128*f6dc9357SAndroid Build Coastguard Worker       ResetIntervalBits(0),
129*f6dc9357SAndroid Build Coastguard Worker       WindowSizeBits(0),
130*f6dc9357SAndroid Build Coastguard Worker       CacheSize(0)
131*f6dc9357SAndroid Build Coastguard Worker       {}
132*f6dc9357SAndroid Build Coastguard Worker 
GetNumDictBitsCLzxInfo133*f6dc9357SAndroid Build Coastguard Worker   unsigned GetNumDictBits() const
134*f6dc9357SAndroid Build Coastguard Worker   {
135*f6dc9357SAndroid Build Coastguard Worker     if (Version == 2 || Version == 3)
136*f6dc9357SAndroid Build Coastguard Worker       return 15 + WindowSizeBits;
137*f6dc9357SAndroid Build Coastguard Worker     return 0;
138*f6dc9357SAndroid Build Coastguard Worker   }
139*f6dc9357SAndroid Build Coastguard Worker 
GetFolderSizeCLzxInfo140*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetFolderSize() const { return (UInt64)kBlockSize << ResetIntervalBits; }
GetFolderCLzxInfo141*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); }
GetFolderPosCLzxInfo142*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); }
GetBlockIndexFromFolderIndexCLzxInfo143*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex << ResetIntervalBits; }
144*f6dc9357SAndroid Build Coastguard Worker 
GetOffsetOfFolderCLzxInfo145*f6dc9357SAndroid Build Coastguard Worker   bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const
146*f6dc9357SAndroid Build Coastguard Worker   {
147*f6dc9357SAndroid Build Coastguard Worker     const UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
148*f6dc9357SAndroid Build Coastguard Worker     if (blockIndex >= ResetTable.ResetOffsets.Size())
149*f6dc9357SAndroid Build Coastguard Worker       return false;
150*f6dc9357SAndroid Build Coastguard Worker     offset = ResetTable.ResetOffsets[(unsigned)blockIndex];
151*f6dc9357SAndroid Build Coastguard Worker     return true;
152*f6dc9357SAndroid Build Coastguard Worker   }
153*f6dc9357SAndroid Build Coastguard Worker 
GetCompressedSizeOfFolderCLzxInfo154*f6dc9357SAndroid Build Coastguard Worker   bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const
155*f6dc9357SAndroid Build Coastguard Worker   {
156*f6dc9357SAndroid Build Coastguard Worker     UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
157*f6dc9357SAndroid Build Coastguard Worker     return ResetTable.GetCompressedSizeOfBlocks(blockIndex, (UInt32)1 << ResetIntervalBits, size);
158*f6dc9357SAndroid Build Coastguard Worker   }
159*f6dc9357SAndroid Build Coastguard Worker };
160*f6dc9357SAndroid Build Coastguard Worker 
161*f6dc9357SAndroid Build Coastguard Worker 
162*f6dc9357SAndroid Build Coastguard Worker struct CMethodInfo
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker   Byte Guid[16];
165*f6dc9357SAndroid Build Coastguard Worker   // CByteBuffer ControlData;
166*f6dc9357SAndroid Build Coastguard Worker   CLzxInfo LzxInfo;
167*f6dc9357SAndroid Build Coastguard Worker 
168*f6dc9357SAndroid Build Coastguard Worker   bool IsLzx() const;
169*f6dc9357SAndroid Build Coastguard Worker   bool IsDes() const;
170*f6dc9357SAndroid Build Coastguard Worker   AString GetGuidString() const;
171*f6dc9357SAndroid Build Coastguard Worker   AString GetName() const;
172*f6dc9357SAndroid Build Coastguard Worker };
173*f6dc9357SAndroid Build Coastguard Worker 
174*f6dc9357SAndroid Build Coastguard Worker 
175*f6dc9357SAndroid Build Coastguard Worker struct CSectionInfo
176*f6dc9357SAndroid Build Coastguard Worker {
177*f6dc9357SAndroid Build Coastguard Worker   UInt64 Offset;
178*f6dc9357SAndroid Build Coastguard Worker   UInt64 CompressedSize;
179*f6dc9357SAndroid Build Coastguard Worker   UInt64 UncompressedSize;
180*f6dc9357SAndroid Build Coastguard Worker 
181*f6dc9357SAndroid Build Coastguard Worker   AString Name;
182*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CMethodInfo> Methods;
183*f6dc9357SAndroid Build Coastguard Worker 
184*f6dc9357SAndroid Build Coastguard Worker   bool IsLzx() const;
185*f6dc9357SAndroid Build Coastguard Worker   UString GetMethodName() const;
186*f6dc9357SAndroid Build Coastguard Worker };
187*f6dc9357SAndroid Build Coastguard Worker 
188*f6dc9357SAndroid Build Coastguard Worker class CFilesDatabase: public CDatabase
189*f6dc9357SAndroid Build Coastguard Worker {
190*f6dc9357SAndroid Build Coastguard Worker public:
191*f6dc9357SAndroid Build Coastguard Worker   CUIntVector Indices;
192*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CSectionInfo> Sections;
193*f6dc9357SAndroid Build Coastguard Worker   bool LowLevel;
194*f6dc9357SAndroid Build Coastguard Worker 
GetFileSize(unsigned fileIndex)195*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetFileSize(unsigned fileIndex) const { return Items[Indices[fileIndex]].Size; }
GetFileOffset(unsigned fileIndex)196*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetFileOffset(unsigned fileIndex) const { return Items[Indices[fileIndex]].Offset; }
197*f6dc9357SAndroid Build Coastguard Worker 
GetFolder(unsigned fileIndex)198*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetFolder(unsigned fileIndex) const
199*f6dc9357SAndroid Build Coastguard Worker   {
200*f6dc9357SAndroid Build Coastguard Worker     const CItem &item = Items[Indices[fileIndex]];
201*f6dc9357SAndroid Build Coastguard Worker     if (item.Section < Sections.Size())
202*f6dc9357SAndroid Build Coastguard Worker     {
203*f6dc9357SAndroid Build Coastguard Worker       const CSectionInfo &section = Sections[(unsigned)item.Section];
204*f6dc9357SAndroid Build Coastguard Worker       if (section.IsLzx())
205*f6dc9357SAndroid Build Coastguard Worker         return section.Methods[0].LzxInfo.GetFolder(item.Offset);
206*f6dc9357SAndroid Build Coastguard Worker     }
207*f6dc9357SAndroid Build Coastguard Worker     return 0;
208*f6dc9357SAndroid Build Coastguard Worker   }
209*f6dc9357SAndroid Build Coastguard Worker 
GetLastFolder(unsigned fileIndex)210*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetLastFolder(unsigned fileIndex) const
211*f6dc9357SAndroid Build Coastguard Worker   {
212*f6dc9357SAndroid Build Coastguard Worker     const CItem &item = Items[Indices[fileIndex]];
213*f6dc9357SAndroid Build Coastguard Worker     if (item.Section < Sections.Size())
214*f6dc9357SAndroid Build Coastguard Worker     {
215*f6dc9357SAndroid Build Coastguard Worker       const CSectionInfo &section = Sections[(unsigned)item.Section];
216*f6dc9357SAndroid Build Coastguard Worker       if (section.IsLzx())
217*f6dc9357SAndroid Build Coastguard Worker         return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1);
218*f6dc9357SAndroid Build Coastguard Worker     }
219*f6dc9357SAndroid Build Coastguard Worker     return 0;
220*f6dc9357SAndroid Build Coastguard Worker   }
221*f6dc9357SAndroid Build Coastguard Worker 
HighLevelClear()222*f6dc9357SAndroid Build Coastguard Worker   void HighLevelClear()
223*f6dc9357SAndroid Build Coastguard Worker   {
224*f6dc9357SAndroid Build Coastguard Worker     LowLevel = true;
225*f6dc9357SAndroid Build Coastguard Worker     Indices.Clear();
226*f6dc9357SAndroid Build Coastguard Worker     Sections.Clear();
227*f6dc9357SAndroid Build Coastguard Worker   }
228*f6dc9357SAndroid Build Coastguard Worker 
Clear()229*f6dc9357SAndroid Build Coastguard Worker   void Clear()
230*f6dc9357SAndroid Build Coastguard Worker   {
231*f6dc9357SAndroid Build Coastguard Worker     CDatabase::Clear();
232*f6dc9357SAndroid Build Coastguard Worker     HighLevelClear();
233*f6dc9357SAndroid Build Coastguard Worker   }
234*f6dc9357SAndroid Build Coastguard Worker 
235*f6dc9357SAndroid Build Coastguard Worker   void SetIndices();
236*f6dc9357SAndroid Build Coastguard Worker   void Sort();
237*f6dc9357SAndroid Build Coastguard Worker   bool Check();
238*f6dc9357SAndroid Build Coastguard Worker   bool CheckSectionRefs();
239*f6dc9357SAndroid Build Coastguard Worker };
240*f6dc9357SAndroid Build Coastguard Worker 
241*f6dc9357SAndroid Build Coastguard Worker 
242*f6dc9357SAndroid Build Coastguard Worker class CInArchive
243*f6dc9357SAndroid Build Coastguard Worker {
244*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> m_InStreamRef;
245*f6dc9357SAndroid Build Coastguard Worker   ::CInBuffer _inBuffer;
246*f6dc9357SAndroid Build Coastguard Worker   UInt64 _chunkSize;
247*f6dc9357SAndroid Build Coastguard Worker   bool _help2;
248*f6dc9357SAndroid Build Coastguard Worker 
249*f6dc9357SAndroid Build Coastguard Worker   Byte ReadByte();
250*f6dc9357SAndroid Build Coastguard Worker   void ReadBytes(Byte *data, UInt32 size);
251*f6dc9357SAndroid Build Coastguard Worker   void Skip(size_t size);
252*f6dc9357SAndroid Build Coastguard Worker   UInt16 ReadUInt16();
253*f6dc9357SAndroid Build Coastguard Worker   UInt32 ReadUInt32();
254*f6dc9357SAndroid Build Coastguard Worker   UInt64 ReadUInt64();
255*f6dc9357SAndroid Build Coastguard Worker   UInt64 ReadEncInt();
256*f6dc9357SAndroid Build Coastguard Worker   void ReadString(unsigned size, AString &s);
257*f6dc9357SAndroid Build Coastguard Worker   void ReadUString(unsigned size, UString &s);
258*f6dc9357SAndroid Build Coastguard Worker   void ReadGUID(Byte *g);
259*f6dc9357SAndroid Build Coastguard Worker 
260*f6dc9357SAndroid Build Coastguard Worker   HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size);
261*f6dc9357SAndroid Build Coastguard Worker 
262*f6dc9357SAndroid Build Coastguard Worker   HRESULT ReadDirEntry(CDatabase &database);
263*f6dc9357SAndroid Build Coastguard Worker   HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name);
264*f6dc9357SAndroid Build Coastguard Worker 
265*f6dc9357SAndroid Build Coastguard Worker public:
266*f6dc9357SAndroid Build Coastguard Worker   bool IsArc;
267*f6dc9357SAndroid Build Coastguard Worker   bool HeadersError;
268*f6dc9357SAndroid Build Coastguard Worker   bool UnexpectedEnd;
269*f6dc9357SAndroid Build Coastguard Worker   bool UnsupportedFeature;
270*f6dc9357SAndroid Build Coastguard Worker 
CInArchive(bool help2)271*f6dc9357SAndroid Build Coastguard Worker   CInArchive(bool help2) { _help2 = help2; }
272*f6dc9357SAndroid Build Coastguard Worker 
273*f6dc9357SAndroid Build Coastguard Worker   HRESULT OpenChm(IInStream *inStream, CDatabase &database);
274*f6dc9357SAndroid Build Coastguard Worker   HRESULT OpenHelp2(IInStream *inStream, CDatabase &database);
275*f6dc9357SAndroid Build Coastguard Worker   HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database);
276*f6dc9357SAndroid Build Coastguard Worker   HRESULT Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);
277*f6dc9357SAndroid Build Coastguard Worker   HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);
278*f6dc9357SAndroid Build Coastguard Worker };
279*f6dc9357SAndroid Build Coastguard Worker 
280*f6dc9357SAndroid Build Coastguard Worker }}
281*f6dc9357SAndroid Build Coastguard Worker 
282*f6dc9357SAndroid Build Coastguard Worker #endif
283