diff options
Diffstat (limited to '')
-rw-r--r-- | CPP/7zip/Archive/IhexHandler.cpp | 162 |
1 files changed, 81 insertions, 81 deletions
diff --git a/CPP/7zip/Archive/IhexHandler.cpp b/CPP/7zip/Archive/IhexHandler.cpp index badb559..98ca0a3 100644 --- a/CPP/7zip/Archive/IhexHandler.cpp +++ b/CPP/7zip/Archive/IhexHandler.cpp | |||
@@ -7,14 +7,14 @@ | |||
7 | #include "../../Common/ComTry.h" | 7 | #include "../../Common/ComTry.h" |
8 | #include "../../Common/DynamicBuffer.h" | 8 | #include "../../Common/DynamicBuffer.h" |
9 | #include "../../Common/IntToString.h" | 9 | #include "../../Common/IntToString.h" |
10 | #include "../../Common/MyVector.h" | 10 | #include "../../Common/StringToInt.h" |
11 | 11 | ||
12 | #include "../../Windows/PropVariant.h" | 12 | #include "../../Windows/PropVariant.h" |
13 | 13 | ||
14 | #include "../Common/InBuffer.h" | ||
14 | #include "../Common/ProgressUtils.h" | 15 | #include "../Common/ProgressUtils.h" |
15 | #include "../Common/RegisterArc.h" | 16 | #include "../Common/RegisterArc.h" |
16 | #include "../Common/StreamUtils.h" | 17 | #include "../Common/StreamUtils.h" |
17 | #include "../Common/InBuffer.h" | ||
18 | 18 | ||
19 | namespace NArchive { | 19 | namespace NArchive { |
20 | namespace NIhex { | 20 | namespace NIhex { |
@@ -68,6 +68,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
68 | if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; | 68 | if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; |
69 | if (_dataError) v |= kpv_ErrorFlags_DataError; | 69 | if (_dataError) v |= kpv_ErrorFlags_DataError; |
70 | prop = v; | 70 | prop = v; |
71 | break; | ||
71 | } | 72 | } |
72 | } | 73 | } |
73 | prop.Detach(value); | 74 | prop.Detach(value); |
@@ -99,19 +100,12 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
99 | COM_TRY_END | 100 | COM_TRY_END |
100 | } | 101 | } |
101 | 102 | ||
102 | static inline int HexToByte(unsigned c) | ||
103 | { | ||
104 | if (c >= '0' && c <= '9') return (int)(c - '0'); | ||
105 | if (c >= 'A' && c <= 'F') return (int)(c - 'A' + 10); | ||
106 | if (c >= 'a' && c <= 'f') return (int)(c - 'a' + 10); | ||
107 | return -1; | ||
108 | } | ||
109 | 103 | ||
110 | static int Parse(const Byte *p) | 104 | static int Parse(const Byte *p) |
111 | { | 105 | { |
112 | const int c1 = HexToByte(p[0]); if (c1 < 0) return -1; | 106 | unsigned v0 = p[0]; Z7_PARSE_HEX_DIGIT(v0, return -1;) |
113 | const int c2 = HexToByte(p[1]); if (c2 < 0) return -1; | 107 | unsigned v1 = p[1]; Z7_PARSE_HEX_DIGIT(v1, return -1;) |
114 | return (c1 << 4) | c2; | 108 | return (int)((v0 << 4) | v1); |
115 | } | 109 | } |
116 | 110 | ||
117 | #define kType_Data 0 | 111 | #define kType_Data 0 |
@@ -123,7 +117,11 @@ static int Parse(const Byte *p) | |||
123 | 117 | ||
124 | #define kType_MAX 5 | 118 | #define kType_MAX 5 |
125 | 119 | ||
126 | #define IS_LINE_DELIMITER(c) ((c) == 0 || (c) == 10 || (c) == 13) | 120 | // we don't want to read files with big number of spaces between records |
121 | // it's our limitation (out of specification): | ||
122 | static const unsigned k_NumSpaces_LIMIT = 16 + 1; | ||
123 | |||
124 | #define IS_LINE_DELIMITER(c) (/* (c) == 0 || */ (c) == 10 || (c) == 13) | ||
127 | 125 | ||
128 | API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size) | 126 | API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size) |
129 | { | 127 | { |
@@ -141,11 +139,11 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size) | |||
141 | if (size < 4 * 2) | 139 | if (size < 4 * 2) |
142 | return k_IsArc_Res_NEED_MORE; | 140 | return k_IsArc_Res_NEED_MORE; |
143 | 141 | ||
144 | int num = Parse(p); | 142 | const int num = Parse(p); |
145 | if (num < 0) | 143 | if (num < 0) |
146 | return k_IsArc_Res_NO; | 144 | return k_IsArc_Res_NO; |
147 | 145 | ||
148 | int type = Parse(p + 6); | 146 | const int type = Parse(p + 6); |
149 | if (type < 0 || type > kType_MAX) | 147 | if (type < 0 || type > kType_MAX) |
150 | return k_IsArc_Res_NO; | 148 | return k_IsArc_Res_NO; |
151 | 149 | ||
@@ -162,7 +160,7 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size) | |||
162 | sum += (unsigned)v; | 160 | sum += (unsigned)v; |
163 | } | 161 | } |
164 | 162 | ||
165 | if ((sum & 0xFF) != 0) | 163 | if (sum & 0xFF) |
166 | return k_IsArc_Res_NO; | 164 | return k_IsArc_Res_NO; |
167 | 165 | ||
168 | if (type == kType_Data) | 166 | if (type == kType_Data) |
@@ -199,17 +197,17 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size) | |||
199 | p += numChars; | 197 | p += numChars; |
200 | size -= numChars; | 198 | size -= numChars; |
201 | 199 | ||
200 | unsigned numSpaces = k_NumSpaces_LIMIT; | ||
202 | for (;;) | 201 | for (;;) |
203 | { | 202 | { |
204 | if (size == 0) | 203 | if (size == 0) |
205 | return k_IsArc_Res_NEED_MORE; | 204 | return k_IsArc_Res_NEED_MORE; |
206 | const Byte b = *p++; | 205 | const Byte b = *p++; |
207 | size--; | 206 | size--; |
208 | if (IS_LINE_DELIMITER(b)) | ||
209 | continue; | ||
210 | if (b == ':') | 207 | if (b == ':') |
211 | break; | 208 | break; |
212 | return k_IsArc_Res_NO; | 209 | if (--numSpaces == 0 || !IS_LINE_DELIMITER(b)) |
210 | return k_IsArc_Res_NO; | ||
213 | } | 211 | } |
214 | } | 212 | } |
215 | 213 | ||
@@ -217,7 +215,7 @@ API_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size) | |||
217 | } | 215 | } |
218 | } | 216 | } |
219 | 217 | ||
220 | Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *)) | 218 | Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback)) |
221 | { | 219 | { |
222 | COM_TRY_BEGIN | 220 | COM_TRY_BEGIN |
223 | { | 221 | { |
@@ -229,7 +227,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
229 | { | 227 | { |
230 | size_t size = kStartSize; | 228 | size_t size = kStartSize; |
231 | RINOK(ReadStream(stream, temp, &size)) | 229 | RINOK(ReadStream(stream, temp, &size)) |
232 | UInt32 isArcRes = IsArc_Ihex(temp, size); | 230 | const UInt32 isArcRes = IsArc_Ihex(temp, size); |
233 | if (isArcRes == k_IsArc_Res_NO) | 231 | if (isArcRes == k_IsArc_Res_NO) |
234 | return S_FALSE; | 232 | return S_FALSE; |
235 | if (isArcRes == k_IsArc_Res_NEED_MORE && size != kStartSize) | 233 | if (isArcRes == k_IsArc_Res_NEED_MORE && size != kStartSize) |
@@ -243,7 +241,6 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
243 | return E_OUTOFMEMORY; | 241 | return E_OUTOFMEMORY; |
244 | s.SetStream(stream); | 242 | s.SetStream(stream); |
245 | s.Init(); | 243 | s.Init(); |
246 | |||
247 | { | 244 | { |
248 | Byte b; | 245 | Byte b; |
249 | if (!s.ReadByte(b)) | 246 | if (!s.ReadByte(b)) |
@@ -259,6 +256,8 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
259 | } | 256 | } |
260 | 257 | ||
261 | UInt32 globalOffset = 0; | 258 | UInt32 globalOffset = 0; |
259 | const UInt32 k_progressStep = 1 << 24; | ||
260 | UInt64 progressNext = k_progressStep; | ||
262 | 261 | ||
263 | for (;;) | 262 | for (;;) |
264 | { | 263 | { |
@@ -273,16 +272,14 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
273 | _dataError = true; | 272 | _dataError = true; |
274 | return S_FALSE; | 273 | return S_FALSE; |
275 | } | 274 | } |
276 | |||
277 | { | 275 | { |
278 | size_t numPairs = ((unsigned)num + 4); | 276 | const size_t numPairs = (unsigned)num + 4; |
279 | size_t numBytes = numPairs * 2; | 277 | const size_t numBytes = numPairs * 2; |
280 | if (s.ReadBytes(temp, numBytes) != numBytes) | 278 | if (s.ReadBytes(temp, numBytes) != numBytes) |
281 | { | 279 | { |
282 | _needMoreInput = true; | 280 | _needMoreInput = true; |
283 | return S_FALSE; | 281 | return S_FALSE; |
284 | } | 282 | } |
285 | |||
286 | unsigned sum = (unsigned)num; | 283 | unsigned sum = (unsigned)num; |
287 | for (size_t i = 0; i < numPairs; i++) | 284 | for (size_t i = 0; i < numPairs; i++) |
288 | { | 285 | { |
@@ -295,21 +292,21 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
295 | temp[i] = (Byte)a; | 292 | temp[i] = (Byte)a; |
296 | sum += (unsigned)a; | 293 | sum += (unsigned)a; |
297 | } | 294 | } |
298 | if ((sum & 0xFF) != 0) | 295 | if (sum & 0xFF) |
299 | { | 296 | { |
300 | _dataError = true; | 297 | _dataError = true; |
301 | return S_FALSE; | 298 | return S_FALSE; |
302 | } | 299 | } |
303 | } | 300 | } |
304 | 301 | ||
305 | unsigned type = temp[2]; | 302 | const unsigned type = temp[2]; |
306 | if (type > kType_MAX) | 303 | if (type > kType_MAX) |
307 | { | 304 | { |
308 | _dataError = true; | 305 | _dataError = true; |
309 | return S_FALSE; | 306 | return S_FALSE; |
310 | } | 307 | } |
311 | 308 | ||
312 | UInt32 a = GetBe16(temp); | 309 | const UInt32 a = GetBe16(temp); |
313 | 310 | ||
314 | if (type == kType_Data) | 311 | if (type == kType_Data) |
315 | { | 312 | { |
@@ -322,7 +319,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
322 | } | 319 | } |
323 | // if (num != 0) | 320 | // if (num != 0) |
324 | { | 321 | { |
325 | UInt32 offs = globalOffset + a; | 322 | const UInt32 offs = globalOffset + a; |
326 | CBlock *block = NULL; | 323 | CBlock *block = NULL; |
327 | if (!_blocks.IsEmpty()) | 324 | if (!_blocks.IsEmpty()) |
328 | { | 325 | { |
@@ -338,10 +335,21 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
338 | block->Data.AddData(temp + 3, (unsigned)num); | 335 | block->Data.AddData(temp + 3, (unsigned)num); |
339 | } | 336 | } |
340 | } | 337 | } |
341 | else if (type == kType_Eof) | 338 | else |
342 | { | 339 | { |
343 | _phySize = s.GetProcessedSize(); | 340 | if (a != 0) // from description: the address field is typically 0. |
344 | { | 341 | { |
342 | _dataError = true; | ||
343 | return S_FALSE; | ||
344 | } | ||
345 | if (type == kType_Eof) | ||
346 | { | ||
347 | if (num != 0) | ||
348 | { | ||
349 | _dataError = true; | ||
350 | return S_FALSE; | ||
351 | } | ||
352 | _phySize = s.GetProcessedSize(); | ||
345 | Byte b; | 353 | Byte b; |
346 | if (s.ReadByte(b)) | 354 | if (s.ReadByte(b)) |
347 | { | 355 | { |
@@ -357,16 +365,9 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
357 | } | 365 | } |
358 | } | 366 | } |
359 | } | 367 | } |
368 | return S_OK; | ||
360 | } | 369 | } |
361 | return S_OK; | 370 | |
362 | } | ||
363 | else | ||
364 | { | ||
365 | if (a != 0) | ||
366 | { | ||
367 | _dataError = true; | ||
368 | return S_FALSE; | ||
369 | } | ||
370 | if (type == kType_Seg || type == kType_High) | 371 | if (type == kType_Seg || type == kType_High) |
371 | { | 372 | { |
372 | if (num != 2) | 373 | if (num != 2) |
@@ -374,8 +375,8 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
374 | _dataError = true; | 375 | _dataError = true; |
375 | return S_FALSE; | 376 | return S_FALSE; |
376 | } | 377 | } |
377 | UInt32 d = GetBe16(temp + 3); | 378 | // here we use optimization trick for num shift calculation: (type == kType_Seg ? 4 : 16) |
378 | globalOffset = d << (type == kType_Seg ? 4 : 16); | 379 | globalOffset = (UInt32)GetBe16(temp + 3) << (1u << type); |
379 | } | 380 | } |
380 | else | 381 | else |
381 | { | 382 | { |
@@ -387,6 +388,18 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
387 | } | 388 | } |
388 | } | 389 | } |
389 | 390 | ||
391 | if (openCallback) | ||
392 | { | ||
393 | const UInt64 processed = s.GetProcessedSize(); | ||
394 | if (processed >= progressNext) | ||
395 | { | ||
396 | progressNext = processed + k_progressStep; | ||
397 | const UInt64 numFiles = _blocks.Size(); | ||
398 | RINOK(openCallback->SetCompleted(&numFiles, &processed)) | ||
399 | } | ||
400 | } | ||
401 | |||
402 | unsigned numSpaces = k_NumSpaces_LIMIT; | ||
390 | for (;;) | 403 | for (;;) |
391 | { | 404 | { |
392 | Byte b; | 405 | Byte b; |
@@ -395,12 +408,13 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
395 | _needMoreInput = true; | 408 | _needMoreInput = true; |
396 | return S_FALSE; | 409 | return S_FALSE; |
397 | } | 410 | } |
398 | if (IS_LINE_DELIMITER(b)) | ||
399 | continue; | ||
400 | if (b == ':') | 411 | if (b == ':') |
401 | break; | 412 | break; |
402 | _dataError = true; | 413 | if (--numSpaces == 0 || !IS_LINE_DELIMITER(b)) |
403 | return S_FALSE; | 414 | { |
415 | _dataError = true; | ||
416 | return S_FALSE; | ||
417 | } | ||
404 | } | 418 | } |
405 | } | 419 | } |
406 | } | 420 | } |
@@ -409,14 +423,13 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb | |||
409 | COM_TRY_END | 423 | COM_TRY_END |
410 | } | 424 | } |
411 | 425 | ||
426 | |||
412 | Z7_COM7F_IMF(CHandler::Close()) | 427 | Z7_COM7F_IMF(CHandler::Close()) |
413 | { | 428 | { |
414 | _phySize = 0; | 429 | _phySize = 0; |
415 | |||
416 | _isArc = false; | 430 | _isArc = false; |
417 | _needMoreInput = false; | 431 | _needMoreInput = false; |
418 | _dataError = false; | 432 | _dataError = false; |
419 | |||
420 | _blocks.Clear(); | 433 | _blocks.Clear(); |
421 | return S_OK; | 434 | return S_OK; |
422 | } | 435 | } |
@@ -436,53 +449,40 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
436 | UInt32 i; | 449 | UInt32 i; |
437 | for (i = 0; i < numItems; i++) | 450 | for (i = 0; i < numItems; i++) |
438 | totalSize += _blocks[allFilesMode ? i : indices[i]].Data.GetPos(); | 451 | totalSize += _blocks[allFilesMode ? i : indices[i]].Data.GetPos(); |
439 | extractCallback->SetTotal(totalSize); | 452 | RINOK(extractCallback->SetTotal(totalSize)) |
440 | |||
441 | UInt64 currentTotalSize = 0; | ||
442 | UInt64 currentItemSize; | ||
443 | 453 | ||
444 | CLocalProgress *lps = new CLocalProgress; | 454 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; |
445 | CMyComPtr<ICompressProgressInfo> progress = lps; | ||
446 | lps->Init(extractCallback, false); | 455 | lps->Init(extractCallback, false); |
447 | 456 | ||
448 | for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) | 457 | for (i = 0;; i++) |
449 | { | 458 | { |
450 | currentItemSize = 0; | 459 | lps->InSize = lps->OutSize; |
451 | lps->InSize = lps->OutSize = currentTotalSize; | ||
452 | RINOK(lps->SetCur()) | 460 | RINOK(lps->SetCur()) |
453 | 461 | if (i >= numItems) | |
462 | break; | ||
454 | const UInt32 index = allFilesMode ? i : indices[i]; | 463 | const UInt32 index = allFilesMode ? i : indices[i]; |
455 | const CByteDynamicBuffer &data = _blocks[index].Data; | 464 | const CByteDynamicBuffer &data = _blocks[index].Data; |
456 | currentItemSize = data.GetPos(); | 465 | lps->OutSize += data.GetPos(); |
457 | |||
458 | CMyComPtr<ISequentialOutStream> realOutStream; | ||
459 | const Int32 askMode = testMode ? | ||
460 | NExtract::NAskMode::kTest : | ||
461 | NExtract::NAskMode::kExtract; | ||
462 | |||
463 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) | ||
464 | |||
465 | if (!testMode && !realOutStream) | ||
466 | continue; | ||
467 | |||
468 | extractCallback->PrepareOperation(askMode); | ||
469 | |||
470 | if (realOutStream) | ||
471 | { | 466 | { |
472 | RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetPos())) | 467 | CMyComPtr<ISequentialOutStream> realOutStream; |
468 | const Int32 askMode = testMode ? | ||
469 | NExtract::NAskMode::kTest : | ||
470 | NExtract::NAskMode::kExtract; | ||
471 | RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) | ||
472 | if (!testMode && !realOutStream) | ||
473 | continue; | ||
474 | RINOK(extractCallback->PrepareOperation(askMode)) | ||
475 | if (realOutStream) | ||
476 | RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetPos())) | ||
473 | } | 477 | } |
474 | |||
475 | realOutStream.Release(); | ||
476 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) | 478 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) |
477 | } | 479 | } |
478 | 480 | ||
479 | lps->InSize = lps->OutSize = currentTotalSize; | 481 | return S_OK; |
480 | return lps->SetCur(); | ||
481 | |||
482 | COM_TRY_END | 482 | COM_TRY_END |
483 | } | 483 | } |
484 | 484 | ||
485 | // k_Signature: { ':', '1' } | 485 | // k_Signature: { ':' } |
486 | 486 | ||
487 | REGISTER_ARC_I_NO_SIG( | 487 | REGISTER_ARC_I_NO_SIG( |
488 | "IHex", "ihex", NULL, 0xCD, | 488 | "IHex", "ihex", NULL, 0xCD, |