diff options
Diffstat (limited to '')
-rw-r--r-- | CPP/7zip/Archive/7z/7zUpdate.cpp | 307 |
1 files changed, 192 insertions, 115 deletions
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 4e9ea5d..d374a00 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp | |||
@@ -33,7 +33,7 @@ struct CFilterMode | |||
33 | UInt32 Id; | 33 | UInt32 Id; |
34 | UInt32 Delta; // required File Size alignment, if Id is not k_Delta. | 34 | UInt32 Delta; // required File Size alignment, if Id is not k_Delta. |
35 | // (Delta == 0) means unknown alignment | 35 | // (Delta == 0) means unknown alignment |
36 | UInt32 Offset; // for k_ARM64 | 36 | UInt32 Offset; // for k_ARM64 / k_RISCV |
37 | // UInt32 AlignSizeOpt; // for k_ARM64 | 37 | // UInt32 AlignSizeOpt; // for k_ARM64 |
38 | 38 | ||
39 | CFilterMode(): | 39 | CFilterMode(): |
@@ -59,7 +59,7 @@ struct CFilterMode | |||
59 | Delta = 16; | 59 | Delta = 16; |
60 | else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC) | 60 | else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC) |
61 | Delta = 4; | 61 | Delta = 4; |
62 | else if (Id == k_ARMT) | 62 | else if (Id == k_ARMT || Id == k_RISCV) |
63 | Delta = 2; | 63 | Delta = 2; |
64 | else if (Id == k_BCJ || Id == k_BCJ2) | 64 | else if (Id == k_BCJ || Id == k_BCJ2) |
65 | Delta = 1; // do we need it? | 65 | Delta = 1; // do we need it? |
@@ -95,7 +95,9 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
95 | return 0; | 95 | return 0; |
96 | p += 4; | 96 | p += 4; |
97 | 97 | ||
98 | switch (GetUi16(p)) | 98 | const unsigned machine = GetUi16(p); |
99 | |||
100 | switch (machine) | ||
99 | { | 101 | { |
100 | case 0x014C: | 102 | case 0x014C: |
101 | case 0x8664: filterId = k_X86; break; | 103 | case 0x8664: filterId = k_X86; break; |
@@ -112,11 +114,16 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
112 | case 0x01C2: filterId = k_ARM; break; // WinCE new | 114 | case 0x01C2: filterId = k_ARM; break; // WinCE new |
113 | case 0x01C4: filterId = k_ARMT; break; // WinRT | 115 | case 0x01C4: filterId = k_ARMT; break; // WinRT |
114 | 116 | ||
117 | case 0x5032: // RISCV32 | ||
118 | case 0x5064: // RISCV64 | ||
119 | // case 0x5128: // RISCV128 | ||
120 | filterId = k_RISCV; break; | ||
121 | |||
115 | case 0x0200: filterId = k_IA64; break; | 122 | case 0x0200: filterId = k_IA64; break; |
116 | default: return 0; | 123 | default: return 0; |
117 | } | 124 | } |
118 | 125 | ||
119 | // const UInt32 numSections = GetUi16(p + 2); | 126 | const UInt32 numSections = GetUi16(p + 2); |
120 | optHeaderSize = GetUi16(p + 16); | 127 | optHeaderSize = GetUi16(p + 16); |
121 | if (optHeaderSize > (1 << 10)) | 128 | if (optHeaderSize > (1 << 10)) |
122 | return 0; | 129 | return 0; |
@@ -132,34 +139,49 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
132 | return 0; | 139 | return 0; |
133 | } | 140 | } |
134 | 141 | ||
135 | /* | ||
136 | // Windows exe file sizes are not aligned for 4 KiB. | 142 | // Windows exe file sizes are not aligned for 4 KiB. |
137 | // So we can't use (CFilterMode::Offset != 0) in solid archives. | 143 | // So we can't use (CFilterMode::Offset != 0) in solid archives. |
138 | // So we just don't set Offset here. | 144 | // So we just don't set Offset here. |
139 | #define NUM_SCAN_SECTIONS_MAX (1 << 6) | 145 | #define NUM_SCAN_SECTIONS_MAX (1 << 6) |
140 | #define EXE_SECTION_OFFSET_MAX (1 << 27) | 146 | // #define EXE_SECTION_OFFSET_MAX (1 << 27) |
141 | #define EXE_SECTION_SIZE_MIN (1 << 8) | 147 | // #define EXE_SECTION_SIZE_MIN (1 << 8) |
142 | #define EXE_SECTION_SIZE_MAX (1 << 27) | 148 | // #define EXE_SECTION_SIZE_MAX (1 << 27) |
143 | #define PE_SectHeaderSize 40 | 149 | #define PE_SectHeaderSize 40 |
144 | #define PE_SECT_EXECUTE 0x20000000 | 150 | // #define PE_SECT_EXECUTE 0x20000000 |
145 | 151 | ||
152 | /* | ||
146 | if (numSections > NUM_SCAN_SECTIONS_MAX) | 153 | if (numSections > NUM_SCAN_SECTIONS_MAX) |
147 | return 0; | 154 | return 0; |
155 | */ | ||
148 | 156 | ||
157 | if ((size_t)(p - buf) + optHeaderSize <= size) | ||
158 | { | ||
149 | p += optHeaderSize; | 159 | p += optHeaderSize; |
160 | /* | ||
150 | // UInt32 numExeSections = 0; | 161 | // UInt32 numExeSections = 0; |
151 | // bool execute_finded = false; | 162 | // bool execute_finded = false; |
152 | // UInt32 sect_va = 0; | 163 | // UInt32 sect_va = 0; |
153 | // UInt32 sect_size = 0; | 164 | // UInt32 sect_size = 0; |
154 | // UInt32 sect_offset = 0; | 165 | // UInt32 sect_offset = 0; |
155 | 166 | */ | |
167 | if (numSections <= NUM_SCAN_SECTIONS_MAX) | ||
168 | if (machine == 0x8664) | ||
156 | for (UInt32 i = 0; i < numSections | 169 | for (UInt32 i = 0; i < numSections |
157 | // && numExeSections < numSectionsMax | ||
158 | ; i++, p += PE_SectHeaderSize) | 170 | ; i++, p += PE_SectHeaderSize) |
159 | { | 171 | { |
160 | UInt32 characts, rawSize, offset; | 172 | // UInt32 characts, rawSize, offset; |
161 | if ((UInt32)(p - buf) + PE_SectHeaderSize > size) | 173 | if ((UInt32)(p - buf) + PE_SectHeaderSize > size) |
162 | return 0; | 174 | { |
175 | // return 0; | ||
176 | break; | ||
177 | } | ||
178 | if (memcmp(p, ".a64xrm", 8) == 0) | ||
179 | { | ||
180 | // ARM64EC | ||
181 | filterId = k_ARM64; | ||
182 | break; | ||
183 | } | ||
184 | /* | ||
163 | rawSize = GetUi32(p + 16); | 185 | rawSize = GetUi32(p + 16); |
164 | offset = GetUi32(p + 20); | 186 | offset = GetUi32(p + 20); |
165 | characts = GetUi32(p + 36); | 187 | characts = GetUi32(p + 36); |
@@ -178,8 +200,11 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
178 | break; | 200 | break; |
179 | } | 201 | } |
180 | } | 202 | } |
203 | */ | ||
204 | } | ||
181 | } | 205 | } |
182 | 206 | ||
207 | /* | ||
183 | filterMode->Offset = 0; | 208 | filterMode->Offset = 0; |
184 | if (filterId == k_ARM64) | 209 | if (filterId == k_ARM64) |
185 | { | 210 | { |
@@ -243,8 +268,9 @@ static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode) | |||
243 | case 43: filterId = k_SPARC; break; | 268 | case 43: filterId = k_SPARC; break; |
244 | case 20: | 269 | case 20: |
245 | case 21: if (!be) return 0; filterId = k_PPC; break; | 270 | case 21: if (!be) return 0; filterId = k_PPC; break; |
246 | case 40: if ( be) return 0; filterId = k_ARM; break; | 271 | case 40: if (be) return 0; filterId = k_ARM; break; |
247 | case 183: if (be) return 0; filterId = k_ARM64; break; | 272 | case 183: if (be) return 0; filterId = k_ARM64; break; |
273 | case 243: if (be) return 0; filterId = k_RISCV; break; | ||
248 | 274 | ||
249 | /* Some IA-64 ELF executables have size that is not aligned for 16 bytes. | 275 | /* Some IA-64 ELF executables have size that is not aligned for 16 bytes. |
250 | So we don't use IA-64 filter for IA-64 ELF */ | 276 | So we don't use IA-64 filter for IA-64 ELF */ |
@@ -482,6 +508,7 @@ static inline bool IsExeFilter(CMethodId m) | |||
482 | switch (m) | 508 | switch (m) |
483 | { | 509 | { |
484 | case k_ARM64: | 510 | case k_ARM64: |
511 | case k_RISCV: | ||
485 | case k_BCJ: | 512 | case k_BCJ: |
486 | case k_BCJ2: | 513 | case k_BCJ2: |
487 | case k_ARM: | 514 | case k_ARM: |
@@ -490,6 +517,7 @@ static inline bool IsExeFilter(CMethodId m) | |||
490 | case k_SPARC: | 517 | case k_SPARC: |
491 | case k_IA64: | 518 | case k_IA64: |
492 | return true; | 519 | return true; |
520 | default: break; | ||
493 | } | 521 | } |
494 | return false; | 522 | return false; |
495 | } | 523 | } |
@@ -521,7 +549,8 @@ static unsigned Get_FilterGroup_for_Folder( | |||
521 | if (m.Id == k_BCJ2) | 549 | if (m.Id == k_BCJ2) |
522 | m.Id = k_BCJ; | 550 | m.Id = k_BCJ; |
523 | m.SetDelta(); | 551 | m.SetDelta(); |
524 | if (m.Id == k_ARM64) | 552 | if (m.Id == k_ARM64 || |
553 | m.Id == k_RISCV) | ||
525 | if (coder.Props.Size() == 4) | 554 | if (coder.Props.Size() == 4) |
526 | m.Offset = GetUi32(coder.Props); | 555 | m.Offset = GetUi32(coder.Props); |
527 | } | 556 | } |
@@ -537,15 +566,12 @@ static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream, | |||
537 | UInt64 position, UInt64 size, ICompressProgressInfo *progress) | 566 | UInt64 position, UInt64 size, ICompressProgressInfo *progress) |
538 | { | 567 | { |
539 | RINOK(InStream_SeekSet(inStream, position)) | 568 | RINOK(InStream_SeekSet(inStream, position)) |
540 | CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; | 569 | CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> streamSpec; |
541 | CMyComPtr<ISequentialInStream> inStreamLimited(streamSpec); | ||
542 | streamSpec->SetStream(inStream); | 570 | streamSpec->SetStream(inStream); |
543 | streamSpec->Init(size); | 571 | streamSpec->Init(size); |
544 | 572 | CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder; | |
545 | NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; | 573 | RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, progress)) |
546 | CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | 574 | return (copyCoder->TotalSize == size ? S_OK : E_FAIL); |
547 | RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress)) | ||
548 | return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL); | ||
549 | } | 575 | } |
550 | 576 | ||
551 | /* | 577 | /* |
@@ -759,9 +785,9 @@ struct CRefItem | |||
759 | { | 785 | { |
760 | if (sortByType) | 786 | if (sortByType) |
761 | { | 787 | { |
762 | int slashPos = ui.Name.ReverseFind_PathSepar(); | 788 | const int slashPos = ui.Name.ReverseFind_PathSepar(); |
763 | NamePos = (unsigned)(slashPos + 1); | 789 | NamePos = (unsigned)(slashPos + 1); |
764 | int dotPos = ui.Name.ReverseFind_Dot(); | 790 | const int dotPos = ui.Name.ReverseFind_Dot(); |
765 | if (dotPos <= slashPos) | 791 | if (dotPos <= slashPos) |
766 | ExtensionPos = ui.Name.Len(); | 792 | ExtensionPos = ui.Name.Len(); |
767 | else | 793 | else |
@@ -772,7 +798,7 @@ struct CRefItem | |||
772 | AString s; | 798 | AString s; |
773 | for (unsigned pos = ExtensionPos;; pos++) | 799 | for (unsigned pos = ExtensionPos;; pos++) |
774 | { | 800 | { |
775 | wchar_t c = ui.Name[pos]; | 801 | const wchar_t c = ui.Name[pos]; |
776 | if (c >= 0x80) | 802 | if (c >= 0x80) |
777 | break; | 803 | break; |
778 | if (c == 0) | 804 | if (c == 0) |
@@ -780,7 +806,7 @@ struct CRefItem | |||
780 | ExtensionIndex = GetExtIndex(s); | 806 | ExtensionIndex = GetExtIndex(s); |
781 | break; | 807 | break; |
782 | } | 808 | } |
783 | s += (char)MyCharLower_Ascii((char)c); | 809 | s.Add_Char((char)MyCharLower_Ascii((char)c)); |
784 | } | 810 | } |
785 | } | 811 | } |
786 | } | 812 | } |
@@ -1123,6 +1149,12 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo | |||
1123 | #ifdef MY_CPU_ARM64 | 1149 | #ifdef MY_CPU_ARM64 |
1124 | filterModeTemp.Id = k_ARM64; | 1150 | filterModeTemp.Id = k_ARM64; |
1125 | #endif | 1151 | #endif |
1152 | #ifdef MY_CPU_RISCV | ||
1153 | filterModeTemp.Id = k_RISCV; | ||
1154 | #endif | ||
1155 | #ifdef MY_CPU_SPARC | ||
1156 | filterModeTemp.Id = k_SPARC; | ||
1157 | #endif | ||
1126 | parseRes = true; | 1158 | parseRes = true; |
1127 | } | 1159 | } |
1128 | 1160 | ||
@@ -1172,6 +1204,8 @@ static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull | |||
1172 | m.NumStreams = numStreams; | 1204 | m.NumStreams = numStreams; |
1173 | } | 1205 | } |
1174 | 1206 | ||
1207 | |||
1208 | // we add bond for mode.Methods[0] that is filter | ||
1175 | static HRESULT AddBondForFilter(CCompressionMethodMode &mode) | 1209 | static HRESULT AddBondForFilter(CCompressionMethodMode &mode) |
1176 | { | 1210 | { |
1177 | for (unsigned c = 1; c < mode.Methods.Size(); c++) | 1211 | for (unsigned c = 1; c < mode.Methods.Size(); c++) |
@@ -1189,16 +1223,19 @@ static HRESULT AddBondForFilter(CCompressionMethodMode &mode) | |||
1189 | return E_INVALIDARG; | 1223 | return E_INVALIDARG; |
1190 | } | 1224 | } |
1191 | 1225 | ||
1192 | static HRESULT AddFilterBond(CCompressionMethodMode &mode) | 1226 | /* |
1227 | static HRESULT AddBondForFilter_if_ThereAreBonds(CCompressionMethodMode &mode) | ||
1193 | { | 1228 | { |
1194 | if (!mode.Bonds.IsEmpty()) | 1229 | if (!mode.Bonds.IsEmpty()) |
1195 | return AddBondForFilter(mode); | 1230 | return AddBondForFilter(mode); |
1196 | return S_OK; | 1231 | return S_OK; |
1197 | } | 1232 | } |
1233 | */ | ||
1198 | 1234 | ||
1199 | static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) | 1235 | static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) |
1200 | { | 1236 | { |
1201 | // mode.Methods[0] must be k_BCJ2 method ! | 1237 | // mode.Methods[0] must be k_BCJ2 method ! |
1238 | // mode.Methods[1] : we expect that there is at least one method after BCJ2 | ||
1202 | 1239 | ||
1203 | CMethodFull m; | 1240 | CMethodFull m; |
1204 | GetMethodFull(k_LZMA, 1, m); | 1241 | GetMethodFull(k_LZMA, 1, m); |
@@ -1210,7 +1247,7 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) | |||
1210 | m.AddProp32(NCoderPropID::kLitContextBits, 0); | 1247 | m.AddProp32(NCoderPropID::kLitContextBits, 0); |
1211 | // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2"); | 1248 | // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2"); |
1212 | 1249 | ||
1213 | unsigned methodIndex = mode.Methods.Size(); | 1250 | const unsigned methodIndex = mode.Methods.Size(); |
1214 | 1251 | ||
1215 | if (mode.Bonds.IsEmpty()) | 1252 | if (mode.Bonds.IsEmpty()) |
1216 | { | 1253 | { |
@@ -1229,109 +1266,140 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) | |||
1229 | 1266 | ||
1230 | RINOK(AddBondForFilter(mode)) | 1267 | RINOK(AddBondForFilter(mode)) |
1231 | CBond2 bond; | 1268 | CBond2 bond; |
1232 | bond.OutCoder = 0; | 1269 | bond.OutCoder = 0; // index of BCJ2 coder |
1233 | bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); | 1270 | bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); |
1234 | bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond); | 1271 | bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond); |
1235 | return S_OK; | 1272 | return S_OK; |
1236 | } | 1273 | } |
1237 | 1274 | ||
1275 | |||
1238 | static HRESULT MakeExeMethod(CCompressionMethodMode &mode, | 1276 | static HRESULT MakeExeMethod(CCompressionMethodMode &mode, |
1239 | const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter) | 1277 | const CFilterMode &filterMode, |
1278 | const bool bcj2_IsAllowed, | ||
1279 | const CUIntVector &disabledFilterIDs) | ||
1240 | { | 1280 | { |
1241 | if (mode.Filter_was_Inserted) | 1281 | if (mode.Filter_was_Inserted) |
1242 | { | 1282 | { |
1283 | // filter was inserted, but bond for that filter was not added still. | ||
1243 | const CMethodFull &m = mode.Methods[0]; | 1284 | const CMethodFull &m = mode.Methods[0]; |
1244 | const CMethodId id = m.Id; | 1285 | if (m.Id == k_BCJ2) |
1245 | if (id == k_BCJ2) | ||
1246 | return AddBcj2Methods(mode); | 1286 | return AddBcj2Methods(mode); |
1247 | if (!m.IsSimpleCoder()) | 1287 | if (!m.IsSimpleCoder()) |
1248 | return E_NOTIMPL; | 1288 | return E_NOTIMPL; |
1249 | // if (Bonds.IsEmpty()) we can create bonds later | 1289 | if (mode.Bonds.IsEmpty()) |
1250 | return AddFilterBond(mode); | 1290 | return S_OK; |
1291 | return AddBondForFilter(mode); | ||
1251 | } | 1292 | } |
1252 | 1293 | ||
1253 | if (filterMode.Id == 0) | 1294 | if (filterMode.Id == 0) |
1254 | return S_OK; | 1295 | return S_OK; |
1255 | 1296 | ||
1256 | CMethodFull &m = mode.Methods.InsertNew(0); | 1297 | unsigned nextCoder; |
1257 | 1298 | ||
1258 | { | 1299 | const bool useBcj2 = bcj2_IsAllowed |
1259 | FOR_VECTOR (k, mode.Bonds) | 1300 | && Is86Filter(filterMode.Id) |
1260 | { | 1301 | && disabledFilterIDs.FindInSorted(k_BCJ2) < 0; |
1261 | CBond2 &bond = mode.Bonds[k]; | ||
1262 | bond.InCoder++; | ||
1263 | bond.OutCoder++; | ||
1264 | } | ||
1265 | } | ||
1266 | 1302 | ||
1267 | HRESULT res; | 1303 | if (!useBcj2 && disabledFilterIDs.FindInSorted(filterMode.Id) >= 0) |
1268 | |||
1269 | if (bcj2Filter && Is86Filter(filterMode.Id)) | ||
1270 | { | 1304 | { |
1271 | GetMethodFull(k_BCJ2, 4, m); | 1305 | // required filter is disabled, |
1272 | res = AddBcj2Methods(mode); | 1306 | // but we still can use information about data alignment. |
1307 | #if 0 // 1 for debug | ||
1308 | // we can return here, if we want default lzma properties | ||
1309 | return S_OK; | ||
1310 | #else | ||
1311 | // we will try to change lzma/lzma2 properties | ||
1312 | nextCoder = 0; | ||
1313 | if (!mode.Bonds.IsEmpty()) | ||
1314 | for (unsigned c = 0;; c++) | ||
1315 | { | ||
1316 | if (c == mode.Methods.Size()) | ||
1317 | return S_OK; | ||
1318 | if (!mode.IsThereBond_to_Coder(c)) | ||
1319 | { | ||
1320 | nextCoder = c; | ||
1321 | break; | ||
1322 | } | ||
1323 | } | ||
1324 | #endif | ||
1273 | } | 1325 | } |
1274 | else | 1326 | else |
1275 | { | 1327 | { |
1328 | // we insert new filter method: | ||
1329 | CMethodFull &m = mode.Methods.InsertNew(0); // 0 == index of new inserted item | ||
1330 | { | ||
1331 | // we move all coder indexes in bonds up for 1 position: | ||
1332 | FOR_VECTOR (k, mode.Bonds) | ||
1333 | { | ||
1334 | CBond2 &bond = mode.Bonds[k]; | ||
1335 | bond.InCoder++; | ||
1336 | bond.OutCoder++; | ||
1337 | } | ||
1338 | } | ||
1339 | if (useBcj2) | ||
1340 | { | ||
1341 | GetMethodFull(k_BCJ2, 4, m); | ||
1342 | return AddBcj2Methods(mode); | ||
1343 | } | ||
1344 | |||
1276 | GetMethodFull(filterMode.Id, 1, m); | 1345 | GetMethodFull(filterMode.Id, 1, m); |
1346 | |||
1277 | if (filterMode.Id == k_Delta) | 1347 | if (filterMode.Id == k_Delta) |
1278 | m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); | 1348 | m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); |
1279 | else if (filterMode.Id == k_ARM64) | 1349 | else if (filterMode.Id == k_ARM64 |
1350 | || filterMode.Id == k_RISCV) | ||
1280 | { | 1351 | { |
1281 | // if (filterMode.Offset != 0) | 1352 | // if (filterMode.Offset != 0) |
1282 | m.AddProp32( | 1353 | m.AddProp32( |
1283 | NCoderPropID::kDefaultProp, | 1354 | NCoderPropID::kDefaultProp, |
1284 | // NCoderPropID::kBranchOffset, | 1355 | // NCoderPropID::kBranchOffset, |
1285 | filterMode.Offset); | 1356 | filterMode.Offset); |
1286 | } | 1357 | } |
1287 | res = AddFilterBond(mode); | 1358 | |
1288 | 1359 | nextCoder = 1; | |
1289 | int alignBits = -1; | 1360 | if (!mode.Bonds.IsEmpty()) |
1290 | { | 1361 | { |
1291 | const UInt32 delta = filterMode.Delta; | 1362 | RINOK(AddBondForFilter(mode)) |
1292 | if (delta == 0 || delta > 16) | 1363 | nextCoder = mode.Bonds.Back().InCoder; |
1293 | { | ||
1294 | // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id); | ||
1295 | } | ||
1296 | else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4; | ||
1297 | else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3; | ||
1298 | else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2; | ||
1299 | else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1; | ||
1300 | // else alignBits = 0; | ||
1301 | /* alignBits=0 is default mode for lzma/lzma2. | ||
1302 | So we don't set alignBits=0 here. */ | ||
1303 | } | 1364 | } |
1304 | if (res == S_OK && alignBits > 0) | 1365 | } |
1366 | |||
1367 | if (nextCoder >= mode.Methods.Size()) | ||
1368 | { | ||
1369 | // we don't expect that case, if there was non-filter method. | ||
1370 | // but we return S_OK to support filter-only case. | ||
1371 | return S_OK; | ||
1372 | } | ||
1373 | |||
1374 | int alignBits = -1; | ||
1375 | { | ||
1376 | const UInt32 delta = filterMode.Delta; | ||
1377 | if (delta == 0 || delta > 16) | ||
1305 | { | 1378 | { |
1306 | unsigned nextCoder = 1; | 1379 | // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id); |
1307 | if (!mode.Bonds.IsEmpty()) | ||
1308 | { | ||
1309 | nextCoder = mode.Bonds.Back().InCoder; | ||
1310 | } | ||
1311 | if (nextCoder < mode.Methods.Size()) | ||
1312 | { | ||
1313 | CMethodFull &nextMethod = mode.Methods[nextCoder]; | ||
1314 | if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2) | ||
1315 | { | ||
1316 | if (!nextMethod.Are_Lzma_Model_Props_Defined()) | ||
1317 | { | ||
1318 | if (alignBits != 0) | ||
1319 | { | ||
1320 | if (alignBits > 2 || filterMode.Id == k_Delta) | ||
1321 | nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits); | ||
1322 | unsigned lc = 0; | ||
1323 | if (alignBits < 3) | ||
1324 | lc = (unsigned)(3 - alignBits); | ||
1325 | nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc); | ||
1326 | nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits); | ||
1327 | } | ||
1328 | } | ||
1329 | } | ||
1330 | } | ||
1331 | } | 1380 | } |
1381 | else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4; | ||
1382 | else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3; | ||
1383 | else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2; | ||
1384 | else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1; | ||
1385 | // else alignBits = 0; | ||
1386 | /* alignBits=0 is default mode for lzma/lzma2. | ||
1387 | So we don't set alignBits=0 here. */ | ||
1332 | } | 1388 | } |
1333 | 1389 | if (alignBits <= 0) | |
1334 | return res; | 1390 | return S_OK; |
1391 | // (alignBits > 0) | ||
1392 | CMethodFull &nextMethod = mode.Methods[nextCoder]; | ||
1393 | if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2) | ||
1394 | if (!nextMethod.Are_Lzma_Model_Props_Defined()) | ||
1395 | { | ||
1396 | if (alignBits > 2 || filterMode.Id == k_Delta) | ||
1397 | nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits); | ||
1398 | const unsigned lc = (alignBits < 3) ? (unsigned)(3 - alignBits) : 0u; | ||
1399 | nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc); | ||
1400 | nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits); | ||
1401 | } | ||
1402 | return S_OK; | ||
1335 | } | 1403 | } |
1336 | 1404 | ||
1337 | 1405 | ||
@@ -1859,6 +1927,7 @@ HRESULT Update( | |||
1859 | 1927 | ||
1860 | CIntArr fileIndexToUpdateIndexMap; | 1928 | CIntArr fileIndexToUpdateIndexMap; |
1861 | UInt64 complexity = 0; | 1929 | UInt64 complexity = 0; |
1930 | bool isThere_UnknownSize = false; | ||
1862 | UInt64 inSizeForReduce2 = 0; | 1931 | UInt64 inSizeForReduce2 = 0; |
1863 | 1932 | ||
1864 | #ifndef Z7_NO_CRYPTO | 1933 | #ifndef Z7_NO_CRYPTO |
@@ -1971,28 +2040,36 @@ HRESULT Update( | |||
1971 | 2040 | ||
1972 | UInt64 inSizeForReduce = 0; | 2041 | UInt64 inSizeForReduce = 0; |
1973 | { | 2042 | { |
1974 | bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0); | 2043 | const bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0); |
1975 | FOR_VECTOR (i, updateItems) | 2044 | FOR_VECTOR (i, updateItems) |
1976 | { | 2045 | { |
1977 | const CUpdateItem &ui = updateItems[i]; | 2046 | const CUpdateItem &ui = updateItems[i]; |
1978 | if (ui.NewData) | 2047 | if (ui.NewData) |
1979 | { | 2048 | { |
1980 | complexity += ui.Size; | 2049 | if (ui.Size == (UInt64)(Int64)-1) |
1981 | if (isSolid) | 2050 | isThere_UnknownSize = true; |
1982 | inSizeForReduce += ui.Size; | 2051 | else |
1983 | else if (inSizeForReduce < ui.Size) | 2052 | { |
1984 | inSizeForReduce = ui.Size; | 2053 | complexity += ui.Size; |
2054 | if (isSolid) | ||
2055 | inSizeForReduce += ui.Size; | ||
2056 | else if (inSizeForReduce < ui.Size) | ||
2057 | inSizeForReduce = ui.Size; | ||
2058 | } | ||
1985 | } | 2059 | } |
1986 | } | 2060 | } |
1987 | } | 2061 | } |
1988 | 2062 | ||
2063 | if (isThere_UnknownSize) | ||
2064 | inSizeForReduce = (UInt64)(Int64)-1; | ||
2065 | else | ||
2066 | RINOK(updateCallback->SetTotal(complexity)) | ||
2067 | |||
1989 | if (inSizeForReduce < inSizeForReduce2) | 2068 | if (inSizeForReduce < inSizeForReduce2) |
1990 | inSizeForReduce = inSizeForReduce2; | 2069 | inSizeForReduce = inSizeForReduce2; |
1991 | 2070 | ||
1992 | RINOK(updateCallback->SetTotal(complexity)) | ||
1993 | 2071 | ||
1994 | CLocalProgress *lps = new CLocalProgress; | 2072 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; |
1995 | CMyComPtr<ICompressProgressInfo> progress = lps; | ||
1996 | lps->Init(updateCallback, true); | 2073 | lps->Init(updateCallback, true); |
1997 | 2074 | ||
1998 | #ifndef Z7_ST | 2075 | #ifndef Z7_ST |
@@ -2232,12 +2309,13 @@ HRESULT Update( | |||
2232 | CCompressionMethodMode method = *options.Method; | 2309 | CCompressionMethodMode method = *options.Method; |
2233 | { | 2310 | { |
2234 | const HRESULT res = MakeExeMethod(method, filterMode, | 2311 | const HRESULT res = MakeExeMethod(method, filterMode, |
2312 | // bcj2_IsAllowed: | ||
2235 | #ifdef Z7_ST | 2313 | #ifdef Z7_ST |
2236 | false | 2314 | false |
2237 | #else | 2315 | #else |
2238 | options.MaxFilter && options.MultiThreadMixer | 2316 | options.MaxFilter && options.MultiThreadMixer |
2239 | #endif | 2317 | #endif |
2240 | ); | 2318 | , options.DisabledFilterIDs); |
2241 | 2319 | ||
2242 | RINOK(res) | 2320 | RINOK(res) |
2243 | } | 2321 | } |
@@ -2299,7 +2377,7 @@ HRESULT Update( | |||
2299 | 2377 | ||
2300 | const UInt64 packSize = db->GetFolderFullPackSize(folderIndex); | 2378 | const UInt64 packSize = db->GetFolderFullPackSize(folderIndex); |
2301 | RINOK(WriteRange(inStream, archive.SeqStream, | 2379 | RINOK(WriteRange(inStream, archive.SeqStream, |
2302 | db->GetFolderStreamPos(folderIndex, 0), packSize, progress)) | 2380 | db->GetFolderStreamPos(folderIndex, 0), packSize, lps)) |
2303 | lps->ProgressOffset += packSize; | 2381 | lps->ProgressOffset += packSize; |
2304 | 2382 | ||
2305 | const unsigned folderIndex_New = newDatabase.Folders.Size(); | 2383 | const unsigned folderIndex_New = newDatabase.Folders.Size(); |
@@ -2321,7 +2399,7 @@ HRESULT Update( | |||
2321 | size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; | 2399 | size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; |
2322 | const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; | 2400 | const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; |
2323 | for (; indexStart < indexEnd; indexStart++) | 2401 | for (; indexStart < indexEnd; indexStart++) |
2324 | newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); | 2402 | newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes.ConstData()[indexStart]); |
2325 | } | 2403 | } |
2326 | else | 2404 | else |
2327 | { | 2405 | { |
@@ -2481,7 +2559,7 @@ HRESULT Update( | |||
2481 | sizeToEncode, // expectedDataSize | 2559 | sizeToEncode, // expectedDataSize |
2482 | newDatabase.Folders.AddNew(), | 2560 | newDatabase.Folders.AddNew(), |
2483 | // newDatabase.CoderUnpackSizes, curUnpackSize, | 2561 | // newDatabase.CoderUnpackSizes, curUnpackSize, |
2484 | archive.SeqStream, newDatabase.PackSizes, progress); | 2562 | archive.SeqStream, newDatabase.PackSizes, lps); |
2485 | 2563 | ||
2486 | if (encodeRes == k_My_HRESULT_CRC_ERROR) | 2564 | if (encodeRes == k_My_HRESULT_CRC_ERROR) |
2487 | return E_FAIL; | 2565 | return E_FAIL; |
@@ -2680,8 +2758,7 @@ HRESULT Update( | |||
2680 | */ | 2758 | */ |
2681 | 2759 | ||
2682 | 2760 | ||
2683 | CFolderInStream *inStreamSpec = new CFolderInStream; | 2761 | CMyComPtr2_Create<ISequentialInStream, CFolderInStream> inStreamSpec; // solidInStream; |
2684 | CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec); | ||
2685 | 2762 | ||
2686 | // inStreamSpec->_reportArcProp = reportArcProp; | 2763 | // inStreamSpec->_reportArcProp = reportArcProp; |
2687 | 2764 | ||
@@ -2702,13 +2779,13 @@ HRESULT Update( | |||
2702 | 2779 | ||
2703 | RINOK(encoder.Encode1( | 2780 | RINOK(encoder.Encode1( |
2704 | EXTERNAL_CODECS_LOC_VARS | 2781 | EXTERNAL_CODECS_LOC_VARS |
2705 | solidInStream, | 2782 | inStreamSpec, |
2706 | // NULL, | 2783 | // NULL, |
2707 | &inSizeForReduce, | 2784 | &inSizeForReduce, |
2708 | expectedDataSize, // expected size | 2785 | expectedDataSize, // expected size |
2709 | newDatabase.Folders.AddNew(), | 2786 | newDatabase.Folders.AddNew(), |
2710 | // newDatabase.CoderUnpackSizes, curFolderUnpackSize, | 2787 | // newDatabase.CoderUnpackSizes, curFolderUnpackSize, |
2711 | archive.SeqStream, newDatabase.PackSizes, progress)) | 2788 | archive.SeqStream, newDatabase.PackSizes, lps)) |
2712 | 2789 | ||
2713 | if (!inStreamSpec->WasFinished()) | 2790 | if (!inStreamSpec->WasFinished()) |
2714 | return E_FAIL; | 2791 | return E_FAIL; |
@@ -2970,7 +3047,7 @@ HRESULT Update( | |||
2970 | if (newDatabase.NumUnpackStreamsVector.Size() != numFolders | 3047 | if (newDatabase.NumUnpackStreamsVector.Size() != numFolders |
2971 | || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders) | 3048 | || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders) |
2972 | return E_FAIL; | 3049 | return E_FAIL; |
2973 | newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResedue_with_false(numFolders); | 3050 | newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResidue_with_false(numFolders); |
2974 | } | 3051 | } |
2975 | 3052 | ||
2976 | updateItems.ClearAndFree(); | 3053 | updateItems.ClearAndFree(); |