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 §ion = 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 §ion = 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