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